From ee490fb84ef7902007cfebbe85be28453e2967f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Tue, 29 Aug 2023 09:40:28 +0500 Subject: [PATCH 01/23] =?UTF-8?q?=E2=9C=A8=20Add=20command=20line.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI/Controls/Copyright.cs | 2 +- src/TUI/Controls/Dashboard.cs | 44 ++++++++--------- src/TUI/Controls/Display.cs | 36 +++++++++++--- src/TUI/Controls/IControl.cs | 4 +- src/TUI/Controls/Table.cs | 27 +++-------- src/TUI/Dashboards/DependencyDashboard.cs | 54 +++++++++------------ src/TUI/Domain/NewFile1.txt | 53 +++++++++++++++++++++ src/TUI/Domain/Package.cs | 17 ++----- src/TUI/Domain/Settings.cs | 6 +-- src/TUI/Extensions.cs | 12 ++--- src/TUI/Program.cs | 58 +++++++++++++++++------ src/TUI/Settings/DependencyDto.cs | 2 +- src/TUI/TUI.csproj | 32 ++++++------- src/TUI/UserInterface/CommandLine.cs | 17 +++++++ src/TUI/UserInterface/Header.cs | 25 +++++----- src/TUI/UserInterface/Icons.cs | 20 ++++---- src/TUI/UserInterface/Palette.cs | 37 ++++++++++++--- src/TUI/UserInterface/Panel.cs | 28 +++++------ 18 files changed, 294 insertions(+), 180 deletions(-) create mode 100644 src/TUI/Domain/NewFile1.txt create mode 100644 src/TUI/UserInterface/CommandLine.cs diff --git a/src/TUI/Controls/Copyright.cs b/src/TUI/Controls/Copyright.cs index 0100952..5faf29f 100644 --- a/src/TUI/Controls/Copyright.cs +++ b/src/TUI/Controls/Copyright.cs @@ -5,7 +5,7 @@ namespace TUI.Controls; public class Copyright : IControl { - public void Render(string author, Position position) + public void Render(string author, Position position, int? height = 0) { const string icon = "© "; Console.SetCursorPosition(position.Left - icon.Width(), position.Top); diff --git a/src/TUI/Controls/Dashboard.cs b/src/TUI/Controls/Dashboard.cs index 69ae5bb..581061e 100644 --- a/src/TUI/Controls/Dashboard.cs +++ b/src/TUI/Controls/Dashboard.cs @@ -6,39 +6,42 @@ namespace TUI.Controls; public class Dashboard : IControl { - public void Render(string title, Position position) + public bool IsFocused { get; set; } + + public void Render(string title, Position position, int? height = 0) { Console.SetCursorPosition(position.Left, position.Top); - RenderTopLine(title); + RenderTopLine(title, IsFocused); - var marginTop = Theme.BorderWidth + Theme.Padding + position.Top; - var dashboardHeight = Console.WindowHeight - Theme.BorderWidth; + var marginTop = position.Top; - for (var top = marginTop; top < dashboardHeight; top++) - { - RenderMiddleLine(); - } + var dashboardHeight = height == 0 ? Console.WindowHeight - marginTop : height + Theme.Padding * 2; - RenderBottomLine(); + for (var top = marginTop; + top < dashboardHeight + marginTop - Theme.BorderWidth * 2 - Theme.Padding * 2; + top++) + RenderMiddleLine(IsFocused); + + RenderBottomLine(IsFocused); } - private static void RenderMiddleLine() + private static void RenderMiddleLine(bool isFocused) { - Console.Write("│".Primary()); + Console.Write("│".Primary(isFocused)); Console.Write(new string(' ', Console.WindowWidth - Theme.BorderWidth * 2)); - Console.WriteLine("│".Primary()); + Console.WriteLine("│".Primary(isFocused)); } - private static void RenderBottomLine() + private static void RenderBottomLine(bool isFocused) { var lineWidth = Console.WindowWidth - Theme.BorderWidth * 2; - Console.Write("└".Primary()); - Console.Write('─'.Repeat(lineWidth).Primary()); - Console.WriteLine("┘".Primary()); + Console.Write("└".Primary(isFocused)); + Console.Write('─'.Repeat(lineWidth).Primary(isFocused)); + Console.WriteLine("┘".Primary(isFocused)); } - private static void RenderTopLine(string title) + private static void RenderTopLine(string title, bool isFocused) { var lineWidth = (Console.WindowWidth - title.Width() - Theme.BorderWidth * 2 - Theme.Padding * 2) / @@ -48,13 +51,10 @@ public class Dashboard : IControl topLine.Append("┌"); topLine.Append('─'.Repeat(lineWidth)); topLine.AppendFormat("{0}{1}{0}", ' '.Repeat(Theme.Padding), title); - if (title.Width() % 2 == 1) - { - topLine.Append('─'); - } + if (title.Width() % 2 == 1) topLine.Append('─'); topLine.Append('─'.Repeat(lineWidth)); topLine.Append("┐"); - Console.WriteLine(topLine.ToString().Primary()); + Console.WriteLine(topLine.ToString().Primary(isFocused)); } } \ No newline at end of file diff --git a/src/TUI/Controls/Display.cs b/src/TUI/Controls/Display.cs index bd819a1..3bff348 100644 --- a/src/TUI/Controls/Display.cs +++ b/src/TUI/Controls/Display.cs @@ -7,33 +7,43 @@ namespace TUI.Controls; public class Display { - private bool _headerInDisplay = true; - public readonly Header Header; + public readonly CommandLine CommandLine; public readonly Copyright Copyright; public readonly DependencyDashboard DependencyDashboard; + public readonly Header Header; + private bool _commandLineInDisplay; + private Project _currentProject; + private bool _headerInDisplay = true; public Display() { Header = new Header(); Copyright = new Copyright(); + CommandLine = new CommandLine(); DependencyDashboard = new DependencyDashboard(); - Render(); } + public string FocusedElement { get; set; } = ""; + public void OpenDeps(Project project) { _currentProject = project; var dashboardPosition = new Position(0, Header.Height); + DependencyDashboard.IsFocused = true; + CommandLine.IsFocused = false; DependencyDashboard.Render(_currentProject, dashboardPosition); } - private void ResizeDependencies(bool full) + private void ResizeDependencies() { - var dashboardPosition = new Position(0, full ? 0 : Header.Height); + var topPosition = 0; + topPosition += _commandLineInDisplay ? CommandLine.Height : 0; + topPosition += _headerInDisplay ? Header.Height : 0; + var dashboardPosition = new Position(0, topPosition); DependencyDashboard.Render(_currentProject, dashboardPosition); } @@ -58,7 +68,7 @@ public class Display Header.Render(headerPosition); } - ResizeDependencies(!_headerInDisplay); + ResizeDependencies(); } public void Next() @@ -70,4 +80,18 @@ public class Display { DependencyDashboard.Previous(); } + + public void OpenCommandLine() + { + var commandLinePosition = new Position(0, _headerInDisplay ? Header.Height : 0); + CommandLine.IsFocused = true; + DependencyDashboard.IsFocused = false; + FocusedElement = nameof(CommandLine); + CommandLine.Render(commandLinePosition); + _commandLineInDisplay = true; + ResizeDependencies(); + Console.SetCursorPosition(commandLinePosition.Left + Theme.Padding + Theme.BorderWidth + 2, + commandLinePosition.Top + Theme.BorderWidth); + Console.CursorVisible = true; + } } \ No newline at end of file diff --git a/src/TUI/Controls/IControl.cs b/src/TUI/Controls/IControl.cs index 6fda601..231c82b 100644 --- a/src/TUI/Controls/IControl.cs +++ b/src/TUI/Controls/IControl.cs @@ -7,5 +7,7 @@ public interface IControl public interface IControl { - void Render(TProps props, Position position); + // bool IsFocused { get; } + + void Render(TProps props, Position position, int? height); } \ No newline at end of file diff --git a/src/TUI/Controls/Table.cs b/src/TUI/Controls/Table.cs index 353ca3e..1bf1249 100644 --- a/src/TUI/Controls/Table.cs +++ b/src/TUI/Controls/Table.cs @@ -11,23 +11,20 @@ public record TableProps(IEnumerable HeaderCells, public class Table : IControl { + private readonly Dictionary _rows = new(); private Position _position; private int _selectedRowId; - public void Render(TableProps props, Position position) + public void Render(TableProps props, Position position, int? height = 0) { _position = position; Console.SetCursorPosition(_position.Left, _position.Top); Console.Write(' '.Repeat(props.TitleWidth)); foreach (var headerCell in props.HeaderCells) - { Console.Write(' '.Repeat(props.ColumnWidth - headerCell.Width()) + headerCell); - } } - private readonly Dictionary _rows = new(); - public void RenderRow(int rowId, string rowText, string? bgColor = default) { var padRight = ' '.Repeat(Console.WindowWidth - rowText.Width() - Theme.BorderWidth * 2); @@ -39,10 +36,7 @@ public class Table : IControl public void Next() { - if (_selectedRowId >= _rows.Count) - { - return; - } + if (_selectedRowId >= _rows.Count) return; RemoveHoverFromCurrentRow(); RenderRow(++_selectedRowId, _rows[_selectedRowId], Palette.HoverColor); @@ -50,23 +44,14 @@ public class Table : IControl private void RemoveHoverFromCurrentRow() { - if (_rows.TryGetValue(_selectedRowId, out var row)) - { - RenderRow(_selectedRowId, row); - } + if (_rows.TryGetValue(_selectedRowId, out var row)) RenderRow(_selectedRowId, row); } public void Previous() { - if (_selectedRowId == 0) - { - Next(); - } + if (_selectedRowId == 0) Next(); - if (_selectedRowId == 1) - { - return; - } + if (_selectedRowId == 1) return; RemoveHoverFromCurrentRow(); RenderRow(--_selectedRowId, _rows[_selectedRowId], Palette.HoverColor); diff --git a/src/TUI/Dashboards/DependencyDashboard.cs b/src/TUI/Dashboards/DependencyDashboard.cs index 77076b1..f5603da 100644 --- a/src/TUI/Dashboards/DependencyDashboard.cs +++ b/src/TUI/Dashboards/DependencyDashboard.cs @@ -15,13 +15,20 @@ public class DependencyDashboard : IControl private const int TitleWidth = 25; private const int ColumnWidth = 10; + private readonly static Dictionary Packages = new(); + private readonly Dashboard _dashboard = new(); + private readonly Table _table = new(); - public void Render(Project project, Position position) + public bool IsFocused { - var dashboard = new Dashboard(); - dashboard.Render(project.Icon, position); + get => _dashboard.IsFocused; + set => _dashboard.IsFocused = value; + } + public void Render(Project project, Position position, int? height = 0) + { + _dashboard.Render(project.Icon + " Dependencies", position); var header = project.Dependencies.Select(GetConventionVersion).ToArray(); var rows = project.Sources.Select(GetTitle).ToArray(); @@ -77,10 +84,7 @@ public class DependencyDashboard : IControl { var currentVersion = package.ParseVersion(dependency.Name); - if (currentVersion == null) - { - return Icons.NotFound; - } + if (currentVersion == null) return Icons.NotFound; var conventionVersion = dependency.Version?.ToVersion(); return PaintingVersion(currentVersion, conventionVersion); @@ -90,30 +94,20 @@ public class DependencyDashboard : IControl { var textVersion = current.ToString(); - if (current > convention) - { - return textVersion.Info(); - } + if (current > convention) return textVersion.Info(); if (current < convention) - { return current.Major == convention.Major ? textVersion.Primary() : textVersion.Warning(); - } return textVersion.Hint(); } - private readonly static Dictionary Packages = new(); - private static Package DownloadPackage(SourceDto sourceDto) { - if (Packages.TryGetValue(sourceDto.Repo, out var downloadPackage)) - { - return downloadPackage; - } + var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo; + if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; using HttpClient client = new(); - var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo; var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); var package = JsonSerializer.Deserialize(json); Packages.Add(endpoint, package); @@ -135,10 +129,7 @@ public class DependencyDashboard : IControl private static string RenderCurrentVersion(string version) { var versionWidth = version.Width(); - if (versionWidth == 0) - { - return ' '.Repeat(ColumnWidth - 1) + Icons.NotFound.Hint(); - } + if (versionWidth == 0) return ' '.Repeat(ColumnWidth - 1) + Icons.NotFound.Hint(); return ' '.Repeat(ColumnWidth - versionWidth) + version; } @@ -188,20 +179,21 @@ public class DependencyDashboard : IControl private static string GetApplicationType(SourceDto sourceDto) { foreach (var application in Icons.Applications) - { if (sourceDto.Tags.Have(application.Value)) return application.Key; - } return Icons.Undefined; } - private static string GetGitApplication(SourceDto sourceDto) => sourceDto.Repo switch + private static string GetGitApplication(SourceDto sourceDto) { - { } url when url.Contains("gitlab") => Icons.GitLab, - { } url when url.Contains("github") => Icons.GitHub, - _ => Icons.Git - }; + return sourceDto.Repo switch + { + { } url when url.Contains("gitlab") => Icons.GitLab, + { } url when url.Contains("github") => Icons.GitHub, + _ => Icons.Git + }; + } public void Next() { diff --git a/src/TUI/Domain/NewFile1.txt b/src/TUI/Domain/NewFile1.txt new file mode 100644 index 0000000..66c489e --- /dev/null +++ b/src/TUI/Domain/NewFile1.txt @@ -0,0 +1,53 @@ + + 󰘳 1 󱓟 releases  select prev + 󰘳 2 󰧑 competencies  select next + 󰘳 3  dependencies 󰬌 toggle head + 󰘳 4 󰬘 quit + + 󰎔 too new  Auth  package +  so good 󰞉 WWW 󰡨 image +  be nice 󰚩 SEO  site + 󰬟 too old  VCS  api + + 󰦖 wait 󰲽 build 󱓞 release + 󱔢 reopen 󱞈 testing 󰶯 hotfix + 󱞇 in progress 󰦕 done  publish + 󱞇 review 󱄊 cancel + +   releases 󱓟  Fact  2023 +   releases 󱓟  Fact +   releases 󱓟  Planned +   releases 󱓟  Planned  2024-12-31 xfirm +   competencies 󰧑 +   growth zone 󰶼 +   dependencies  + +┌──────────────────────────────────────────────────────────────────────── Planned release ─────────────────────────────────────────────────────────────────┐ +│ 2024-12-31 4/11 xfirm [############# ] //green - done, blue - test, pink review/build, orange WIP +│ 2024-12-31 xfirm 4/11 [###############.......] //green - done, blue - test, pink review/build +│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build +│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build +│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build +│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build +│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ +┌──────────────────────────────────────────────────────────────────────── checkperson-site ────────────────────────────────────────────────────────────────┐ +│ 󰨑 󰦖  ELK-3628 Create new menu. 󰵮 Petrov A. 󰙨 Ivanov I. +│ 󰨑 󰦕  XF-12 Change input hover. 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. +│ 󰨑 󱞇  ELK-3628 Crete new project with menu, profile, issues and # 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + +┌─────────────────────────────────────────────────────────────────────────── Actual releases 2023 ─────────────────────────────────────────────────────────┐ +│ Jan Feb Mar Apl May Jun Jul Aug Sep Oct Nov Dec +│ ├─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤ +│ LK 󱓞 󱓞  󱓞 󱓞  󱓞 󱓞  󱓞 󱓞  󱓞 󱓞  󱓞 󱓞  󱓞 󱓞 󱓞  󱓞 󱓞  󱓞 󱓞  󱓞 󱓞  󱓞 󱓞 +│ CP 󱓞  󱓞  󱓞  󱓞    󱓞  󱓞  󱓞  󱓞  󱓞  󱓞  󱓞 +│ RR 󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯  󰶯 󰶯 +└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + + + + + diff --git a/src/TUI/Domain/Package.cs b/src/TUI/Domain/Package.cs index b7f7f87..c56d4a3 100644 --- a/src/TUI/Domain/Package.cs +++ b/src/TUI/Domain/Package.cs @@ -17,25 +17,16 @@ public class Package public Version? ParseVersion(string? dependencyName) { - if (dependencyName == null) - { - return null; - } + if (dependencyName == null) return null; JsonNode? version = null; var lowerDependencyName = dependencyName.ToLower(); Dependencies?.TryGetPropertyValue(lowerDependencyName, out version); - - if (version == null) - { - Engines?.TryGetPropertyValue(lowerDependencyName, out version); - } - if (version == null) - { - DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version); - } + if (version == null) Engines?.TryGetPropertyValue(lowerDependencyName, out version); + + if (version == null) DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version); return version?.GetValue().ToVersion(); } diff --git a/src/TUI/Domain/Settings.cs b/src/TUI/Domain/Settings.cs index 0a4c676..41085f8 100644 --- a/src/TUI/Domain/Settings.cs +++ b/src/TUI/Domain/Settings.cs @@ -7,6 +7,9 @@ namespace TUI.Domain; [YamlSerializable] public class Settings { + [YamlMember] + public Project[] Projects { get; set; } + public static Settings Init() { var deserializer = new DeserializerBuilder() @@ -16,7 +19,4 @@ public class Settings using var sr = new StreamReader("settings.yaml"); return deserializer.Deserialize(sr.ReadToEnd()); } - - [YamlMember] - public Project[] Projects { get; set; } } \ No newline at end of file diff --git a/src/TUI/Extensions.cs b/src/TUI/Extensions.cs index 310da13..196eb4a 100644 --- a/src/TUI/Extensions.cs +++ b/src/TUI/Extensions.cs @@ -1,3 +1,4 @@ +using System.Globalization; using System.Text.RegularExpressions; @@ -17,18 +18,15 @@ public static class Extensions public static string RemoveColors(this string text) { - return Regex.Replace(text, @"\S\[(\d{0,3}[;m][_]?){0,5}", ""); + return Regex.Replace(text, @"\S\[(\d{0,3}[;m]_?){0,5}", ""); } - + public static int Width(this string text) { - if (string.IsNullOrEmpty(text)) - { - return 0; - } + if (string.IsNullOrEmpty(text)) return 0; var clearText = text.RemoveColors(); - var stringInfo = new System.Globalization.StringInfo(clearText); + var stringInfo = new StringInfo(clearText); return stringInfo.LengthInTextElements; } diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index ed56ff6..5ea9cc9 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -1,5 +1,5 @@ using TUI.Controls; -using Settings = TUI.Domain.Settings; +using TUI.Domain; Console.Clear(); @@ -10,23 +10,53 @@ var settings = Settings.Init(); var display = new Display(); display.OpenDeps(settings.Projects[0]); -var hotKey = ConsoleKey.NoName; +var key = new ConsoleKeyInfo('1', ConsoleKey.NoName, false, false, false); +var waitCommand = true; do { - switch (hotKey) + if (key.Key == ConsoleKey.Q && !display.CommandLine.IsFocused) { - case ConsoleKey.DownArrow: - display.Next(); - break; - case ConsoleKey.UpArrow: - display.Previous(); - break; - case ConsoleKey.E: - display.ToggleHeader(); - break; + waitCommand = false; + continue; } - hotKey = Console.ReadKey(intercept: true).Key; -} while (hotKey != ConsoleKey.Q); + if (display.CommandLine.IsFocused) + { + switch (key.Key) + { + case ConsoleKey.Escape: + display.CommandLine.IsFocused = false; + break; + default: + Console.Write(key.KeyChar); + + break; + } + } + else + { + switch (key.KeyChar) + { + case ':': + display.OpenCommandLine(); + break; + } + + switch (key.Key) + { + case ConsoleKey.DownArrow: + display.Next(); + break; + case ConsoleKey.UpArrow: + display.Previous(); + break; + case ConsoleKey.E: + display.ToggleHeader(); + break; + } + } + + key = Console.ReadKey(true); +} while (waitCommand); Console.Clear(); \ No newline at end of file diff --git a/src/TUI/Settings/DependencyDto.cs b/src/TUI/Settings/DependencyDto.cs index 53d770c..b341736 100644 --- a/src/TUI/Settings/DependencyDto.cs +++ b/src/TUI/Settings/DependencyDto.cs @@ -13,7 +13,7 @@ public class DependencyDto [DataMember] [YamlMember] public string? Name { get; set; } - + [DataMember] [YamlMember] public string? Icon diff --git a/src/TUI/TUI.csproj b/src/TUI/TUI.csproj index 05b1ebc..8e11941 100644 --- a/src/TUI/TUI.csproj +++ b/src/TUI/TUI.csproj @@ -1,22 +1,22 @@ - - Exe - net7.0 - enable - enable - 0.1.0 - + + Exe + net7.0 + enable + enable + 0.1.0 + - - - - + + + + - - - Always - - + + + Always + + diff --git a/src/TUI/UserInterface/CommandLine.cs b/src/TUI/UserInterface/CommandLine.cs new file mode 100644 index 0000000..20969fb --- /dev/null +++ b/src/TUI/UserInterface/CommandLine.cs @@ -0,0 +1,17 @@ +using TUI.Controls; + + +namespace TUI.UserInterface; + +public class CommandLine : Dashboard +{ + public const int Height = 3; + + public void Render(Position position) + { + base.Render("Command", position, Height); + + Console.SetCursorPosition(position.Left + Theme.BorderWidth + Theme.Padding, position.Top + Theme.BorderWidth); + Console.Write(">"); + } +} \ No newline at end of file diff --git a/src/TUI/UserInterface/Header.cs b/src/TUI/UserInterface/Header.cs index 39bebf7..bda1a3f 100644 --- a/src/TUI/UserInterface/Header.cs +++ b/src/TUI/UserInterface/Header.cs @@ -9,15 +9,6 @@ public class Header : IControl public const int Height = 6; public const int MaxHeaderBlocksWidth = 16; - - private readonly Dictionary _hotKeys = new() - { - { "", "select prev" }, - { "", "select next" }, - { "󰬌", "toggle head" }, - { "󰬘", "quit" }, - }; - private readonly Dictionary _hints = new() { { "󰎔", "too new".Info() }, @@ -26,22 +17,28 @@ public class Header : IControl { "󰬟", "too old".Warning() } }; + + private readonly Dictionary _hotKeys = new() + { + { "", "select prev" }, + { "", "select next" }, + { "󰬌", "toggle head" }, + { "󰬘", "quit" } + }; + private readonly Dictionary _tags = new() { { Icons.Auth, "Auth" }, { Icons.NetworkPublic, "WWW" }, { Icons.SEO, "SEO" }, - { Icons.GitLab, "VCS" }, + { Icons.GitLab, "VCS" } }; public void Render(Position position) { Console.SetCursorPosition(position.Left, position.Top); - for (var i = 1; i <= Height; i++) - { - Console.WriteLine(new string(' ', Console.WindowWidth - LogoWidth)); - } + for (var i = 1; i <= Height; i++) Console.WriteLine(new string(' ', Console.WindowWidth - LogoWidth)); RenderBlock(0, _hints); RenderBlock(1, _tags); diff --git a/src/TUI/UserInterface/Icons.cs b/src/TUI/UserInterface/Icons.cs index 2e83dfb..fb6976c 100644 --- a/src/TUI/UserInterface/Icons.cs +++ b/src/TUI/UserInterface/Icons.cs @@ -5,6 +5,14 @@ namespace TUI.UserInterface; public static class Icons { + public readonly static Dictionary Applications = new() + { + { NpmPackage, "package" }, + { DockerImage, "image" }, + { Site, "site" }, + { Api, "api" } + }; + public static string GitLab => GetIcon("", "E24329"); public static string GitHub => GetIcon("", "ADBAC7"); public static string Git => GetIcon("", "F14E32"); @@ -19,14 +27,8 @@ public static class Icons public static string Auth => GetIcon("", "FFD700"); public static string NotFound => GetIcon(""); - public readonly static Dictionary Applications = new() + private static string GetIcon(string icon, string? activeColor = null) { - { NpmPackage, "package" }, - { DockerImage, "image" }, - { Site, "site" }, - { Api, "api" }, - }; - - private static string GetIcon(string icon, string? activeColor = null) => - icon.Pastel(activeColor ?? Palette.HintColor); + return icon.Pastel(activeColor ?? Palette.HintColor); + } } \ No newline at end of file diff --git a/src/TUI/UserInterface/Palette.cs b/src/TUI/UserInterface/Palette.cs index c561172..8cc3f6f 100644 --- a/src/TUI/UserInterface/Palette.cs +++ b/src/TUI/UserInterface/Palette.cs @@ -12,10 +12,35 @@ public static class Palette public const string WarningColor = "EC9706"; public const string InfoColor = "25799F"; - public static string Primary(this string currentText) => currentText.Pastel(PrimaryColor); - public static string Hint(this string currentText) => currentText.Pastel(HintColor); - public static string Disable(this string currentText) => currentText.RemoveColors().Pastel(HintColor); - public static string Warning(this string currentText) => currentText.Pastel(WarningColor); - public static string Error(this string currentText) => currentText.Pastel(ErrorColor); - public static string Info(this string currentText) => currentText.Pastel(InfoColor); + public static string Primary(this string currentText, bool isFocused = true) + { + return isFocused + ? currentText.Pastel(PrimaryColor) + : Hint(currentText); + } + + public static string Hint(this string currentText) + { + return currentText.Pastel(HintColor); + } + + public static string Disable(this string currentText) + { + return currentText.RemoveColors().Pastel(HintColor); + } + + public static string Warning(this string currentText) + { + return currentText.Pastel(WarningColor); + } + + public static string Error(this string currentText) + { + return currentText.Pastel(ErrorColor); + } + + public static string Info(this string currentText) + { + return currentText.Pastel(InfoColor); + } } \ No newline at end of file diff --git a/src/TUI/UserInterface/Panel.cs b/src/TUI/UserInterface/Panel.cs index be70b0a..9bba507 100644 --- a/src/TUI/UserInterface/Panel.cs +++ b/src/TUI/UserInterface/Panel.cs @@ -11,6 +11,9 @@ public static class Panel private const int TagCount = 5; private const int TagWidth = 2; + + private static int _marginTop; + public static void RenderRows(SourceDto[] sources, int selectedRowNumber) { for (var index = 0; index < sources.Length; index++) @@ -28,20 +31,18 @@ public static class Panel } for (var index = 0; index < sources.Length; index++) - { Console.SetCursorPosition(TitleWidth, 6 + index + _marginTop + BorderWidth + Theme.Padding); - // var source = sources[index]; - // var package = DownloadPackage(source); - // var resultText = package.Dependencies.React; - // resultText = new string(' ', ColumnWidth - resultText.Width()) + resultText; - // if (selectedRowNumber == index + 1) - // { - // resultText = resultText.PastelBg("292928"); - // } - // - // Console.Write(resultText); - } + // var source = sources[index]; + // var package = DownloadPackage(source); + // var resultText = package.Dependencies.React; + // resultText = new string(' ', ColumnWidth - resultText.Width()) + resultText; + // if (selectedRowNumber == index + 1) + // { + // resultText = resultText.PastelBg("292928"); + // } + // + // Console.Write(resultText); // for (var index = 0; index < sources.Length; index++) // { // var loading = true; @@ -74,9 +75,6 @@ public static class Panel // } } - - private static int _marginTop; - // private static Package DownloadPackage(Source source) // { // if (Packages.TryGetValue(source.Repo, out var downloadPackage)) From 5514c6bd7a89aa1363065be8de71ab5189e4d2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Mon, 29 Jan 2024 13:08:00 +0500 Subject: [PATCH 02/23] =?UTF-8?q?=F0=9F=94=96=20Change=20render=20for=20ve?= =?UTF-8?q?rsion=20with=20alpha=20postfix.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI/Dashboards/DependencyDashboard.cs | 2 +- src/TUI/Domain/NewFile1.txt | 13 ++++++------- src/TUI/Extensions.cs | 2 -- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/TUI/Dashboards/DependencyDashboard.cs b/src/TUI/Dashboards/DependencyDashboard.cs index f5603da..96fba08 100644 --- a/src/TUI/Dashboards/DependencyDashboard.cs +++ b/src/TUI/Dashboards/DependencyDashboard.cs @@ -118,7 +118,7 @@ public class DependencyDashboard : IControl { var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); return $"{sourceDto.Repo}/api/v4/projects/{sourceDto.ProjectId}/repository/files/package.json/raw?" + - $"private_token={token}&ref=master"; + $"private_token={token}&ref=dev"; } private static string GetConventionVersion(DependencyDto dependencyDto) diff --git a/src/TUI/Domain/NewFile1.txt b/src/TUI/Domain/NewFile1.txt index 66c489e..9f63c19 100644 --- a/src/TUI/Domain/NewFile1.txt +++ b/src/TUI/Domain/NewFile1.txt @@ -23,8 +23,9 @@   dependencies  ┌──────────────────────────────────────────────────────────────────────── Planned release ─────────────────────────────────────────────────────────────────┐ -│ 2024-12-31 4/11 xfirm [############# ] //green - done, blue - test, pink review/build, orange WIP -│ 2024-12-31 xfirm 4/11 [###############.......] //green - done, blue - test, pink review/build +│ 2024-12-31 4/11 xfirm [############# ] //green - done, blue - test, pink review/build, orange WIP +│ 4/11 xfirm [###############.......] //green - done, blue - test, pink review/build +│ 2024-12-31 4/11 xfirm [###############.......] //green - done, blue - test, pink review/build │ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build │ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build │ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build @@ -32,9 +33,9 @@ │ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ┌──────────────────────────────────────────────────────────────────────── checkperson-site ────────────────────────────────────────────────────────────────┐ -│ 󰨑 󰦖  ELK-3628 Create new menu. 󰵮 Petrov A. 󰙨 Ivanov I. -│ 󰨑 󰦕  XF-12 Change input hover. 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. -│ 󰨑 󱞇  ELK-3628 Crete new project with menu, profile, issues and # 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. +│ 󰨑 󰦖  ELK-3628 Create new menu.  Anna P. 󰵮 Petrov A. 󰙨 Ivanov I. +│ 󰨑 󰦕  XF-12 Change input hover.  Alex K. 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. +│ 󰨑 󱞇  ELK-3628 Crete new project with menu, profile, issues and #  Anna P. 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────── Actual releases 2023 ─────────────────────────────────────────────────────────┐ @@ -49,5 +50,3 @@ - - diff --git a/src/TUI/Extensions.cs b/src/TUI/Extensions.cs index 196eb4a..4acb68f 100644 --- a/src/TUI/Extensions.cs +++ b/src/TUI/Extensions.cs @@ -33,8 +33,6 @@ public static class Extensions public static Version? ToVersion(this string textVersion) { var version = textVersion.Replace("^", "").Replace("~", "").Split("."); - if (version.Length != 3) - return null; var major = Convert.ToInt32(version[0]); var minor = Convert.ToInt32(version[1]); var patch = Convert.ToInt32(version[2].Split('-')[0]); From dfa9d9e665e6f243a759caef5ade824908221b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Thu, 7 Mar 2024 02:49:54 +0500 Subject: [PATCH 03/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactoring=20render?= =?UTF-8?q?=20engine.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TLD.sln | 6 + docs/RENDER.md | 51 +++++ src/Dashboard/Dashboard.csproj | 10 + src/Dashboard/Program.cs | 9 + .../Components/Controls/CellsComponentBase.cs | 37 ++++ src/TUI/Components/Controls/Copyright.cs | 18 ++ src/TUI/Components/Controls/Dashboard.cs | 68 ++++++ .../Components/Controls/HeaderContainer.cs | 37 ++++ .../Controls/Statics/Hints/AppTypeHints.cs | 28 +++ .../Controls/Statics/Hints/HotkeysHint.cs | 27 +++ .../Controls/Statics/Hints/TagHints.cs | 28 +++ .../Controls/Statics/Hints/VersionHints.cs | 27 +++ src/TUI/Components/Controls/Statics/Logo.cs | 20 ++ src/TUI/Components/Controls/Tag.cs | 66 ++++++ src/TUI/Components/Layouts/DashboardLayout.cs | 36 +++ src/TUI/Components/Views/DependenciesView.cs | 160 ++++++++++++++ src/TUI/Controls/Copyright.cs | 16 -- src/TUI/Controls/Dashboard.cs | 60 ----- src/TUI/Controls/Display.cs | 97 -------- src/TUI/Controls/IControl.cs | 13 -- src/TUI/Controls/Position.cs | 3 - src/TUI/Controls/Table.cs | 59 ----- src/TUI/Dashboards/DependencyDashboard.cs | 207 ------------------ src/TUI/Domain/DevelopmentStack.cs | 3 + src/TUI/Domain/{Project.cs => ProjectDto.cs} | 8 +- src/TUI/Domain/Settings.cs | 2 +- src/TUI/Engine/Helper.cs | 46 ++++ .../Nodes/Attributes/Alignments/Alignment.cs | 3 + .../Nodes/Attributes/Alignments/Horizontal.cs | 8 + .../Attributes/Alignments/IWithAlignment.cs | 8 + .../Nodes/Attributes/Alignments/Vertical.cs | 8 + .../Nodes/Attributes/Paddings/IWithPadding.cs | 17 ++ .../Nodes/Attributes/Paddings/Padding.cs | 15 ++ src/TUI/Engine/Nodes/Attributes/Size.cs | 6 + .../Engine/Nodes/Components/ComponentBase.cs | 45 ++++ .../Nodes/Components/ComponentStaticBase.cs | 24 ++ src/TUI/Engine/Nodes/Components/Content.cs | 26 +++ src/TUI/Engine/Nodes/Components/IComponent.cs | 11 + src/TUI/Engine/Nodes/Containers/IContainer.cs | 8 + .../Engine/Nodes/Containers/Orientation.cs | 7 + src/TUI/Engine/Nodes/INode.cs | 5 + src/TUI/Engine/Nodes/NodePosition.cs | 6 + src/TUI/Engine/Nodes/Nodes.cs | 5 + .../Rendering/ConsoleRenderingEngine.cs | 129 +++++++++++ src/TUI/Engine/Rendering/ConsoleWindow.cs | 9 + src/TUI/Engine/Rendering/IRenderingEngine.cs | 9 + src/TUI/Engine/Rendering/IWindow.cs | 9 + src/TUI/Engine/Symbols.cs | 25 +++ src/TUI/Engine/Theme/Indentation.cs | 7 + src/TUI/Engine/Theme/Level.cs | 7 + src/TUI/Engine/Theme/Palette.cs | 28 +++ src/TUI/Extensions.cs | 4 +- src/TUI/Pages/DependenciesPage.cs | 103 +++++++++ src/TUI/Program.cs | 93 ++++---- src/TUI/Store/DependenciesStore.cs | 29 +++ src/TUI/UserInterface/CommandLine.cs | 36 +-- src/TUI/UserInterface/Header.cs | 79 ------- src/TUI/UserInterface/Icons.cs | 19 +- src/TUI/UserInterface/Palette.cs | 46 ---- src/TUI/UserInterface/Panel.cs | 9 +- src/TUI/UserInterface/Theme.cs | 7 - tests/WIdgets/TUI.Tests/ComponentBaseTests.cs | 63 ++++++ .../TUI.Tests/ConsoleRenderingEngineTests.cs | 184 ++++++++++++++++ tests/WIdgets/TUI.Tests/Controls/LogoTests.cs | 18 ++ tests/WIdgets/TUI.Tests/TUI.Tests.csproj | 32 +++ tests/WIdgets/TUI.Tests/Usings.cs | 1 + 66 files changed, 1623 insertions(+), 667 deletions(-) create mode 100644 docs/RENDER.md create mode 100644 src/Dashboard/Dashboard.csproj create mode 100644 src/Dashboard/Program.cs create mode 100644 src/TUI/Components/Controls/CellsComponentBase.cs create mode 100644 src/TUI/Components/Controls/Copyright.cs create mode 100644 src/TUI/Components/Controls/Dashboard.cs create mode 100644 src/TUI/Components/Controls/HeaderContainer.cs create mode 100644 src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs create mode 100644 src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs create mode 100644 src/TUI/Components/Controls/Statics/Hints/TagHints.cs create mode 100644 src/TUI/Components/Controls/Statics/Hints/VersionHints.cs create mode 100644 src/TUI/Components/Controls/Statics/Logo.cs create mode 100644 src/TUI/Components/Controls/Tag.cs create mode 100644 src/TUI/Components/Layouts/DashboardLayout.cs create mode 100644 src/TUI/Components/Views/DependenciesView.cs delete mode 100644 src/TUI/Controls/Copyright.cs delete mode 100644 src/TUI/Controls/Dashboard.cs delete mode 100644 src/TUI/Controls/Display.cs delete mode 100644 src/TUI/Controls/IControl.cs delete mode 100644 src/TUI/Controls/Position.cs delete mode 100644 src/TUI/Controls/Table.cs delete mode 100644 src/TUI/Dashboards/DependencyDashboard.cs create mode 100644 src/TUI/Domain/DevelopmentStack.cs rename src/TUI/Domain/{Project.cs => ProjectDto.cs} (70%) create mode 100644 src/TUI/Engine/Helper.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Size.cs create mode 100644 src/TUI/Engine/Nodes/Components/ComponentBase.cs create mode 100644 src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs create mode 100644 src/TUI/Engine/Nodes/Components/Content.cs create mode 100644 src/TUI/Engine/Nodes/Components/IComponent.cs create mode 100644 src/TUI/Engine/Nodes/Containers/IContainer.cs create mode 100644 src/TUI/Engine/Nodes/Containers/Orientation.cs create mode 100644 src/TUI/Engine/Nodes/INode.cs create mode 100644 src/TUI/Engine/Nodes/NodePosition.cs create mode 100644 src/TUI/Engine/Nodes/Nodes.cs create mode 100644 src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs create mode 100644 src/TUI/Engine/Rendering/ConsoleWindow.cs create mode 100644 src/TUI/Engine/Rendering/IRenderingEngine.cs create mode 100644 src/TUI/Engine/Rendering/IWindow.cs create mode 100644 src/TUI/Engine/Symbols.cs create mode 100644 src/TUI/Engine/Theme/Indentation.cs create mode 100644 src/TUI/Engine/Theme/Level.cs create mode 100644 src/TUI/Engine/Theme/Palette.cs create mode 100644 src/TUI/Pages/DependenciesPage.cs create mode 100644 src/TUI/Store/DependenciesStore.cs delete mode 100644 src/TUI/UserInterface/Header.cs delete mode 100644 src/TUI/UserInterface/Palette.cs delete mode 100644 src/TUI/UserInterface/Theme.cs create mode 100644 tests/WIdgets/TUI.Tests/ComponentBaseTests.cs create mode 100644 tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs create mode 100644 tests/WIdgets/TUI.Tests/Controls/LogoTests.cs create mode 100644 tests/WIdgets/TUI.Tests/TUI.Tests.csproj create mode 100644 tests/WIdgets/TUI.Tests/Usings.cs diff --git a/TLD.sln b/TLD.sln index 245bd53..a779c60 100644 --- a/TLD.sln +++ b/TLD.sln @@ -2,6 +2,8 @@ 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}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -16,5 +18,9 @@ Global {F92C03F7-2A65-4D0A-9736-13E749AF6903}.Debug|Any CPU.Build.0 = Debug|Any CPU {F92C03F7-2A65-4D0A-9736-13E749AF6903}.Release|Any CPU.ActiveCfg = Release|Any CPU {F92C03F7-2A65-4D0A-9736-13E749AF6903}.Release|Any CPU.Build.0 = Release|Any CPU + {2F0611D2-073F-4E26-BD1B-ACC433FC6F4E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {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 EndGlobalSection EndGlobal diff --git a/docs/RENDER.md b/docs/RENDER.md new file mode 100644 index 0000000..2afcf9a --- /dev/null +++ b/docs/RENDER.md @@ -0,0 +1,51 @@ +# RENDER + +```mermaid +classDiagram + %% Application layer + class ViewPort{ + + GetCanvas() + + string: Content + } + + %% Хранит данные + class Store { + Reload() + } + + %% Хранит разметку + class View { + Store + SetWidgets() + SetCanvas() + Render() + } + + %% Подгатавливает текст + class Painter { + + SetGrid() + + SetView() + } + + %% Composition + class Widget { + + State + ~ Bind() + ~ Render() + } + + class WidgetState + <> WidgetState + WidgetState : Loading + WidgetState : Mounted + WidgetState : BindingError + WidgetState : RenderError +``` + +```mermaid +flowchart LR + Change_Store --> Binding_Widgets + Binding_Widgets --> Render_Widgets + Render_Widgets --> Create_View + Create_View --> Fill_View_Port +``` \ No newline at end of file diff --git a/src/Dashboard/Dashboard.csproj b/src/Dashboard/Dashboard.csproj new file mode 100644 index 0000000..2b14c81 --- /dev/null +++ b/src/Dashboard/Dashboard.csproj @@ -0,0 +1,10 @@ + + + + Exe + net7.0 + enable + enable + + + diff --git a/src/Dashboard/Program.cs b/src/Dashboard/Program.cs new file mode 100644 index 0000000..c462094 --- /dev/null +++ b/src/Dashboard/Program.cs @@ -0,0 +1,9 @@ +namespace Dashboard; + +class Program +{ + static void Main(string[] args) + { + Console.WriteLine("Hello, World!"); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Components/Controls/CellsComponentBase.cs new file mode 100644 index 0000000..5cdde2a --- /dev/null +++ b/src/TUI/Components/Controls/CellsComponentBase.cs @@ -0,0 +1,37 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Attributes; +using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Nodes.Components; + +namespace TUI.Components.Controls; + +public class CellsComponentBase : ComponentBase, IComponent +{ + private const int MaxCellWidth = 10; + + private readonly IEnumerable _cells; + + + public CellsComponentBase(IEnumerable cells) + { + _cells = cells; + } + + public void Render(Horizontal horizontal, Size size) + { + var content = new StringBuilder(); + foreach (var cell in _cells) + { + content.Append(Symbols.Space.Repeat(MaxCellWidth - cell.Width())); + content.Append(cell); + } + + // base.Render(content, position, size); + } + + public override Content Render() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Copyright.cs b/src/TUI/Components/Controls/Copyright.cs new file mode 100644 index 0000000..0cd2d2a --- /dev/null +++ b/src/TUI/Components/Controls/Copyright.cs @@ -0,0 +1,18 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Theme; + +namespace TUI.Components.Controls; + +public class Copyright : ComponentStaticBase +{ + protected override void RenderWithCache(StringBuilder builder) + { + builder.Append(Symbols.Copyright); + builder.Append(Symbols.Space); + builder.Append("Kolosov A. aka \"dnwSilver\"".Hint()); + builder.Append(Symbols.Space); + builder.Append(DateTime.Now.Year); + } +} diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs new file mode 100644 index 0000000..ecdb115 --- /dev/null +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -0,0 +1,68 @@ +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.Theme; + +namespace TUI.Components.Controls; + +public class Dashboard : ComponentBase, IComponent +{ + private readonly string _title; + + public Dashboard(string title) + { + _title = title; + } + + public void Render(Horizontal horizontal, Size size) + { + var dashboardBuilder = new StringBuilder(); + + RenderTopLine(dashboardBuilder, size, _title); + RenderMiddleLine(dashboardBuilder, size); + RenderBottomLine(dashboardBuilder, size); + + // base.Render(dashboardBuilder, position, size); + } + + private static void RenderTopLine(StringBuilder dashboardBuilder, Size size, string title) + { + var halfWidth = (size.Width - title.Width() - (int)Indentation.BorderWidth * 2 - + (int)Indentation.Default * 2) / 2; + dashboardBuilder.Append(Symbols.Angles.LeftTop); + dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); + dashboardBuilder.AppendFormat("{0}{1}{0}", Symbols.Space.Repeat(Convert.ToInt32(Indentation.Default)), title); + dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); + dashboardBuilder.Append(Symbols.Angles.RightTop); + } + + private static void RenderMiddleLine(StringBuilder dashboardBuilder, Size size) + { + var dashboardHeight = size.Height - (int)Indentation.BorderWidth * 2; + + while (dashboardHeight > 0) + { + var bodyWidth = size.Width - (int)Indentation.BorderWidth * 2; + dashboardBuilder.Append(Symbols.Lines.Vertical); + dashboardBuilder.Append(Symbols.Space.Repeat(bodyWidth)); + dashboardBuilder.Append(Symbols.Lines.Vertical); + + dashboardHeight--; + } + } + + private static void RenderBottomLine(StringBuilder dashboardBuilder, Size size) + { + var width = size.Width - (int)Indentation.BorderWidth * 2; + dashboardBuilder.Append(Symbols.Angles.LeftBottom); + dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(width)); + dashboardBuilder.Append(Symbols.Angles.RightBottom); + } + + public override Content Render() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/HeaderContainer.cs b/src/TUI/Components/Controls/HeaderContainer.cs new file mode 100644 index 0000000..abe8bef --- /dev/null +++ b/src/TUI/Components/Controls/HeaderContainer.cs @@ -0,0 +1,37 @@ +using TUI.Components.Controls.Statics; +using TUI.Components.Controls.Statics.Hints; +using TUI.Engine.Nodes; +using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Nodes.Containers; +using TUI.Engine.Theme; + +namespace TUI.Components.Controls; + +public class HeaderContainer : IContainer +{ + public Orientation Orientation => Orientation.Horizontal; + + public Nodes Nodes + { + get + { + var versionHints = new VersionHints() + .Set(Indentation.Default); + + var tagsHints = new TagHints() + .Set(Indentation.Default); + + var appTypeHints = new AppTypeHints() + .Set(Indentation.Default); + + var hotkeysHints = new HotkeysHint() + .Set(Indentation.Default); + + var logo = new Logo() + .Set(Horizontal.Right) + .Set(left: Indentation.Default, bottom: Indentation.Default, right: Indentation.Default); + + return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo }; + } + } +} diff --git a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs b/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs new file mode 100644 index 0000000..31520d0 --- /dev/null +++ b/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs @@ -0,0 +1,28 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Theme; +using TUI.UserInterface; + +namespace TUI.Components.Controls.Statics.Hints; + +public class AppTypeHints : ComponentStaticBase +{ + private readonly Dictionary _hints = new() + { + { Icons.NpmPackage, "package" }, + { Icons.DockerImage, "image" }, + { Icons.Site, "site" }, + { Icons.Api, "api" } + }; + + protected override void RenderWithCache(StringBuilder builder) + { + foreach (var hint in _hints) + { + builder.Append(hint.Key); + builder.Append(Symbols.Space); + builder.AppendLine(hint.Value.Hint()); + } + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs b/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs new file mode 100644 index 0000000..630177e --- /dev/null +++ b/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs @@ -0,0 +1,27 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Theme; + +namespace TUI.Components.Controls.Statics.Hints; + +public class HotkeysHint : ComponentStaticBase +{ + private readonly Dictionary _hints = new() + { + { "", "select prev" }, + { "", "select next" }, + { "󰬌", "toggle head" }, + { "󰬘", "quit" } + }; + + protected override void RenderWithCache(StringBuilder builder) + { + foreach (var hint in _hints) + { + builder.Append(hint.Key.Hint()); + builder.Append(Symbols.Space); + builder.AppendLine(hint.Value.Hint()); + } + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs b/src/TUI/Components/Controls/Statics/Hints/TagHints.cs new file mode 100644 index 0000000..54cb140 --- /dev/null +++ b/src/TUI/Components/Controls/Statics/Hints/TagHints.cs @@ -0,0 +1,28 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Theme; +using TUI.UserInterface; + +namespace TUI.Components.Controls.Statics.Hints; + +public class TagHints : ComponentStaticBase +{ + private readonly Dictionary _hints = new() + { + { Icons.Auth, "Auth" }, + { Icons.NetworkPublic, "WWW" }, + { Icons.SEO, "SEO" }, + { Icons.GitLab, "VCS" } + }; + + protected override void RenderWithCache(StringBuilder builder) + { + foreach (var hint in _hints) + { + builder.Append(hint.Key); + builder.Append(Symbols.Space); + builder.AppendLine(hint.Value.Hint()); + } + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs b/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs new file mode 100644 index 0000000..fa5f3fd --- /dev/null +++ b/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs @@ -0,0 +1,27 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Theme; + +namespace TUI.Components.Controls.Statics.Hints; + +public class VersionHints : ComponentStaticBase +{ + private readonly Dictionary _hints = new() + { + { "󰎔", "too new".Info() }, + { "", "so good".Hint() }, + { "", "be nice".Main() }, + { "󰬟", "too old".Warning() } + }; + + protected override void RenderWithCache(StringBuilder builder) + { + foreach (var hint in _hints) + { + builder.Append(hint.Key.Hint()); + builder.Append(Symbols.Space); + builder.AppendLine(hint.Value); + } + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Statics/Logo.cs b/src/TUI/Components/Controls/Statics/Logo.cs new file mode 100644 index 0000000..41c54b8 --- /dev/null +++ b/src/TUI/Components/Controls/Statics/Logo.cs @@ -0,0 +1,20 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Theme; + +namespace TUI.Components.Controls.Statics; + +public class Logo : ComponentStaticBase +{ + protected override void RenderWithCache(StringBuilder builder) + { + builder.Append($" {"╭━━━━┳╮".Main()}{"╱╱".Hint()}{"╭━━━╮".Main()}").Append(Symbols.LineBreak); + builder.Append($" {"┃╭╮╭╮┃┃".Main()}{"╱╱".Hint()}{"╰╮╭╮┃".Main()}").Append(Symbols.LineBreak); + builder.Append($" {"╰╯┃┃╰┫┃".Main()}{"╱╱╱".Hint()}{"┃┃┃┃".Main()}").Append(Symbols.LineBreak); + builder.Append($" {"╱╱".Hint()}{"┃┃".Main()}{"╱".Hint()}{"┃┃".Main()}{"╱".Hint()}{"╭╮┃┃┃┃".Main()}") + .Append(Symbols.LineBreak); + builder.Append($" {"╱╱╱".Hint()}{"┃┃".Main()}{"╱".Hint()}{"┃╰━╯┣╯╰╯┃".Main()}").Append(Symbols.LineBreak); + builder.Append($"{"╱╱╱╱".Hint()}{"╰╯".Main()}{"╱".Hint()}{"╰━━━┻━━━╯".Main()}").Append(Symbols.LineBreak); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Components/Controls/Tag.cs new file mode 100644 index 0000000..6969993 --- /dev/null +++ b/src/TUI/Components/Controls/Tag.cs @@ -0,0 +1,66 @@ +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.Theme; +using TUI.UserInterface; + +namespace TUI.Components.Controls; + +public class Tag : ComponentBase +{ + private IEnumerable _tags; + private string _gitType; + + public Tag(IRenderingEngine renderingEngine) + { + } + + public void Bind(IEnumerable tags, string gitType) + { + _tags = tags; + _gitType = gitType; + } + + public void Render(Horizontal horizontal, Size size) + { + var tagBuilder = new StringBuilder(); + + tagBuilder.Append(GetGitTypeImage(_gitType)); + tagBuilder.Append(Symbols.Space); + tagBuilder.Append(_tags.Have("public") ? Icons.NetworkPublic : Icons.NetworkPrivate); + tagBuilder.Append(Symbols.Space); + tagBuilder.Append(_tags.Have("seo") ? Icons.SEO : Icons.SEO.Disable()); + tagBuilder.Append(Symbols.Space); + tagBuilder.Append(_tags.Have("auth") ? Icons.Auth : Icons.Auth.Disable()); + tagBuilder.Append(Symbols.Space); + tagBuilder.Append(GetApplicationType()); + tagBuilder.Append(Symbols.Space); + + // base.Render(tagBuilder, position, size); + } + + private string GetApplicationType() + { + foreach (var application in Icons.Applications) + if (_tags.Have(application.Value)) + return application.Key; + + return Icons.Undefined; + } + + private static char GetGitTypeImage(string gitType) => + gitType switch + { + "gitlab" => Symbols.GitLab, + "github" => Symbols.GitHub, + _ => Symbols.Git + }; + + public override Content Render() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Layouts/DashboardLayout.cs b/src/TUI/Components/Layouts/DashboardLayout.cs new file mode 100644 index 0000000..95ab0a1 --- /dev/null +++ b/src/TUI/Components/Layouts/DashboardLayout.cs @@ -0,0 +1,36 @@ +using TUI.Engine.Nodes; +using TUI.Engine.Nodes.Components; +using TUI.Engine.Nodes.Containers; + +namespace TUI.Components.Layouts; + +public class DashboardLayout : IContainer +{ + public Orientation Orientation { get; } = Orientation.Vertical; + + private INode _header; + private INode _footer; + + public Nodes Nodes => + new() + { + _header, _footer + }; + + public DashboardLayout AddHeader(IContainer header) + { + _header = header; + return this; + } + + public DashboardLayout AddFooter(IComponent footer) + { + _footer = footer; + return this; + } + + public string Render() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Views/DependenciesView.cs b/src/TUI/Components/Views/DependenciesView.cs new file mode 100644 index 0000000..e74bd4e --- /dev/null +++ b/src/TUI/Components/Views/DependenciesView.cs @@ -0,0 +1,160 @@ +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; + +namespace TUI.Components.Views; + +public class DependenciesView : ComponentBase, IComponent +{ + private const string ViewName = "Dependencies"; + + private DevelopmentStack _developmentStack; + + public void Bind(DevelopmentStack developmentStack) + { + _developmentStack = developmentStack; + } + + public void Render(Horizontal horizontal, Size size) + { + var dashboardTitle = _developmentStack.Icon + Symbols.Space + ViewName; + var dashboard = new Dashboard(dashboardTitle); + + Add(dashboard); + } + + // private const int TitleWidth = 25; + // private const int ColumnWidth = 10; + + // private readonly DashboardControl _dashboard = new(); + + // public bool IsFocused + // { + // get => _dashboard.IsFocused; + // set => _dashboard.IsFocused = value; + // } + + // public void Render(ProjectDto projectDto, ControlPosition position) + // { + // _dashboard.Render(projectDto.Icon + " Dependencies", position); + // var header = projectDto.Dependencies.Select(GetConventionVersion).ToArray(); + // var rows = projectDto.Sources.Select(GetTitle).ToArray(); + // + // var tablePosition = new ControlPosition( + // position.Left + Theme.BorderWidth, + // position.Top + Theme.BorderWidth); + // + // var tableProps = new TableProps(header, rows, TitleWidth, ColumnWidth); + // _table.Render(tableProps, tablePosition); + // + // for (var rowId = 0; rowId < rows.Length; rowId++) + // { + // var actualDependencies = GetDependencies(projectDto.Sources[rowId], projectDto.Dependencies); + // _table.RenderRow(rowId + 1, rows[rowId] + actualDependencies); + // } + // } + + // private static string GetDependencies(SourceDto sourceDto, IEnumerable conventionDependencies) + // { + // try + // { + // var package = DownloadPackage(sourceDto); + // + // return string.Join("", + // conventionDependencies + // .Select(dependency => GetVersion(dependency, package)) + // .Select(RenderCurrentVersion)); + // } + // catch (HttpRequestException exception) + // { + // switch (exception.StatusCode) + // { + // case HttpStatusCode.BadRequest: + // return " Request have errors.".Pastel(Palette.ErrorColor); + // case HttpStatusCode.Forbidden: + // return " Not enough rights.".Pastel(Palette.ErrorColor); + // case HttpStatusCode.NotFound: + // return " Repository or branch master not found.".Pastel(Palette.ErrorColor); + // } + // + // throw; + // } + // catch (Exception exception) + // { + // Debugger.Break(); + // return "󰋔 We tried to send a request but couldn't. Check your configuration.".Pastel(Palette.ErrorColor); + // } + // } + // + // private static string GetVersion(DependencyDto dependency, Package package) + // { + // var currentVersion = package.ParseVersion(dependency.Name); + // + // if (currentVersion == null) return Icons.NotFound; + // + // var conventionVersion = dependency.Version?.ToVersion(); + // return PaintingVersion(currentVersion, conventionVersion); + // } + // + // private static string PaintingVersion(Version current, Version? convention) + // { + // var textVersion = current.ToString(); + // + // if (current > convention) return textVersion.Info(); + // + // if (current < convention) + // return current.Major == convention.Major ? textVersion.Primary() : textVersion.Warning(); + // + // return textVersion.Hint(); + // } + // + // private static string GetConventionVersion(DependencyDto dependencyDto) + // { + // return dependencyDto.Icon.Pastel(dependencyDto.Color) + dependencyDto.Version.Primary(); + // } + // + // private static string RenderCurrentVersion(string version) + // { + // var versionWidth = version.Width(); + // if (versionWidth == 0) return ' '.Repeat(ColumnWidth - 1) + Icons.NotFound.Hint(); + // + // return ' '.Repeat(ColumnWidth - versionWidth) + version; + // } + // + // private static string GetTitle(SourceDto sourceDto) + // { + // var title = ""; + // + // title += RenderPadding(); + // title += RenderTags(sourceDto); + // if (title.Width() + sourceDto.Name.Length + Theme.Padding <= TitleWidth) + // { + // title += sourceDto.Name; + // } + // else + // { + // var maxNameWidth = TitleWidth - title.Width() - Theme.Padding; + // title += $"{sourceDto.Name[..(maxNameWidth - 1)]}{"#".Hint()}"; + // } + // + // title += RenderPadding(); + // return $"{title}{' '.Repeat(TitleWidth - title.Width())}"; + // } + // + // public void Next() + // { + // _table.Next(); + // } + // + // public void Previous() + // { + // _table.Previous(); + // } + public override Content Render() + { + throw new NotImplementedException(); + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Copyright.cs b/src/TUI/Controls/Copyright.cs deleted file mode 100644 index 5faf29f..0000000 --- a/src/TUI/Controls/Copyright.cs +++ /dev/null @@ -1,16 +0,0 @@ -using TUI.UserInterface; - - -namespace TUI.Controls; - -public class Copyright : IControl -{ - public void Render(string author, Position position, int? height = 0) - { - const string icon = "© "; - Console.SetCursorPosition(position.Left - icon.Width(), position.Top); - - var copyright = $"{icon}{author}".Hint(); - Console.Write(copyright); - } -} \ No newline at end of file diff --git a/src/TUI/Controls/Dashboard.cs b/src/TUI/Controls/Dashboard.cs deleted file mode 100644 index 581061e..0000000 --- a/src/TUI/Controls/Dashboard.cs +++ /dev/null @@ -1,60 +0,0 @@ -using System.Text; -using TUI.UserInterface; - - -namespace TUI.Controls; - -public class Dashboard : IControl -{ - public bool IsFocused { get; set; } - - public void Render(string title, Position position, int? height = 0) - { - Console.SetCursorPosition(position.Left, position.Top); - - RenderTopLine(title, IsFocused); - - var marginTop = position.Top; - - var dashboardHeight = height == 0 ? Console.WindowHeight - marginTop : height + Theme.Padding * 2; - - for (var top = marginTop; - top < dashboardHeight + marginTop - Theme.BorderWidth * 2 - Theme.Padding * 2; - top++) - RenderMiddleLine(IsFocused); - - RenderBottomLine(IsFocused); - } - - private static void RenderMiddleLine(bool isFocused) - { - Console.Write("│".Primary(isFocused)); - Console.Write(new string(' ', Console.WindowWidth - Theme.BorderWidth * 2)); - Console.WriteLine("│".Primary(isFocused)); - } - - private static void RenderBottomLine(bool isFocused) - { - var lineWidth = Console.WindowWidth - Theme.BorderWidth * 2; - Console.Write("└".Primary(isFocused)); - Console.Write('─'.Repeat(lineWidth).Primary(isFocused)); - Console.WriteLine("┘".Primary(isFocused)); - } - - private static void RenderTopLine(string title, bool isFocused) - { - var lineWidth = - (Console.WindowWidth - title.Width() - Theme.BorderWidth * 2 - Theme.Padding * 2) / - 2; - - var topLine = new StringBuilder(); - topLine.Append("┌"); - topLine.Append('─'.Repeat(lineWidth)); - topLine.AppendFormat("{0}{1}{0}", ' '.Repeat(Theme.Padding), title); - if (title.Width() % 2 == 1) topLine.Append('─'); - - topLine.Append('─'.Repeat(lineWidth)); - topLine.Append("┐"); - Console.WriteLine(topLine.ToString().Primary(isFocused)); - } -} \ No newline at end of file diff --git a/src/TUI/Controls/Display.cs b/src/TUI/Controls/Display.cs deleted file mode 100644 index 3bff348..0000000 --- a/src/TUI/Controls/Display.cs +++ /dev/null @@ -1,97 +0,0 @@ -using TUI.Dashboards; -using TUI.Domain; -using TUI.UserInterface; - - -namespace TUI.Controls; - -public class Display -{ - public readonly CommandLine CommandLine; - - public readonly Copyright Copyright; - - public readonly DependencyDashboard DependencyDashboard; - public readonly Header Header; - private bool _commandLineInDisplay; - - private Project _currentProject; - private bool _headerInDisplay = true; - - public Display() - { - Header = new Header(); - Copyright = new Copyright(); - CommandLine = new CommandLine(); - DependencyDashboard = new DependencyDashboard(); - Render(); - } - - public string FocusedElement { get; set; } = ""; - - public void OpenDeps(Project project) - { - _currentProject = project; - var dashboardPosition = new Position(0, Header.Height); - DependencyDashboard.IsFocused = true; - CommandLine.IsFocused = false; - DependencyDashboard.Render(_currentProject, dashboardPosition); - } - - private void ResizeDependencies() - { - var topPosition = 0; - topPosition += _commandLineInDisplay ? CommandLine.Height : 0; - topPosition += _headerInDisplay ? Header.Height : 0; - var dashboardPosition = new Position(0, topPosition); - DependencyDashboard.Render(_currentProject, dashboardPosition); - } - - public void Render() - { - var headerPosition = new Position(0, 0); - Header.Render(headerPosition); - - const string copyrightText = "Kolosov Aleksandr"; - var copyrightPosition = new Position( - Console.WindowWidth - copyrightText.Width(), - Console.WindowHeight); - Copyright.Render(copyrightText, copyrightPosition); - } - - public void ToggleHeader() - { - _headerInDisplay = !_headerInDisplay; - if (_headerInDisplay) - { - var headerPosition = new Position(0, 0); - Header.Render(headerPosition); - } - - ResizeDependencies(); - } - - public void Next() - { - DependencyDashboard.Next(); - } - - public void Previous() - { - DependencyDashboard.Previous(); - } - - public void OpenCommandLine() - { - var commandLinePosition = new Position(0, _headerInDisplay ? Header.Height : 0); - CommandLine.IsFocused = true; - DependencyDashboard.IsFocused = false; - FocusedElement = nameof(CommandLine); - CommandLine.Render(commandLinePosition); - _commandLineInDisplay = true; - ResizeDependencies(); - Console.SetCursorPosition(commandLinePosition.Left + Theme.Padding + Theme.BorderWidth + 2, - commandLinePosition.Top + Theme.BorderWidth); - Console.CursorVisible = true; - } -} \ No newline at end of file diff --git a/src/TUI/Controls/IControl.cs b/src/TUI/Controls/IControl.cs deleted file mode 100644 index 231c82b..0000000 --- a/src/TUI/Controls/IControl.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace TUI.Controls; - -public interface IControl -{ - void Render(Position position); -} - -public interface IControl -{ - // bool IsFocused { get; } - - void Render(TProps props, Position position, int? height); -} \ No newline at end of file diff --git a/src/TUI/Controls/Position.cs b/src/TUI/Controls/Position.cs deleted file mode 100644 index d9200b9..0000000 --- a/src/TUI/Controls/Position.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace TUI.Controls; - -public record Position(int Left, int Top); \ No newline at end of file diff --git a/src/TUI/Controls/Table.cs b/src/TUI/Controls/Table.cs deleted file mode 100644 index 1bf1249..0000000 --- a/src/TUI/Controls/Table.cs +++ /dev/null @@ -1,59 +0,0 @@ -using Pastel; -using TUI.UserInterface; - - -namespace TUI.Controls; - -public record TableProps(IEnumerable HeaderCells, - IEnumerable Rows, - int TitleWidth, - int ColumnWidth); - -public class Table : IControl -{ - private readonly Dictionary _rows = new(); - private Position _position; - private int _selectedRowId; - - public void Render(TableProps props, Position position, int? height = 0) - { - _position = position; - Console.SetCursorPosition(_position.Left, _position.Top); - - Console.Write(' '.Repeat(props.TitleWidth)); - foreach (var headerCell in props.HeaderCells) - Console.Write(' '.Repeat(props.ColumnWidth - headerCell.Width()) + headerCell); - } - - public void RenderRow(int rowId, string rowText, string? bgColor = default) - { - var padRight = ' '.Repeat(Console.WindowWidth - rowText.Width() - Theme.BorderWidth * 2); - _rows[rowId] = rowText + padRight; - - Console.SetCursorPosition(_position.Left, _position.Top + rowId); - Console.Write(string.IsNullOrEmpty(bgColor) ? rowText : rowText.PastelBg(bgColor)); - } - - public void Next() - { - if (_selectedRowId >= _rows.Count) return; - - RemoveHoverFromCurrentRow(); - RenderRow(++_selectedRowId, _rows[_selectedRowId], Palette.HoverColor); - } - - private void RemoveHoverFromCurrentRow() - { - if (_rows.TryGetValue(_selectedRowId, out var row)) RenderRow(_selectedRowId, row); - } - - public void Previous() - { - if (_selectedRowId == 0) Next(); - - if (_selectedRowId == 1) return; - - RemoveHoverFromCurrentRow(); - RenderRow(--_selectedRowId, _rows[_selectedRowId], Palette.HoverColor); - } -} \ No newline at end of file diff --git a/src/TUI/Dashboards/DependencyDashboard.cs b/src/TUI/Dashboards/DependencyDashboard.cs deleted file mode 100644 index 96fba08..0000000 --- a/src/TUI/Dashboards/DependencyDashboard.cs +++ /dev/null @@ -1,207 +0,0 @@ -using System.Diagnostics; -using System.Net; -using System.Text.Json; -using Pastel; -using TUI.Controls; -using TUI.Domain; -using TUI.Settings; -using TUI.UserInterface; - - -namespace TUI.Dashboards; - -public class DependencyDashboard : IControl -{ - private const int TitleWidth = 25; - private const int ColumnWidth = 10; - - private readonly static Dictionary Packages = new(); - private readonly Dashboard _dashboard = new(); - - private readonly Table _table = new(); - - public bool IsFocused - { - get => _dashboard.IsFocused; - set => _dashboard.IsFocused = value; - } - - public void Render(Project project, Position position, int? height = 0) - { - _dashboard.Render(project.Icon + " Dependencies", position); - var header = project.Dependencies.Select(GetConventionVersion).ToArray(); - var rows = project.Sources.Select(GetTitle).ToArray(); - - var tablePosition = new Position( - position.Left + Theme.BorderWidth, - position.Top + Theme.BorderWidth); - - var tableProps = new TableProps(header, rows, TitleWidth, ColumnWidth); - - _table.Render(tableProps, tablePosition); - - for (var rowId = 0; rowId < rows.Length; rowId++) - { - var actualDependencies = GetDependencies(project.Sources[rowId], project.Dependencies); - _table.RenderRow(rowId + 1, rows[rowId] + actualDependencies); - } - } - - private static string GetDependencies(SourceDto sourceDto, IEnumerable conventionDependencies) - { - try - { - var package = DownloadPackage(sourceDto); - - return string.Join("", - conventionDependencies - .Select(dependency => GetVersion(dependency, package)) - .Select(RenderCurrentVersion)); - } - catch (HttpRequestException exception) - { - switch (exception.StatusCode) - { - case HttpStatusCode.BadRequest: - return " Request have errors.".Pastel(Palette.ErrorColor); - case HttpStatusCode.Forbidden: - return " Not enough rights.".Pastel(Palette.ErrorColor); - case HttpStatusCode.NotFound: - return " Repository or branch master not found.".Pastel(Palette.ErrorColor); - } - - throw; - } - catch (Exception exception) - { - Debugger.Break(); - return "󰋔 We tried to send a request but couldn't. Check your configuration.".Pastel(Palette.ErrorColor); - } - } - - - private static string GetVersion(DependencyDto dependency, Package package) - { - var currentVersion = package.ParseVersion(dependency.Name); - - if (currentVersion == null) return Icons.NotFound; - - var conventionVersion = dependency.Version?.ToVersion(); - return PaintingVersion(currentVersion, conventionVersion); - } - - private static string PaintingVersion(Version current, Version? convention) - { - var textVersion = current.ToString(); - - if (current > convention) return textVersion.Info(); - - if (current < convention) - return current.Major == convention.Major ? textVersion.Primary() : textVersion.Warning(); - - return textVersion.Hint(); - } - - private static Package DownloadPackage(SourceDto sourceDto) - { - var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo; - if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; - - using HttpClient client = new(); - var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); - var package = JsonSerializer.Deserialize(json); - Packages.Add(endpoint, package); - return package; - } - - private static string GetGitlabEndpoint(SourceDto sourceDto) - { - var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); - return $"{sourceDto.Repo}/api/v4/projects/{sourceDto.ProjectId}/repository/files/package.json/raw?" + - $"private_token={token}&ref=dev"; - } - - private static string GetConventionVersion(DependencyDto dependencyDto) - { - return dependencyDto.Icon.Pastel(dependencyDto.Color) + dependencyDto.Version.Primary(); - } - - private static string RenderCurrentVersion(string version) - { - var versionWidth = version.Width(); - if (versionWidth == 0) return ' '.Repeat(ColumnWidth - 1) + Icons.NotFound.Hint(); - - return ' '.Repeat(ColumnWidth - versionWidth) + version; - } - - private static string GetTitle(SourceDto sourceDto) - { - var title = ""; - - title += RenderPadding(); - title += RenderTags(sourceDto); - if (title.Width() + sourceDto.Name.Length + Theme.Padding <= TitleWidth) - { - title += sourceDto.Name; - } - else - { - var maxNameWidth = TitleWidth - title.Width() - Theme.Padding; - title += $"{sourceDto.Name[..(maxNameWidth - 1)]}{"#".Hint()}"; - } - - title += RenderPadding(); - return $"{title}{' '.Repeat(TitleWidth - title.Width())}"; - } - - private static string RenderPadding() - { - return new string(' ', Theme.Padding); - } - - private static string RenderTags(SourceDto sourceDto) - { - var tags = ""; - tags += GetGitApplication(sourceDto); - tags += " "; - tags += sourceDto.Tags.Have("public") ? Icons.NetworkPublic : Icons.NetworkPrivate; - tags += " "; - tags += sourceDto.Tags.Have("seo") ? Icons.SEO : Icons.SEO.Disable(); - tags += " "; - tags += sourceDto.Tags.Have("auth") ? Icons.Auth : Icons.Auth.Disable(); - tags += " "; - tags += GetApplicationType(sourceDto); - tags += " "; - - return tags; - } - - private static string GetApplicationType(SourceDto sourceDto) - { - foreach (var application in Icons.Applications) - if (sourceDto.Tags.Have(application.Value)) - return application.Key; - - return Icons.Undefined; - } - - private static string GetGitApplication(SourceDto sourceDto) - { - return sourceDto.Repo switch - { - { } url when url.Contains("gitlab") => Icons.GitLab, - { } url when url.Contains("github") => Icons.GitHub, - _ => Icons.Git - }; - } - - public void Next() - { - _table.Next(); - } - - public void Previous() - { - _table.Previous(); - } -} \ No newline at end of file diff --git a/src/TUI/Domain/DevelopmentStack.cs b/src/TUI/Domain/DevelopmentStack.cs new file mode 100644 index 0000000..e24631b --- /dev/null +++ b/src/TUI/Domain/DevelopmentStack.cs @@ -0,0 +1,3 @@ +namespace TUI.Domain; + +public record DevelopmentStack(string Name, char Icon); \ No newline at end of file diff --git a/src/TUI/Domain/Project.cs b/src/TUI/Domain/ProjectDto.cs similarity index 70% rename from src/TUI/Domain/Project.cs rename to src/TUI/Domain/ProjectDto.cs index dc08f5b..df48aa4 100644 --- a/src/TUI/Domain/Project.cs +++ b/src/TUI/Domain/ProjectDto.cs @@ -1,21 +1,27 @@ +using System.Runtime.Serialization; using TUI.Settings; using YamlDotNet.Serialization; namespace TUI.Domain; +[DataContract] [YamlSerializable] -public class Project +public class ProjectDto { [YamlMember] + [DataMember] public string Icon { get; set; } [YamlMember] + [DataMember] public string Name { get; set; } [YamlMember] + [DataMember] public DependencyDto[] Dependencies { get; set; } [YamlMember] + [DataMember] public IList Sources { get; set; } } \ No newline at end of file diff --git a/src/TUI/Domain/Settings.cs b/src/TUI/Domain/Settings.cs index 41085f8..6f03fe8 100644 --- a/src/TUI/Domain/Settings.cs +++ b/src/TUI/Domain/Settings.cs @@ -8,7 +8,7 @@ namespace TUI.Domain; public class Settings { [YamlMember] - public Project[] Projects { get; set; } + public ProjectDto[] Projects { get; set; } public static Settings Init() { diff --git a/src/TUI/Engine/Helper.cs b/src/TUI/Engine/Helper.cs new file mode 100644 index 0000000..8c7a1ad --- /dev/null +++ b/src/TUI/Engine/Helper.cs @@ -0,0 +1,46 @@ +using Pastel; +using TUI.Engine.Nodes; +using TUI.Engine.Nodes.Attributes; + +namespace TUI.Engine; + +public static class Helper +{ + private static readonly Queue Colors = new(); + + static Helper() + { + Colors.Enqueue(ConsoleColor.DarkYellow); + Colors.Enqueue(ConsoleColor.DarkMagenta); + Colors.Enqueue(ConsoleColor.DarkGreen); + Colors.Enqueue(ConsoleColor.DarkCyan); + Colors.Enqueue(ConsoleColor.DarkBlue); + Colors.Enqueue(ConsoleColor.DarkRed); + Colors.Enqueue(ConsoleColor.Cyan); + Colors.Enqueue(ConsoleColor.Yellow); + } + + public static void ShowBackground(NodePosition position, Size size) + { + return; + var color = Colors.Dequeue(); + var top = position.Top; + var height = 0; + + while (height < size.Height) + { + var left = position.Left; + var width = 0; + while (width < size.Width) + { + Console.SetCursorPosition(left, top); + Console.Write(Symbols.Space.ToString().PastelBg(color)); + width++; + left++; + } + + height++; + top++; + } + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs new file mode 100644 index 0000000..1ddb95c --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs @@ -0,0 +1,3 @@ +namespace TUI.Engine.Nodes.Attributes.Alignments; + +public record Alignment(Horizontal Horizontal, Vertical Vertical); \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs new file mode 100644 index 0000000..cbc839a --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs @@ -0,0 +1,8 @@ +namespace TUI.Engine.Nodes.Attributes.Alignments; + +public enum Horizontal +{ + Left = 0, + Center = 1, + Right = 2, +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs new file mode 100644 index 0000000..56067a2 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs @@ -0,0 +1,8 @@ +namespace TUI.Engine.Nodes.Attributes.Alignments; + +public interface IWithAlignment where TNode : INode +{ + public Alignment Alignment { get; } + + public TNode Set(Horizontal horizontal = Horizontal.Left, Vertical vertical = Vertical.Top); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs new file mode 100644 index 0000000..f03c6fa --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs @@ -0,0 +1,8 @@ +namespace TUI.Engine.Nodes.Attributes.Alignments; + +public enum Vertical +{ + Top, + Center, + Bottom, +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs b/src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs new file mode 100644 index 0000000..493fc45 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs @@ -0,0 +1,17 @@ +using TUI.Engine.Theme; + +namespace TUI.Engine.Nodes.Attributes.Paddings; + +public interface IWithPadding where TNode : INode +{ + public Padding? Padding { get; } + + public TNode Set(Level padding); + + public TNode Set( + Level? left = Level.None, + Level? top = Level.None, + Level? right = Level.None, + Level? bottom = Level.None + ); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs b/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs new file mode 100644 index 0000000..f7ccf52 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs @@ -0,0 +1,15 @@ +using TUI.Engine.Theme; + +namespace TUI.Engine.Nodes.Attributes.Paddings; + +public record Padding( + Level? Left = Level.None, + Level? Top = Level.None, + Level? Right = Level.None, + Level? Bottom = Level.None +) +{ + public Padding(Level padding) : this(Left: padding, Top: padding, Right: padding, Bottom: padding) + { + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Size.cs b/src/TUI/Engine/Nodes/Attributes/Size.cs new file mode 100644 index 0000000..d0c7689 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Size.cs @@ -0,0 +1,6 @@ +namespace TUI.Engine.Nodes.Attributes; + +public record Size(int Width, int Height) +{ + public override string ToString() => $"W[{Width}] H[{Height}]"; +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentBase.cs b/src/TUI/Engine/Nodes/Components/ComponentBase.cs new file mode 100644 index 0000000..05caf8f --- /dev/null +++ b/src/TUI/Engine/Nodes/Components/ComponentBase.cs @@ -0,0 +1,45 @@ +using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Nodes.Attributes.Paddings; +using TUI.Engine.Theme; + +namespace TUI.Engine.Nodes.Components; + +public abstract class ComponentBase : List, IComponent +{ + public abstract Content Render(); + + #region Alignments + + public Alignment Alignment { get; private set; } = new(Horizontal.Center, Vertical.Top); + + public IComponent Set(Horizontal horizontal = Horizontal.Left, Vertical vertical = Vertical.Top) + { + Alignment = new Alignment(horizontal, vertical); + return this; + } + + #endregion + + #region Paddings + + public Padding Padding { get; private set; } = new(Level.None); + + public IComponent Set(Level padding) + { + Padding = new Padding(padding); + return this; + } + + public IComponent Set( + Level? left = Level.None, + Level? top = Level.None, + Level? right = Level.None, + Level? bottom = Level.None + ) + { + Padding = new Padding(left, top, right, bottom); + return this; + } + + #endregion +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs b/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs new file mode 100644 index 0000000..6e9a3ce --- /dev/null +++ b/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs @@ -0,0 +1,24 @@ +using System.Text; + +namespace TUI.Engine.Nodes.Components; + +public abstract class ComponentStaticBase : ComponentBase +{ + private Content? _cache; + + protected abstract void RenderWithCache(StringBuilder builder); + + public override Content Render() + { + if (_cache is not null) + { + return _cache; + } + + var builder = new StringBuilder(); + RenderWithCache(builder); + _cache = new Content(builder.ToString()); + + return _cache; + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/Content.cs b/src/TUI/Engine/Nodes/Components/Content.cs new file mode 100644 index 0000000..d357bb1 --- /dev/null +++ b/src/TUI/Engine/Nodes/Components/Content.cs @@ -0,0 +1,26 @@ +using TUI.Engine.Nodes.Attributes; + +namespace TUI.Engine.Nodes.Components; + +public sealed class Content : IEnumerable +{ + private IEnumerable ContentRows { get; } + + public Content(string content) => ContentRows = content.Split(Symbols.LineBreak); + + public IEnumerator GetEnumerator() => ContentRows.GetEnumerator(); + + public IEnumerable Rows(int maxWidth, int maxHeight) => + ContentRows.Where(row => maxWidth >= row.Width()).Take(maxHeight).ToArray(); + + public Size GetSize() + { + var width = ContentRows.Select(row => row.Width()).DefaultIfEmpty(0).Max(); + var height = ContentRows.Count(); + return new Size(width, height); + } + + public override string ToString() => string.Join(Symbols.LineBreak, ContentRows); + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => GetEnumerator(); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/IComponent.cs b/src/TUI/Engine/Nodes/Components/IComponent.cs new file mode 100644 index 0000000..4a841cc --- /dev/null +++ b/src/TUI/Engine/Nodes/Components/IComponent.cs @@ -0,0 +1,11 @@ +using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Nodes.Attributes.Paddings; + +namespace TUI.Engine.Nodes.Components; + +public interface IComponent : INode, + IWithAlignment, + IWithPadding +{ + Content Render(); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/IContainer.cs b/src/TUI/Engine/Nodes/Containers/IContainer.cs new file mode 100644 index 0000000..aac4955 --- /dev/null +++ b/src/TUI/Engine/Nodes/Containers/IContainer.cs @@ -0,0 +1,8 @@ +namespace TUI.Engine.Nodes.Containers; + +public interface IContainer : INode +{ + public Orientation Orientation { get; } + + public Nodes Nodes { get; } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/Orientation.cs b/src/TUI/Engine/Nodes/Containers/Orientation.cs new file mode 100644 index 0000000..f53ba11 --- /dev/null +++ b/src/TUI/Engine/Nodes/Containers/Orientation.cs @@ -0,0 +1,7 @@ +namespace TUI.Engine.Nodes.Containers; + +public enum Orientation +{ + Horizontal, + Vertical, +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/INode.cs b/src/TUI/Engine/Nodes/INode.cs new file mode 100644 index 0000000..52874c7 --- /dev/null +++ b/src/TUI/Engine/Nodes/INode.cs @@ -0,0 +1,5 @@ +namespace TUI.Engine.Nodes; + +public interface INode +{ +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/NodePosition.cs b/src/TUI/Engine/Nodes/NodePosition.cs new file mode 100644 index 0000000..b0c9cf5 --- /dev/null +++ b/src/TUI/Engine/Nodes/NodePosition.cs @@ -0,0 +1,6 @@ +namespace TUI.Engine.Nodes; + +public record NodePosition(int Left, int Top) +{ + public override string ToString() => $"L[{Left}] T[{Top}]"; +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Nodes.cs b/src/TUI/Engine/Nodes/Nodes.cs new file mode 100644 index 0000000..0f58be7 --- /dev/null +++ b/src/TUI/Engine/Nodes/Nodes.cs @@ -0,0 +1,5 @@ +namespace TUI.Engine.Nodes; + +public class Nodes : List +{ +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs b/src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs new file mode 100644 index 0000000..75235dc --- /dev/null +++ b/src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs @@ -0,0 +1,129 @@ +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 + }; +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleWindow.cs b/src/TUI/Engine/Rendering/ConsoleWindow.cs new file mode 100644 index 0000000..20908ae --- /dev/null +++ b/src/TUI/Engine/Rendering/ConsoleWindow.cs @@ -0,0 +1,9 @@ +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); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IRenderingEngine.cs b/src/TUI/Engine/Rendering/IRenderingEngine.cs new file mode 100644 index 0000000..9cc91bd --- /dev/null +++ b/src/TUI/Engine/Rendering/IRenderingEngine.cs @@ -0,0 +1,9 @@ +using TUI.Engine.Nodes.Attributes; +using TUI.Engine.Nodes.Containers; + +namespace TUI.Engine.Rendering; + +public interface IRenderingEngine +{ + void Render(IContainer container, Size? defaultSize); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IWindow.cs b/src/TUI/Engine/Rendering/IWindow.cs new file mode 100644 index 0000000..5fd7dc6 --- /dev/null +++ b/src/TUI/Engine/Rendering/IWindow.cs @@ -0,0 +1,9 @@ +namespace TUI.Engine.Rendering; + +public interface IWindow +{ + int Width { get; } + int Height { get; } + void SetCursorPosition(int left, int top); + void Write(string value); +} \ No newline at end of file diff --git a/src/TUI/Engine/Symbols.cs b/src/TUI/Engine/Symbols.cs new file mode 100644 index 0000000..ea35302 --- /dev/null +++ b/src/TUI/Engine/Symbols.cs @@ -0,0 +1,25 @@ +namespace TUI.Engine; + +public static class Symbols +{ + public const char Space = ' '; + public const char Copyright = '©'; + public const char GitLab = ''; + public const char GitHub = ''; + public const char Git = ''; + public const char LineBreak = '\n'; + + public static class Lines + { + public const char Vertical = '│'; + public const char Horizontal = '─'; + } + + public static class Angles + { + public const char RightTop = '┐'; + public const char LeftBottom = '└'; + public const char LeftTop = '┌'; + public const char RightBottom = '┘'; + } +} diff --git a/src/TUI/Engine/Theme/Indentation.cs b/src/TUI/Engine/Theme/Indentation.cs new file mode 100644 index 0000000..eb9d7d9 --- /dev/null +++ b/src/TUI/Engine/Theme/Indentation.cs @@ -0,0 +1,7 @@ +namespace TUI.Engine.Theme; + +public static class Indentation +{ + public const Level Default = Level.Normal; + public const Level BorderWidth = Level.Normal; +} \ No newline at end of file diff --git a/src/TUI/Engine/Theme/Level.cs b/src/TUI/Engine/Theme/Level.cs new file mode 100644 index 0000000..8c246fa --- /dev/null +++ b/src/TUI/Engine/Theme/Level.cs @@ -0,0 +1,7 @@ +namespace TUI.Engine.Theme; + +public enum Level +{ + None = 0, + Normal = 1 +} \ No newline at end of file diff --git a/src/TUI/Engine/Theme/Palette.cs b/src/TUI/Engine/Theme/Palette.cs new file mode 100644 index 0000000..4b700d0 --- /dev/null +++ b/src/TUI/Engine/Theme/Palette.cs @@ -0,0 +1,28 @@ +using Pastel; + +namespace TUI.Engine.Theme; + +public static class Palette +{ + private const string HoverColor = "292928"; + private const string PrimaryColor = "84BA64"; + private const string HintColor = "71797E"; + private const string ErrorColor = "CA3433"; + private const string WarningColor = "EC9706"; + private const string InfoColor = "25799F"; + + public static string Main(this string currentText, bool isFocused = true) => + isFocused + ? currentText.Pastel(PrimaryColor) + : Hint(currentText); + + public static string Hint(this string currentText) => currentText.Pastel(HintColor); + + public static string Disable(this string currentText) => currentText.RemoveColors().Pastel(HintColor); + + public static string Warning(this string currentText) => currentText.Pastel(WarningColor); + + public static string Error(this string currentText) => currentText.Pastel(ErrorColor); + + public static string Info(this string currentText) => currentText.Pastel(InfoColor); +} \ No newline at end of file diff --git a/src/TUI/Extensions.cs b/src/TUI/Extensions.cs index 4acb68f..63945e3 100644 --- a/src/TUI/Extensions.cs +++ b/src/TUI/Extensions.cs @@ -13,7 +13,7 @@ public static class Extensions public static string Repeat(this char symbol, int repeatCount) { - return repeatCount < 0 ? "" : new string(symbol, repeatCount); + return repeatCount < 0 ? string.Empty : new string(symbol, repeatCount); } public static string RemoveColors(this string text) @@ -30,7 +30,7 @@ public static class Extensions return stringInfo.LengthInTextElements; } - public static Version? ToVersion(this string textVersion) + public static Version ToVersion(this string textVersion) { var version = textVersion.Replace("^", "").Replace("~", "").Split("."); var major = Convert.ToInt32(version[0]); diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs new file mode 100644 index 0000000..b535af6 --- /dev/null +++ b/src/TUI/Pages/DependenciesPage.cs @@ -0,0 +1,103 @@ +using System.Diagnostics; +using TUI.Components.Controls; +using TUI.Components.Layouts; +using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Rendering; +using TUI.Engine.Theme; + +namespace TUI.Pages; + +public class DependenciesPage +{ + public void Open() + { + Debugger.Log(0, "Event", "Open page dependencies\n"); + + var window = new ConsoleWindow(); + var renderEngine = new ConsoleRenderingEngine(window); + var header = new HeaderContainer(); + var copyright = new Copyright() + .Set(right: Level.Normal) + .Set(Horizontal.Right, Vertical.Bottom); + + var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright); + // CommandLine = new CommandLine(); + // DependenciesView = new DependenciesView(); + renderEngine.Render(layout); + } + + // private bool _commandLineInDisplay; + + // private ProjectDto _currentProjectDto; + + // private bool _headerInDisplay = true; + + + // public string FocusedElement { get; set; } = ""; + + // public void OpenDeps(ProjectDto projectDto) + // { + // _currentProjectDto = projectDto; + // var dashboardPosition = new ControlPosition(0, Header.Height); + // // DependencyDashboard.IsFocused = true; + // // CommandLine.IsFocused = false; + // DependenciesView.Render(_currentProjectDto, dashboardPosition); + // } + // + // private void ResizeDependencies() + // { + // var topPosition = 0; + // topPosition += _commandLineInDisplay ? CommandLine.Height : 0; + // topPosition += _headerInDisplay ? Header.Height : 0; + // var dashboardPosition = new ControlPosition(0, topPosition); + // DependenciesView.Render(_currentProjectDto, dashboardPosition); + // } + // + // public void Render() + // { + // var headerPosition = new ControlPosition(0, 0); + // Header.Render(headerPosition); + // + // const string copyrightText = "Kolosov Aleksandr"; + // var copyrightPosition = new ControlPosition( + // Console.WindowWidth - copyrightText.Width(), + // Console.WindowHeight); + // CopyrightControl.Render(copyrightText, copyrightPosition); + // } + // + // public void ToggleHeader() + // { + // _headerInDisplay = !_headerInDisplay; + // if (_headerInDisplay) + // { + // var headerPosition = new ControlPosition(0, 0); + // Header.Render(headerPosition); + // } + // + // ResizeDependencies(); + // } + // + // public void Next() + // { + // DependenciesView.Next(); + // } + // + // public void Previous() + // { + // DependenciesView.Previous(); + // } + // + // public void OpenCommandLine() + // { + // var commandLinePosition = new ControlPosition(0, _headerInDisplay ? Header.Height : 0); + // // CommandLine.IsFocused = true; + // // DependencyDashboard.IsFocused = false; + // FocusedElement = nameof(CommandLine); + // CommandLine.Render(commandLinePosition); + // _commandLineInDisplay = true; + // ResizeDependencies(); + // Console.SetCursorPosition(commandLinePosition.Left + Theme.Padding + Theme.BorderWidth + 2, + // commandLinePosition.Top + Theme.BorderWidth); + // Console.CursorVisible = true; + // } +} \ No newline at end of file diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index 5ea9cc9..775f06f 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -1,60 +1,61 @@ -using TUI.Controls; -using TUI.Domain; +using TUI.Pages; Console.Clear(); Console.CursorVisible = false; -var settings = Settings.Init(); +// var settings = Settings.Init(); -var display = new Display(); -display.OpenDeps(settings.Projects[0]); +var dependenciesPage = new DependenciesPage(); +dependenciesPage.Open(); + +// display.OpenDeps(settings.Projects[0]); var key = new ConsoleKeyInfo('1', ConsoleKey.NoName, false, false, false); var waitCommand = true; do { - if (key.Key == ConsoleKey.Q && !display.CommandLine.IsFocused) - { - waitCommand = false; - continue; - } - - if (display.CommandLine.IsFocused) - { - switch (key.Key) - { - case ConsoleKey.Escape: - display.CommandLine.IsFocused = false; - break; - default: - Console.Write(key.KeyChar); - - break; - } - } - else - { - switch (key.KeyChar) - { - case ':': - display.OpenCommandLine(); - break; - } - - switch (key.Key) - { - case ConsoleKey.DownArrow: - display.Next(); - break; - case ConsoleKey.UpArrow: - display.Previous(); - break; - case ConsoleKey.E: - display.ToggleHeader(); - break; - } - } + // if (key.Key == ConsoleKey.Q && !display.CommandLine.IsFocused) + // { + // waitCommand = false; + // continue; + // } + // + // if (display.CommandLine.IsFocused) + // { + // switch (key.Key) + // { + // case ConsoleKey.Escape: + // display.CommandLine.IsFocused = false; + // break; + // default: + // Console.Write(key.KeyChar); + // + // break; + // } + // } + // else + // { + // switch (key.KeyChar) + // { + // case ':': + // display.OpenCommandLine(); + // break; + // } + // + // switch (key.Key) + // { + // case ConsoleKey.DownArrow: + // display.Next(); + // break; + // case ConsoleKey.UpArrow: + // display.Previous(); + // break; + // case ConsoleKey.E: + // display.Toggle(); + // break; + // } + // } key = Console.ReadKey(true); } while (waitCommand); diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs new file mode 100644 index 0000000..141484f --- /dev/null +++ b/src/TUI/Store/DependenciesStore.cs @@ -0,0 +1,29 @@ +using System.Text.Json; +using TUI.Domain; +using TUI.Settings; + +namespace TUI.Store; + +public static class DependenciesStore +{ + private readonly static Dictionary Packages = new(); + + private static Package DownloadPackage(SourceDto sourceDto) + { + var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo; + if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; + + using HttpClient client = new(); + var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); + var package = JsonSerializer.Deserialize(json); + Packages.Add(endpoint, package); + return package; + } + + private static string GetGitlabEndpoint(SourceDto sourceDto) + { + var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); + return $"{sourceDto.Repo}/api/v4/projects/{sourceDto.ProjectId}/repository/files/package.json/raw?" + + $"private_token={token}&ref=dev"; + } +} \ No newline at end of file diff --git a/src/TUI/UserInterface/CommandLine.cs b/src/TUI/UserInterface/CommandLine.cs index 20969fb..a4cd92a 100644 --- a/src/TUI/UserInterface/CommandLine.cs +++ b/src/TUI/UserInterface/CommandLine.cs @@ -1,17 +1,19 @@ -using TUI.Controls; - - -namespace TUI.UserInterface; - -public class CommandLine : Dashboard -{ - public const int Height = 3; - - public void Render(Position position) - { - base.Render("Command", position, Height); - - Console.SetCursorPosition(position.Left + Theme.BorderWidth + Theme.Padding, position.Top + Theme.BorderWidth); - Console.Write(">"); - } -} \ No newline at end of file +// using TUI.Components.Controls; +// using TUI.Engine; +// using TUI.Engine.Controls; +// +// +// namespace TUI.UserInterface; +// // +// // public class CommandLine : DashboardControl +// // { +// // public const int Height = 3; +// // +// // public void Render(ControlPosition position) +// // { +// // base.Render("Command", position, Height); +// // +// // Console.SetCursorPosition(position.Left + Theme.BorderWidth + Theme.Padding, position.Top + Theme.BorderWidth); +// // Console.Write(">"); +// // } +// // } \ No newline at end of file diff --git a/src/TUI/UserInterface/Header.cs b/src/TUI/UserInterface/Header.cs deleted file mode 100644 index bda1a3f..0000000 --- a/src/TUI/UserInterface/Header.cs +++ /dev/null @@ -1,79 +0,0 @@ -using TUI.Controls; - - -namespace TUI.UserInterface; - -public class Header : IControl -{ - public const int LogoWidth = 16; - public const int Height = 6; - public const int MaxHeaderBlocksWidth = 16; - - private readonly Dictionary _hints = new() - { - { "󰎔", "too new".Info() }, - { "", "so good" }, - { "", "be nice".Primary() }, - { "󰬟", "too old".Warning() } - }; - - - private readonly Dictionary _hotKeys = new() - { - { "", "select prev" }, - { "", "select next" }, - { "󰬌", "toggle head" }, - { "󰬘", "quit" } - }; - - private readonly Dictionary _tags = new() - { - { Icons.Auth, "Auth" }, - { Icons.NetworkPublic, "WWW" }, - { Icons.SEO, "SEO" }, - { Icons.GitLab, "VCS" } - }; - - public void Render(Position position) - { - Console.SetCursorPosition(position.Left, position.Top); - - for (var i = 1; i <= Height; i++) Console.WriteLine(new string(' ', Console.WindowWidth - LogoWidth)); - - RenderBlock(0, _hints); - RenderBlock(1, _tags); - RenderBlock(2, Icons.Applications); - RenderBlock(3, _hotKeys); - RenderLogo(); - } - - private static void RenderBlock(int blockNumber, Dictionary items) - { - var leftPadding = Theme.Padding + blockNumber * MaxHeaderBlocksWidth; - - var hotKeyNumber = 0; - foreach (var item in items) - { - Console.SetCursorPosition(leftPadding, Theme.Padding + hotKeyNumber++); - Console.Write((item.Key + " " + item.Value).Hint()); - } - } - - - private static void RenderLogo() - { - Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 0); - Console.WriteLine(" ╭━━━━┳╮".Primary() + "╱╱".Hint() + "╭━━━╮ ".Primary()); - Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 1); - Console.WriteLine(" ┃╭╮╭╮┃┃".Primary() + "╱╱".Hint() + "╰╮╭╮┃ ".Primary()); - Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 2); - Console.WriteLine(" ╰╯┃┃╰┫┃".Primary() + "╱╱╱".Hint() + "┃┃┃┃ ".Primary()); - Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 3); - Console.WriteLine(" ╱╱".Hint() + "┃┃".Primary() + "╱".Hint() + "┃┃".Primary() + "╱".Hint() + - "╭╮┃┃┃┃ ".Primary()); - Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 4); - Console.WriteLine(" ╱╱╱".Hint() + "┃┃".Primary() + "╱".Hint() + "┃╰━╯┣╯╰╯┃ ".Primary()); - Console.SetCursorPosition(Console.WindowWidth - LogoWidth - Theme.Padding, 5); - Console.WriteLine("╱╱╱╱".Hint() + "╰╯".Primary() + "╱".Hint() + "╰━━━┻━━━╯ ".Primary()); - } -} \ No newline at end of file diff --git a/src/TUI/UserInterface/Icons.cs b/src/TUI/UserInterface/Icons.cs index fb6976c..b86cc29 100644 --- a/src/TUI/UserInterface/Icons.cs +++ b/src/TUI/UserInterface/Icons.cs @@ -1,4 +1,5 @@ using Pastel; +using TUI.Engine.Theme; namespace TUI.UserInterface; @@ -13,22 +14,22 @@ public static class Icons { Api, "api" } }; - public static string GitLab => GetIcon("", "E24329"); - public static string GitHub => GetIcon("", "ADBAC7"); - public static string Git => GetIcon("", "F14E32"); + public static string GitLab => GetIcon("", "E24329"); + public static string GitHub => GetIcon("", "ADBAC7"); + public static string Git => GetIcon("", "F14E32"); public static string NetworkPublic => GetIcon("󰞉", "00FFFF"); public static string NetworkPrivate => GetIcon("󰕑"); public static string Undefined => GetIcon(""); - public static string Site => GetIcon("", "BF40BF"); - public static string Api => GetIcon("", "7F52FF"); + public static string Site => GetIcon("", "BF40BF"); + public static string Api => GetIcon("", "7F52FF"); public static string DockerImage => GetIcon("󰡨", "086DD7"); - public static string NpmPackage => GetIcon("", "CB0000"); - public static string SEO => GetIcon("󰚩", "4285F4"); - public static string Auth => GetIcon("", "FFD700"); + public static string NpmPackage => GetIcon("", "CB0000"); + public static string SEO => GetIcon("󰚩", "4285F4"); + public static string Auth => GetIcon("", "FFD700"); public static string NotFound => GetIcon(""); private static string GetIcon(string icon, string? activeColor = null) { - return icon.Pastel(activeColor ?? Palette.HintColor); + return activeColor != null ? icon.Pastel(activeColor) : icon.Hint(); } } \ No newline at end of file diff --git a/src/TUI/UserInterface/Palette.cs b/src/TUI/UserInterface/Palette.cs deleted file mode 100644 index 8cc3f6f..0000000 --- a/src/TUI/UserInterface/Palette.cs +++ /dev/null @@ -1,46 +0,0 @@ -using Pastel; - - -namespace TUI.UserInterface; - -public static class Palette -{ - public const string HoverColor = "292928"; - public const string PrimaryColor = "84BA64"; - public const string HintColor = "71797E"; - public const string ErrorColor = "CA3433"; - public const string WarningColor = "EC9706"; - public const string InfoColor = "25799F"; - - public static string Primary(this string currentText, bool isFocused = true) - { - return isFocused - ? currentText.Pastel(PrimaryColor) - : Hint(currentText); - } - - public static string Hint(this string currentText) - { - return currentText.Pastel(HintColor); - } - - public static string Disable(this string currentText) - { - return currentText.RemoveColors().Pastel(HintColor); - } - - public static string Warning(this string currentText) - { - return currentText.Pastel(WarningColor); - } - - public static string Error(this string currentText) - { - return currentText.Pastel(ErrorColor); - } - - public static string Info(this string currentText) - { - return currentText.Pastel(InfoColor); - } -} \ No newline at end of file diff --git a/src/TUI/UserInterface/Panel.cs b/src/TUI/UserInterface/Panel.cs index 9bba507..157062e 100644 --- a/src/TUI/UserInterface/Panel.cs +++ b/src/TUI/UserInterface/Panel.cs @@ -1,3 +1,4 @@ +using TUI.Engine.Theme; using TUI.Settings; @@ -18,9 +19,9 @@ public static class Panel { for (var index = 0; index < sources.Length; index++) { - Console.SetCursorPosition(Theme.Padding, - 6 + index + _marginTop + BorderWidth + - Theme.Padding); + Console.SetCursorPosition(Convert.ToInt32(Indentation.Default), + 6 + index + _marginTop + BorderWidth + + Convert.ToInt32(Indentation.Default)); if (selectedRowNumber == index + 1) { @@ -32,7 +33,7 @@ public static class Panel for (var index = 0; index < sources.Length; index++) Console.SetCursorPosition(TitleWidth, - 6 + index + _marginTop + BorderWidth + Theme.Padding); + 6 + index + _marginTop + BorderWidth + Convert.ToInt32(Indentation.Default)); // var source = sources[index]; // var package = DownloadPackage(source); // var resultText = package.Dependencies.React; diff --git a/src/TUI/UserInterface/Theme.cs b/src/TUI/UserInterface/Theme.cs deleted file mode 100644 index dec24e8..0000000 --- a/src/TUI/UserInterface/Theme.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TUI.UserInterface; - -public static class Theme -{ - public static int Padding = 1; - public static int BorderWidth = 1; -} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs b/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs new file mode 100644 index 0000000..77bb47a --- /dev/null +++ b/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs @@ -0,0 +1,63 @@ +using FluentAssertions; +using TUI.Components.Controls.Statics; +using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Theme; + +namespace Widgets.Tests; + +public class ComponentBaseTests +{ + [Fact] + public void WhenUseChainingSaveAllChange() + { + var component = new Logo() + .Set(Level.Normal) + .Set(vertical: Vertical.Center, horizontal: Horizontal.Center); + + component.Padding.Top.Should().Be(Level.Normal); + component.Padding.Left.Should().Be(Level.Normal); + component.Padding.Bottom.Should().Be(Level.Normal); + component.Padding.Right.Should().Be(Level.Normal); + component.Alignment.Horizontal.Should().Be(Horizontal.Center); + component.Alignment.Vertical.Should().Be(Vertical.Center); + } + + [Fact] + public void WhenSetPaddingsSaveAllChange() + { + var component = new Logo(); + + component.Set(Level.Normal); + + component.Padding.Top.Should().Be(Level.Normal); + component.Padding.Left.Should().Be(Level.Normal); + component.Padding.Bottom.Should().Be(Level.Normal); + component.Padding.Right.Should().Be(Level.Normal); + } + + [Theory] + [InlineData(Vertical.Bottom)] + [InlineData(Vertical.Center)] + [InlineData(Vertical.Top)] + public void WhenSetVerticalAlignSaveAllChange(Vertical alignment) + { + var component = new Logo(); + + component.Set(vertical: alignment); + + component.Alignment.Vertical.Should().Be(alignment); + } + + [Theory] + [InlineData(Horizontal.Left)] + [InlineData(Horizontal.Center)] + [InlineData(Horizontal.Right)] + public void WhenSetHorizontalAlignSaveAllChange(Horizontal alignment) + { + var component = new Logo(); + + component.Set(horizontal: alignment); + + component.Alignment.Horizontal.Should().Be(alignment); + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs b/tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs new file mode 100644 index 0000000..08ad62a --- /dev/null +++ b/tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs @@ -0,0 +1,184 @@ +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(c => + c.Render() == new Content("Lorem") && + c.Alignment == new Alignment(Horizontal.Left, Vertical.Top)); + } + + [Fact] + public void RenderSimple() + { + var window = Mock.Of(w => w.Width == 9 && w.Height == 1); + var nodes = new Nodes { _component }; + var root = Mock.Of(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(w => w.Width == windowSize && w.Height == windowSize); + var component = Mock.Of(c => c.Render() == new Content(content) && + c.Alignment == new Alignment(alignment, Vertical.Top)); + var nodes = new Nodes { component }; + var root = Mock.Of(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(w => w.Width == windowSize && w.Height == windowSize); + var component = Mock.Of(c => c.Render() == new Content(content) && + c.Alignment == new Alignment(Horizontal.Left, alignment)); + var nodes = new Nodes { component }; + var root = Mock.Of(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(w => w.Width == 6 && w.Height == 5); + var component = Mock.Of(c => c.Render() == new Content("VV") && + c.Alignment == new Alignment(horizontal, vertical)); + var nodes = new Nodes { component }; + var root = Mock.Of(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(w => w.Width == rootWidth && w.Height == rootHeight); + var nodes = new Nodes { _component, _component }; + var root = Mock.Of(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(w => w.Height == 2 && w.Width == 10); + var nodes = new Nodes { _component, _component }; + var root = Mock.Of(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(w => w.Width == 10 && w.Height == 1); + var nodes = new Nodes { _component, _component }; + var container = Mock.Of(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(w => w.Width == 24 && w.Height == 1); + var nodes = new Nodes { _component, _component, _component, _component }; + var root = Mock.Of(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(w => w.Width == 10 && w.Height == 2); + var container = Mock.Of(c => c.Nodes == new Nodes { _component }); + var nodes = new Nodes { container, _component }; + var root = Mock.Of(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)); + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs new file mode 100644 index 0000000..cc3273c --- /dev/null +++ b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs @@ -0,0 +1,18 @@ +using TUI.Components.Controls.Statics; + +namespace Widgets.Tests.Controls; + +public class LogoTests +{ + [Fact] + public void Simple() + { + var logo = new Logo(); + + var render = logo.Render().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); + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/TUI.Tests.csproj b/tests/WIdgets/TUI.Tests/TUI.Tests.csproj new file mode 100644 index 0000000..5f8628f --- /dev/null +++ b/tests/WIdgets/TUI.Tests/TUI.Tests.csproj @@ -0,0 +1,32 @@ + + + + net7.0 + enable + enable + + false + true + Widgets.Tests + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/tests/WIdgets/TUI.Tests/Usings.cs b/tests/WIdgets/TUI.Tests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/tests/WIdgets/TUI.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file From 2eb8fee7d4448427848123cc0d41825dbbee95e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 8 Mar 2024 13:24:47 +0500 Subject: [PATCH 04/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20naming=20?= =?UTF-8?q?component.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Controls/CellsComponentBase.cs | 4 +- src/TUI/Components/Controls/Dashboard.cs | 4 +- .../Components/Controls/HeaderContainer.cs | 53 ++-- src/TUI/Components/Controls/Tag.cs | 6 +- src/TUI/Components/Layouts/DashboardLayout.cs | 13 +- src/TUI/Components/Views/DependenciesView.cs | 4 +- src/TUI/Engine/Helper.cs | 3 +- .../Nodes/Attributes/Alignments/Alignment.cs | 2 +- .../{Horizontal.cs => AlignmentHorizontal.cs} | 2 +- .../Attributes/Alignments/IWithAlignment.cs | 2 +- .../Orientations/IWithOrientation.cs | 6 + .../Orientations}/Orientation.cs | 2 +- .../Attributes/Resizings/IWithResizing.cs | 10 + .../Nodes/Attributes/Resizings/Resizing.cs | 8 + .../Engine/Nodes/Components/ComponentBase.cs | 8 +- .../Nodes/Components/ComponentStaticBase.cs | 6 +- src/TUI/Engine/Nodes/Components/IComponent.cs | 2 +- .../Components/{Content.cs => Sketch.cs} | 4 +- .../Nodes/Containers/ContainerExtension.cs | 55 +++++ src/TUI/Engine/Nodes/Containers/IContainer.cs | 11 +- .../Nodes/{NodePosition.cs => Position.cs} | 2 +- .../Engine/Rendering/ComponentCraftsman.cs | 41 ++++ src/TUI/Engine/Rendering/ConsoleCanvas.cs | 9 + src/TUI/Engine/Rendering/ConsoleDrawNode.cs | 76 ++++++ .../Rendering/ConsoleRenderingEngine.cs | 129 ---------- src/TUI/Engine/Rendering/ConsoleWindow.cs | 9 - src/TUI/Engine/Rendering/ICanvas.cs | 9 + src/TUI/Engine/Rendering/IDrawable.cs | 9 + src/TUI/Engine/Rendering/IRenderingEngine.cs | 9 - src/TUI/Engine/Rendering/IWindow.cs | 9 - src/TUI/Engine/Rendering/NodeCraftsman.cs | 39 +++ src/TUI/Pages/DependenciesPage.cs | 12 +- tests/WIdgets/TUI.Tests/ComponentBaseTests.cs | 17 +- .../WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs | 226 ++++++++++++++++++ .../TUI.Tests/ConsoleRenderingEngineTests.cs | 184 -------------- tests/WIdgets/TUI.Tests/Controls/LogoTests.cs | 2 +- 36 files changed, 581 insertions(+), 406 deletions(-) rename src/TUI/Engine/Nodes/Attributes/Alignments/{Horizontal.cs => AlignmentHorizontal.cs} (74%) create mode 100644 src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs rename src/TUI/Engine/Nodes/{Containers => Attributes/Orientations}/Orientation.cs (51%) create mode 100644 src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs rename src/TUI/Engine/Nodes/Components/{Content.cs => Sketch.cs} (84%) create mode 100644 src/TUI/Engine/Nodes/Containers/ContainerExtension.cs rename src/TUI/Engine/Nodes/{NodePosition.cs => Position.cs} (66%) create mode 100644 src/TUI/Engine/Rendering/ComponentCraftsman.cs create mode 100644 src/TUI/Engine/Rendering/ConsoleCanvas.cs create mode 100644 src/TUI/Engine/Rendering/ConsoleDrawNode.cs delete mode 100644 src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs delete mode 100644 src/TUI/Engine/Rendering/ConsoleWindow.cs create mode 100644 src/TUI/Engine/Rendering/ICanvas.cs create mode 100644 src/TUI/Engine/Rendering/IDrawable.cs delete mode 100644 src/TUI/Engine/Rendering/IRenderingEngine.cs delete mode 100644 src/TUI/Engine/Rendering/IWindow.cs create mode 100644 src/TUI/Engine/Rendering/NodeCraftsman.cs create mode 100644 tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs delete mode 100644 tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Components/Controls/CellsComponentBase.cs index 5cdde2a..dff5c6b 100644 --- a/src/TUI/Components/Controls/CellsComponentBase.cs +++ b/src/TUI/Components/Controls/CellsComponentBase.cs @@ -18,7 +18,7 @@ public class CellsComponentBase : ComponentBase, IComponent _cells = cells; } - public void Render(Horizontal horizontal, Size size) + public void Render(AlignmentHorizontal alignmentHorizontal, Size size) { var content = new StringBuilder(); foreach (var cell in _cells) @@ -30,7 +30,7 @@ public class CellsComponentBase : ComponentBase, IComponent // base.Render(content, position, size); } - public override Content Render() + public override Sketch Draw() { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs index ecdb115..55f10e4 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -16,7 +16,7 @@ public class Dashboard : ComponentBase, IComponent _title = title; } - public void Render(Horizontal horizontal, Size size) + public void Render(AlignmentHorizontal alignmentHorizontal, Size size) { var dashboardBuilder = new StringBuilder(); @@ -61,7 +61,7 @@ public class Dashboard : ComponentBase, IComponent dashboardBuilder.Append(Symbols.Angles.RightBottom); } - public override Content Render() + public override Sketch Draw() { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Controls/HeaderContainer.cs b/src/TUI/Components/Controls/HeaderContainer.cs index abe8bef..471e044 100644 --- a/src/TUI/Components/Controls/HeaderContainer.cs +++ b/src/TUI/Components/Controls/HeaderContainer.cs @@ -1,37 +1,48 @@ using TUI.Components.Controls.Statics; using TUI.Components.Controls.Statics.Hints; 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.Resizings; using TUI.Engine.Nodes.Containers; using TUI.Engine.Theme; namespace TUI.Components.Controls; -public class HeaderContainer : IContainer +public abstract class ContainerBase : IContainer { public Orientation Orientation => Orientation.Horizontal; - public Nodes Nodes - { - get - { - var versionHints = new VersionHints() - .Set(Indentation.Default); + public Resizing ResizingHorizontal => Resizing.Adaptive; - var tagsHints = new TagHints() - .Set(Indentation.Default); + public Resizing ResizingVertical => Resizing.Hug; - var appTypeHints = new AppTypeHints() - .Set(Indentation.Default); + public Size Fixed { get; } - var hotkeysHints = new HotkeysHint() - .Set(Indentation.Default); - - var logo = new Logo() - .Set(Horizontal.Right) - .Set(left: Indentation.Default, bottom: Indentation.Default, right: Indentation.Default); - - return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo }; - } - } + public abstract Nodes GetNodes(); } + +public class HeaderContainer : ContainerBase, IContainer +{ + public override Nodes GetNodes() + { + var versionHints = new VersionHints() + .Set(Indentation.Default); + + var tagsHints = new TagHints() + .Set(Indentation.Default); + + var appTypeHints = new AppTypeHints() + .Set(Indentation.Default); + + var hotkeysHints = new HotkeysHint() + .Set(Indentation.Default); + + var logo = new Logo() + .Set(AlignmentHorizontal.Right) + .Set(left: Indentation.Default, bottom: Indentation.Default, right: Indentation.Default); + + return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo }; + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Components/Controls/Tag.cs index 6969993..ee15f32 100644 --- a/src/TUI/Components/Controls/Tag.cs +++ b/src/TUI/Components/Controls/Tag.cs @@ -14,7 +14,7 @@ public class Tag : ComponentBase private IEnumerable _tags; private string _gitType; - public Tag(IRenderingEngine renderingEngine) + public Tag(NodeCraftsman drawEngine) { } @@ -24,7 +24,7 @@ public class Tag : ComponentBase _gitType = gitType; } - public void Render(Horizontal horizontal, Size size) + public void Render(AlignmentHorizontal alignmentHorizontal, Size size) { var tagBuilder = new StringBuilder(); @@ -59,7 +59,7 @@ public class Tag : ComponentBase _ => Symbols.Git }; - public override Content Render() + public override Sketch Draw() { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Layouts/DashboardLayout.cs b/src/TUI/Components/Layouts/DashboardLayout.cs index 95ab0a1..e8507e7 100644 --- a/src/TUI/Components/Layouts/DashboardLayout.cs +++ b/src/TUI/Components/Layouts/DashboardLayout.cs @@ -1,17 +1,20 @@ +using TUI.Components.Controls; 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.Containers; 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 _footer; - public Nodes Nodes => + public override Nodes GetNodes() => new() { _header, _footer @@ -33,4 +36,8 @@ public class DashboardLayout : IContainer { throw new NotImplementedException(); } + + public Resizing ResizingHorizontal => Resizing.Adaptive; + + public Resizing ResizingVertical => Resizing.Adaptive; } \ No newline at end of file diff --git a/src/TUI/Components/Views/DependenciesView.cs b/src/TUI/Components/Views/DependenciesView.cs index e74bd4e..a965eac 100644 --- a/src/TUI/Components/Views/DependenciesView.cs +++ b/src/TUI/Components/Views/DependenciesView.cs @@ -18,7 +18,7 @@ public class DependenciesView : ComponentBase, IComponent _developmentStack = developmentStack; } - public void Render(Horizontal horizontal, Size size) + public void Render(AlignmentHorizontal alignmentHorizontal, Size size) { var dashboardTitle = _developmentStack.Icon + Symbols.Space + ViewName; var dashboard = new Dashboard(dashboardTitle); @@ -153,7 +153,7 @@ public class DependenciesView : ComponentBase, IComponent // { // _table.Previous(); // } - public override Content Render() + public override Sketch Draw() { throw new NotImplementedException(); } diff --git a/src/TUI/Engine/Helper.cs b/src/TUI/Engine/Helper.cs index 8c7a1ad..2ea4241 100644 --- a/src/TUI/Engine/Helper.cs +++ b/src/TUI/Engine/Helper.cs @@ -20,10 +20,11 @@ public static class Helper Colors.Enqueue(ConsoleColor.Yellow); } - public static void ShowBackground(NodePosition position, Size size) + public static void ShowBackground(Position position, Size size) { return; var color = Colors.Dequeue(); + var top = position.Top; var height = 0; diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs index 1ddb95c..f7e1b2d 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs @@ -1,3 +1,3 @@ namespace TUI.Engine.Nodes.Attributes.Alignments; -public record Alignment(Horizontal Horizontal, Vertical Vertical); \ No newline at end of file +public record Alignment(AlignmentHorizontal AlignmentHorizontal, Vertical Vertical); \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/AlignmentHorizontal.cs similarity index 74% rename from src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs rename to src/TUI/Engine/Nodes/Attributes/Alignments/AlignmentHorizontal.cs index cbc839a..b278263 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/AlignmentHorizontal.cs @@ -1,6 +1,6 @@ namespace TUI.Engine.Nodes.Attributes.Alignments; -public enum Horizontal +public enum AlignmentHorizontal { Left = 0, Center = 1, diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs index 56067a2..d2fca44 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs @@ -4,5 +4,5 @@ public interface IWithAlignment where TNode : INode { 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); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs b/src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs new file mode 100644 index 0000000..2d5fda9 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs @@ -0,0 +1,6 @@ +namespace TUI.Engine.Nodes.Attributes.Orientations; + +public interface IWithOrientation +{ + public Orientation Orientation { get; } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/Orientation.cs b/src/TUI/Engine/Nodes/Attributes/Orientations/Orientation.cs similarity index 51% rename from src/TUI/Engine/Nodes/Containers/Orientation.cs rename to src/TUI/Engine/Nodes/Attributes/Orientations/Orientation.cs index f53ba11..16b8b41 100644 --- a/src/TUI/Engine/Nodes/Containers/Orientation.cs +++ b/src/TUI/Engine/Nodes/Attributes/Orientations/Orientation.cs @@ -1,4 +1,4 @@ -namespace TUI.Engine.Nodes.Containers; +namespace TUI.Engine.Nodes.Attributes.Orientations; public enum Orientation { diff --git a/src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs b/src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs new file mode 100644 index 0000000..6b483b4 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs @@ -0,0 +1,10 @@ +namespace TUI.Engine.Nodes.Attributes.Resizings; + +public interface IWithResizing +{ + Resizing ResizingHorizontal { get; } + + Resizing ResizingVertical { get; } + + Size Fixed { get; } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs b/src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs new file mode 100644 index 0000000..a268d52 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs @@ -0,0 +1,8 @@ +namespace TUI.Engine.Nodes.Attributes.Resizings; + +public enum Resizing +{ + Adaptive, + Fixed, + Hug, +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentBase.cs b/src/TUI/Engine/Nodes/Components/ComponentBase.cs index 05caf8f..da36b46 100644 --- a/src/TUI/Engine/Nodes/Components/ComponentBase.cs +++ b/src/TUI/Engine/Nodes/Components/ComponentBase.cs @@ -6,15 +6,15 @@ namespace TUI.Engine.Nodes.Components; public abstract class ComponentBase : List, IComponent { - public abstract Content Render(); + public abstract Sketch Draw(); #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; } diff --git a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs b/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs index 6e9a3ce..67c341f 100644 --- a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs +++ b/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs @@ -4,11 +4,11 @@ namespace TUI.Engine.Nodes.Components; public abstract class ComponentStaticBase : ComponentBase { - private Content? _cache; + private Sketch? _cache; protected abstract void RenderWithCache(StringBuilder builder); - public override Content Render() + public override Sketch Draw() { if (_cache is not null) { @@ -17,7 +17,7 @@ public abstract class ComponentStaticBase : ComponentBase var builder = new StringBuilder(); RenderWithCache(builder); - _cache = new Content(builder.ToString()); + _cache = new Sketch(builder.ToString()); return _cache; } diff --git a/src/TUI/Engine/Nodes/Components/IComponent.cs b/src/TUI/Engine/Nodes/Components/IComponent.cs index 4a841cc..c44f65b 100644 --- a/src/TUI/Engine/Nodes/Components/IComponent.cs +++ b/src/TUI/Engine/Nodes/Components/IComponent.cs @@ -7,5 +7,5 @@ public interface IComponent : INode, IWithAlignment, IWithPadding { - Content Render(); + Sketch Draw(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/Content.cs b/src/TUI/Engine/Nodes/Components/Sketch.cs similarity index 84% rename from src/TUI/Engine/Nodes/Components/Content.cs rename to src/TUI/Engine/Nodes/Components/Sketch.cs index d357bb1..583aea8 100644 --- a/src/TUI/Engine/Nodes/Components/Content.cs +++ b/src/TUI/Engine/Nodes/Components/Sketch.cs @@ -2,11 +2,11 @@ using TUI.Engine.Nodes.Attributes; namespace TUI.Engine.Nodes.Components; -public sealed class Content : IEnumerable +public sealed class Sketch : IEnumerable { private IEnumerable ContentRows { get; } - public Content(string content) => ContentRows = content.Split(Symbols.LineBreak); + public Sketch(string content) => ContentRows = content.Split(Symbols.LineBreak); public IEnumerator GetEnumerator() => ContentRows.GetEnumerator(); diff --git a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs new file mode 100644 index 0000000..a938bdc --- /dev/null +++ b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs @@ -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 + }; +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/IContainer.cs b/src/TUI/Engine/Nodes/Containers/IContainer.cs index aac4955..1dfaa7e 100644 --- a/src/TUI/Engine/Nodes/Containers/IContainer.cs +++ b/src/TUI/Engine/Nodes/Containers/IContainer.cs @@ -1,8 +1,11 @@ +using TUI.Engine.Nodes.Attributes.Orientations; +using TUI.Engine.Nodes.Attributes.Resizings; + namespace TUI.Engine.Nodes.Containers; -public interface IContainer : INode +public interface IContainer : INode, + IWithOrientation, + IWithResizing { - public Orientation Orientation { get; } - - public Nodes Nodes { get; } + public Nodes GetNodes(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/NodePosition.cs b/src/TUI/Engine/Nodes/Position.cs similarity index 66% rename from src/TUI/Engine/Nodes/NodePosition.cs rename to src/TUI/Engine/Nodes/Position.cs index b0c9cf5..55600d3 100644 --- a/src/TUI/Engine/Nodes/NodePosition.cs +++ b/src/TUI/Engine/Nodes/Position.cs @@ -1,6 +1,6 @@ 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}]"; } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ComponentCraftsman.cs b/src/TUI/Engine/Rendering/ComponentCraftsman.cs new file mode 100644 index 0000000..65f5547 --- /dev/null +++ b/src/TUI/Engine/Rendering/ComponentCraftsman.cs @@ -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 +{ + 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; + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleCanvas.cs b/src/TUI/Engine/Rendering/ConsoleCanvas.cs new file mode 100644 index 0000000..9636c3b --- /dev/null +++ b/src/TUI/Engine/Rendering/ConsoleCanvas.cs @@ -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); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleDrawNode.cs b/src/TUI/Engine/Rendering/ConsoleDrawNode.cs new file mode 100644 index 0000000..dc01b01 --- /dev/null +++ b/src/TUI/Engine/Rendering/ConsoleDrawNode.cs @@ -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 +{ + private readonly ICanvas _canvas; + private readonly IDrawable _componentCraftsman; + + public ContainerCraftsman( + ICanvas canvas, + IDrawable 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(); + } + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs b/src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs deleted file mode 100644 index 75235dc..0000000 --- a/src/TUI/Engine/Rendering/ConsoleRenderingEngine.cs +++ /dev/null @@ -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 - }; -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleWindow.cs b/src/TUI/Engine/Rendering/ConsoleWindow.cs deleted file mode 100644 index 20908ae..0000000 --- a/src/TUI/Engine/Rendering/ConsoleWindow.cs +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ICanvas.cs b/src/TUI/Engine/Rendering/ICanvas.cs new file mode 100644 index 0000000..88781c1 --- /dev/null +++ b/src/TUI/Engine/Rendering/ICanvas.cs @@ -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); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IDrawable.cs b/src/TUI/Engine/Rendering/IDrawable.cs new file mode 100644 index 0000000..a196386 --- /dev/null +++ b/src/TUI/Engine/Rendering/IDrawable.cs @@ -0,0 +1,9 @@ +using TUI.Engine.Nodes; +using TUI.Engine.Nodes.Attributes; + +namespace TUI.Engine.Rendering; + +public interface IDrawable where TItem : INode +{ + Size Draw(TItem item, Position sketchPosition, Size allowableSize); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IRenderingEngine.cs b/src/TUI/Engine/Rendering/IRenderingEngine.cs deleted file mode 100644 index 9cc91bd..0000000 --- a/src/TUI/Engine/Rendering/IRenderingEngine.cs +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IWindow.cs b/src/TUI/Engine/Rendering/IWindow.cs deleted file mode 100644 index 5fd7dc6..0000000 --- a/src/TUI/Engine/Rendering/IWindow.cs +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/NodeCraftsman.cs b/src/TUI/Engine/Rendering/NodeCraftsman.cs new file mode 100644 index 0000000..a124c27 --- /dev/null +++ b/src/TUI/Engine/Rendering/NodeCraftsman.cs @@ -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 _componentCraftsman; + private readonly IDrawable _containerCraftsman; + + public NodeCraftsman( + ICanvas canvas, + IDrawable componentCraftsman, + IDrawable 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; + } + } +} \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index b535af6..e465e23 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -13,17 +13,21 @@ public class DependenciesPage { Debugger.Log(0, "Event", "Open page dependencies\n"); - var window = new ConsoleWindow(); - var renderEngine = new ConsoleRenderingEngine(window); + var canvas = new ConsoleCanvas(); + + var componentCraftsman = new ComponentCraftsman(canvas); + var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); + var nodeCraftsman = new NodeCraftsman(canvas, componentCraftsman, containerCraftsman); + var header = new HeaderContainer(); var copyright = new Copyright() .Set(right: Level.Normal) - .Set(Horizontal.Right, Vertical.Bottom); + .Set(AlignmentHorizontal.Right, Vertical.Bottom); var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright); // CommandLine = new CommandLine(); // DependenciesView = new DependenciesView(); - renderEngine.Render(layout); + nodeCraftsman.Draw(layout); } // private bool _commandLineInDisplay; diff --git a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs b/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs index 77bb47a..9c67ad1 100644 --- a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs +++ b/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs @@ -12,13 +12,13 @@ public class ComponentBaseTests { var component = new Logo() .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.Left.Should().Be(Level.Normal); component.Padding.Bottom.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); } @@ -49,15 +49,16 @@ public class ComponentBaseTests } [Theory] - [InlineData(Horizontal.Left)] - [InlineData(Horizontal.Center)] - [InlineData(Horizontal.Right)] - public void WhenSetHorizontalAlignSaveAllChange(Horizontal alignment) + [InlineData(AlignmentHorizontal.Left)] + [InlineData(AlignmentHorizontal.Center)] + [InlineData(AlignmentHorizontal.Right)] + public void WhenSetHorizontalAlignSaveAllChange(AlignmentHorizontal alignment) { var component = new Logo(); - component.Set(horizontal: alignment); + component.Set(alignmentHorizontal: alignment); - component.Alignment.Horizontal.Should().Be(alignment); + component.Alignment.AlignmentHorizontal.Should().Be(alignment); } + } \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs new file mode 100644 index 0000000..b90e7e4 --- /dev/null +++ b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs @@ -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(c => + c.Draw() == new Sketch("Lorem") && + c.Alignment == new Alignment(AlignmentHorizontal.Left, Vertical.Top)); + } + + [Fact] + public void DrawSimple() + { + var canvas = Mock.Of(w => w.Width == 9 && w.Height == 1); + var nodes = new Nodes { _component }; + var root = Mock.Of(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(w => w.Width == canvasSize && w.Height == canvasSize); + var component = Mock.Of(c => c.Draw() == new Sketch(content) && + c.Alignment == new Alignment(alignment, Vertical.Top)); + var nodes = new Nodes { component }; + var root = Mock.Of(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(w => w.Width == canvasSize && w.Height == canvasSize); + var component = Mock.Of(c => c.Draw() == new Sketch(content) && + c.Alignment == new Alignment(AlignmentHorizontal.Left, alignment)); + var nodes = new Nodes { component }; + var root = Mock.Of(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(w => w.Width == 6 && w.Height == 5); + var component = Mock.Of(c => c.Draw() == new Sketch("VV") && + c.Alignment == new Alignment(alignmentHorizontal, vertical)); + var nodes = new Nodes { component }; + var root = Mock.Of(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(w => w.Width == rootWidth && w.Height == rootHeight); + var nodes = new Nodes { _component, _component }; + var root = Mock.Of(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(w => w.Height == 2 && w.Width == 10); + var nodes = new Nodes { _component, _component }; + var root = Mock.Of(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(w => w.Width == 10 && w.Height == 1); + var nodes = new Nodes { _component, _component }; + var container = Mock.Of(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(w => w.Width == 24 && w.Height == 1); + var nodes = new Nodes { _component, _component, _component, _component }; + var root = Mock.Of(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(w => w.Width == 10 && w.Height == 2); + var container = Mock.Of(c => c.GetNodes() == new Nodes { _component }); + var nodes = new Nodes { container, _component }; + var root = Mock.Of(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(w => w.Width == 20 && w.Height == 2); + var container = + Mock.Of(c => c.GetNodes() == new Nodes { _component } && c.ResizingHorizontal == resizing); + var nodes = new Nodes { container, _component }; + var root = Mock.Of(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)); + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs b/tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs deleted file mode 100644 index 08ad62a..0000000 --- a/tests/WIdgets/TUI.Tests/ConsoleRenderingEngineTests.cs +++ /dev/null @@ -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(c => - c.Render() == new Content("Lorem") && - c.Alignment == new Alignment(Horizontal.Left, Vertical.Top)); - } - - [Fact] - public void RenderSimple() - { - var window = Mock.Of(w => w.Width == 9 && w.Height == 1); - var nodes = new Nodes { _component }; - var root = Mock.Of(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(w => w.Width == windowSize && w.Height == windowSize); - var component = Mock.Of(c => c.Render() == new Content(content) && - c.Alignment == new Alignment(alignment, Vertical.Top)); - var nodes = new Nodes { component }; - var root = Mock.Of(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(w => w.Width == windowSize && w.Height == windowSize); - var component = Mock.Of(c => c.Render() == new Content(content) && - c.Alignment == new Alignment(Horizontal.Left, alignment)); - var nodes = new Nodes { component }; - var root = Mock.Of(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(w => w.Width == 6 && w.Height == 5); - var component = Mock.Of(c => c.Render() == new Content("VV") && - c.Alignment == new Alignment(horizontal, vertical)); - var nodes = new Nodes { component }; - var root = Mock.Of(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(w => w.Width == rootWidth && w.Height == rootHeight); - var nodes = new Nodes { _component, _component }; - var root = Mock.Of(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(w => w.Height == 2 && w.Width == 10); - var nodes = new Nodes { _component, _component }; - var root = Mock.Of(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(w => w.Width == 10 && w.Height == 1); - var nodes = new Nodes { _component, _component }; - var container = Mock.Of(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(w => w.Width == 24 && w.Height == 1); - var nodes = new Nodes { _component, _component, _component, _component }; - var root = Mock.Of(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(w => w.Width == 10 && w.Height == 2); - var container = Mock.Of(c => c.Nodes == new Nodes { _component }); - var nodes = new Nodes { container, _component }; - var root = Mock.Of(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)); - } -} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs index cc3273c..306b9ac 100644 --- a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs +++ b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs @@ -9,7 +9,7 @@ public class LogoTests { var logo = new Logo(); - var render = logo.Render().ToString(); + var render = logo.Draw().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", From 074365652da078b9f5e82a06fdb2c5254107973d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 8 Mar 2024 14:41:29 +0500 Subject: [PATCH 05/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactoring=20crafts?= =?UTF-8?q?mans.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Controls/CellsComponentBase.cs | 2 +- src/TUI/Components/Controls/Dashboard.cs | 2 +- src/TUI/Engine/Nodes/Attributes/Size.cs | 4 +- src/TUI/Engine/Nodes/Components/Sketch.cs | 6 +-- src/TUI/Engine/Nodes/Position.cs | 1 + src/TUI/Engine/Rendering/CanvasExtensions.cs | 8 ++++ .../Engine/Rendering/ComponentCraftsman.cs | 15 +++---- src/TUI/Engine/Rendering/ConsoleCanvas.cs | 4 ++ ...nsoleDrawNode.cs => ContainerCraftsman.cs} | 12 ++---- src/TUI/Engine/Rendering/CraftsmanBase.cs | 14 +++++++ src/TUI/Engine/Rendering/ICanvas.cs | 2 + src/TUI/Engine/Rendering/NodeCraftsman.cs | 25 ++++-------- src/TUI/Extensions.cs | 2 +- src/TUI/Pages/DependenciesPage.cs | 8 ++-- .../WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs | 40 +++++++++---------- 15 files changed, 78 insertions(+), 67 deletions(-) create mode 100644 src/TUI/Engine/Rendering/CanvasExtensions.cs rename src/TUI/Engine/Rendering/{ConsoleDrawNode.cs => ContainerCraftsman.cs} (85%) create mode 100644 src/TUI/Engine/Rendering/CraftsmanBase.cs diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Components/Controls/CellsComponentBase.cs index dff5c6b..28a1188 100644 --- a/src/TUI/Components/Controls/CellsComponentBase.cs +++ b/src/TUI/Components/Controls/CellsComponentBase.cs @@ -23,7 +23,7 @@ public class CellsComponentBase : ComponentBase, IComponent var content = new StringBuilder(); foreach (var cell in _cells) { - content.Append(Symbols.Space.Repeat(MaxCellWidth - cell.Width())); + content.Append(Symbols.Space.Repeat(MaxCellWidth - cell.GetWidth())); content.Append(cell); } diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs index 55f10e4..969fd25 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -29,7 +29,7 @@ public class Dashboard : ComponentBase, IComponent private static void RenderTopLine(StringBuilder dashboardBuilder, Size size, string title) { - var halfWidth = (size.Width - title.Width() - (int)Indentation.BorderWidth * 2 - + var halfWidth = (size.Width - title.GetWidth() - (int)Indentation.BorderWidth * 2 - (int)Indentation.Default * 2) / 2; dashboardBuilder.Append(Symbols.Angles.LeftTop); dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); diff --git a/src/TUI/Engine/Nodes/Attributes/Size.cs b/src/TUI/Engine/Nodes/Attributes/Size.cs index d0c7689..4848283 100644 --- a/src/TUI/Engine/Nodes/Attributes/Size.cs +++ b/src/TUI/Engine/Nodes/Attributes/Size.cs @@ -1,6 +1,8 @@ namespace TUI.Engine.Nodes.Attributes; -public record Size(int Width, int Height) +public readonly record struct Size(int Width, int Height) { + public static Size operator -(Size a, Position b) => new(a.Width - b.Left, a.Height - b.Top); + public override string ToString() => $"W[{Width}] H[{Height}]"; } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/Sketch.cs b/src/TUI/Engine/Nodes/Components/Sketch.cs index 583aea8..f5c8768 100644 --- a/src/TUI/Engine/Nodes/Components/Sketch.cs +++ b/src/TUI/Engine/Nodes/Components/Sketch.cs @@ -10,12 +10,12 @@ public sealed class Sketch : IEnumerable public IEnumerator GetEnumerator() => ContentRows.GetEnumerator(); - public IEnumerable Rows(int maxWidth, int maxHeight) => - ContentRows.Where(row => maxWidth >= row.Width()).Take(maxHeight).ToArray(); + public IEnumerable Rows(Size maxSize) => + ContentRows.Where(row => maxSize.Width >= row.GetWidth()).Take(maxSize.Height).ToArray(); public Size GetSize() { - var width = ContentRows.Select(row => row.Width()).DefaultIfEmpty(0).Max(); + var width = ContentRows.Select(row => row.GetWidth()).DefaultIfEmpty(0).Max(); var height = ContentRows.Count(); return new Size(width, height); } diff --git a/src/TUI/Engine/Nodes/Position.cs b/src/TUI/Engine/Nodes/Position.cs index 55600d3..edaa9d8 100644 --- a/src/TUI/Engine/Nodes/Position.cs +++ b/src/TUI/Engine/Nodes/Position.cs @@ -2,5 +2,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}]"; } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/CanvasExtensions.cs b/src/TUI/Engine/Rendering/CanvasExtensions.cs new file mode 100644 index 0000000..5dfe4cf --- /dev/null +++ b/src/TUI/Engine/Rendering/CanvasExtensions.cs @@ -0,0 +1,8 @@ +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); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ComponentCraftsman.cs b/src/TUI/Engine/Rendering/ComponentCraftsman.cs index 65f5547..577eed5 100644 --- a/src/TUI/Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI/Engine/Rendering/ComponentCraftsman.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using TUI.Engine.Nodes; using TUI.Engine.Nodes.Attributes; using TUI.Engine.Nodes.Components; @@ -6,7 +5,7 @@ using TUI.Engine.Nodes.Containers; namespace TUI.Engine.Rendering; -public sealed class ComponentCraftsman : IDrawable +public sealed class ComponentCraftsman : CraftsmanBase, IDrawable { private readonly ICanvas _canvas; @@ -19,16 +18,10 @@ public sealed class ComponentCraftsman : IDrawable { var sketch = component.Draw(); var actualSize = sketch.GetSize(); - - var maxWidth = _canvas.Width - sketchPosition.Left; - var maxHeight = _canvas.Height - sketchPosition.Top; - + var maxSize = _canvas.GetSize() - sketchPosition; 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)) + foreach (var row in sketch.Rows(maxSize)) { _canvas.SetPencil(pencilPosition.Left, pencilPosition.Top); _canvas.Paint(row); @@ -36,6 +29,8 @@ public sealed class ComponentCraftsman : IDrawable pencilPosition = pencilPosition with { Top = pencilPosition.Top + 1 }; } + Debug(pencilPosition, sketchPosition, allowableSize); + return actualSize; } } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleCanvas.cs b/src/TUI/Engine/Rendering/ConsoleCanvas.cs index 9636c3b..18227c4 100644 --- a/src/TUI/Engine/Rendering/ConsoleCanvas.cs +++ b/src/TUI/Engine/Rendering/ConsoleCanvas.cs @@ -1,9 +1,13 @@ +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); } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleDrawNode.cs b/src/TUI/Engine/Rendering/ContainerCraftsman.cs similarity index 85% rename from src/TUI/Engine/Rendering/ConsoleDrawNode.cs rename to src/TUI/Engine/Rendering/ContainerCraftsman.cs index dc01b01..42eda37 100644 --- a/src/TUI/Engine/Rendering/ConsoleDrawNode.cs +++ b/src/TUI/Engine/Rendering/ContainerCraftsman.cs @@ -7,16 +7,12 @@ using TUI.Engine.Nodes.Containers; namespace TUI.Engine.Rendering; -public sealed class ContainerCraftsman : IDrawable +public sealed class ContainerCraftsman : CraftsmanBase, IDrawable { - private readonly ICanvas _canvas; private readonly IDrawable _componentCraftsman; - public ContainerCraftsman( - ICanvas canvas, - IDrawable componentCraftsman) + public ContainerCraftsman(IDrawable componentCraftsman) { - _canvas = canvas; _componentCraftsman = componentCraftsman; } @@ -25,9 +21,6 @@ public sealed class ContainerCraftsman : IDrawable { 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) @@ -38,6 +31,7 @@ public sealed class ContainerCraftsman : IDrawable controlNumber++; } + Debug(sketchPosition, sketchPosition, allowableSize); return sketchSize; } diff --git a/src/TUI/Engine/Rendering/CraftsmanBase.cs b/src/TUI/Engine/Rendering/CraftsmanBase.cs new file mode 100644 index 0000000..20d8ad6 --- /dev/null +++ b/src/TUI/Engine/Rendering/CraftsmanBase.cs @@ -0,0 +1,14 @@ +using System.Diagnostics; +using TUI.Engine.Nodes; +using TUI.Engine.Nodes.Attributes; + +namespace TUI.Engine.Rendering; + +public abstract class CraftsmanBase +{ + protected void Debug(Position pencilPosition, Position sketchPosition, Size allowableSize) + { + Debugger.Log(0, "Draw", $"{pencilPosition}{GetType().Name}.\n"); + Helper.ShowBackground(sketchPosition, allowableSize); + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ICanvas.cs b/src/TUI/Engine/Rendering/ICanvas.cs index 88781c1..ef1e82c 100644 --- a/src/TUI/Engine/Rendering/ICanvas.cs +++ b/src/TUI/Engine/Rendering/ICanvas.cs @@ -1,3 +1,5 @@ +using TUI.Engine.Nodes.Attributes; + namespace TUI.Engine.Rendering; public interface ICanvas diff --git a/src/TUI/Engine/Rendering/NodeCraftsman.cs b/src/TUI/Engine/Rendering/NodeCraftsman.cs index a124c27..a73c939 100644 --- a/src/TUI/Engine/Rendering/NodeCraftsman.cs +++ b/src/TUI/Engine/Rendering/NodeCraftsman.cs @@ -5,35 +5,24 @@ using TUI.Engine.Nodes.Containers; namespace TUI.Engine.Rendering; -public sealed class NodeCraftsman +public sealed class NodeCraftsman : IDrawable { - private readonly ICanvas _canvas; private readonly IDrawable _componentCraftsman; private readonly IDrawable _containerCraftsman; public NodeCraftsman( - ICanvas canvas, IDrawable componentCraftsman, IDrawable 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) + public Size Draw(INode node, Position sketchPosition, Size allowableSize) => + node switch { - case IContainer container: - _containerCraftsman.Draw(container, defaultPosition, windowSize); - break; - case IComponent component: - _componentCraftsman.Draw(component, defaultPosition, windowSize); - break; - } - } + IContainer container => _containerCraftsman.Draw(container, sketchPosition, allowableSize), + IComponent component => _componentCraftsman.Draw(component, sketchPosition, allowableSize), + _ => throw new InvalidCastException("Unknown node type.") + }; } \ No newline at end of file diff --git a/src/TUI/Extensions.cs b/src/TUI/Extensions.cs index 63945e3..6da3e2f 100644 --- a/src/TUI/Extensions.cs +++ b/src/TUI/Extensions.cs @@ -21,7 +21,7 @@ public static class Extensions return Regex.Replace(text, @"\S\[(\d{0,3}[;m]_?){0,5}", ""); } - public static int Width(this string text) + public static int GetWidth(this string text) { if (string.IsNullOrEmpty(text)) return 0; diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index e465e23..7742452 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -1,6 +1,7 @@ using System.Diagnostics; using TUI.Components.Controls; using TUI.Components.Layouts; +using TUI.Engine.Nodes; using TUI.Engine.Nodes.Attributes.Alignments; using TUI.Engine.Rendering; using TUI.Engine.Theme; @@ -16,8 +17,8 @@ public class DependenciesPage var canvas = new ConsoleCanvas(); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - var nodeCraftsman = new NodeCraftsman(canvas, componentCraftsman, containerCraftsman); + var containerCraftsman = new ContainerCraftsman(componentCraftsman); + var nodeCraftsman = new NodeCraftsman(componentCraftsman, containerCraftsman); var header = new HeaderContainer(); var copyright = new Copyright() @@ -27,7 +28,8 @@ public class DependenciesPage var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright); // CommandLine = new CommandLine(); // DependenciesView = new DependenciesView(); - nodeCraftsman.Draw(layout); + + nodeCraftsman.Draw(layout, Position.Default, canvas.GetSize()); } // private bool _commandLineInDisplay; diff --git a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs index b90e7e4..e4c1f87 100644 --- a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs +++ b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs @@ -28,8 +28,8 @@ public class NodeCraftsmanTests var root = Mock.Of(r => r.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root); + 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.Paint("Lorem"), Times.Once()); @@ -53,8 +53,8 @@ public class NodeCraftsmanTests var root = Mock.Of(r => r.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root); + var containerCraftsman = new ContainerCraftsman(componentCraftsman); + new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, 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()); @@ -84,8 +84,8 @@ public class NodeCraftsmanTests var root = Mock.Of(r => r.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root); + var containerCraftsman = new ContainerCraftsman(componentCraftsman); + new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); foreach (var expectedCursorPosition in expectedPositions) { @@ -113,8 +113,8 @@ public class NodeCraftsmanTests var root = Mock.Of(r => r.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root); + var containerCraftsman = new ContainerCraftsman(componentCraftsman); + new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); Mock.Get(canvas).Verify(w => w.SetPencil(expectedLeft, expectedTop), Times.Once()); } @@ -129,8 +129,8 @@ public class NodeCraftsmanTests var root = Mock.Of(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); + 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.Paint("Lorem"), Times.Once()); @@ -144,8 +144,8 @@ public class NodeCraftsmanTests var root = Mock.Of(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); + 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()); @@ -160,8 +160,8 @@ public class NodeCraftsmanTests var container = Mock.Of(g => g.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(container); + 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)); @@ -176,8 +176,8 @@ public class NodeCraftsmanTests var root = Mock.Of(r => r.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(canvas, componentCraftsman); - new NodeCraftsman(canvas, componentCraftsman, containerCraftsman).Draw(root); + 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.Exactly(1)); Mock.Get(canvas).Verify(w => w.SetPencil(6, 0), Times.Exactly(1)); @@ -195,8 +195,8 @@ public class NodeCraftsmanTests var root = Mock.Of(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); + 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.Exactly(1)); Mock.Get(canvas).Verify(w => w.SetPencil(0, 1), Times.Exactly(1)); @@ -216,8 +216,8 @@ public class NodeCraftsmanTests var root = Mock.Of(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); + 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.Exactly(1)); Mock.Get(canvas).Verify(w => w.SetPencil(expectedCursorPosition, 0), Times.Exactly(1)); From 3b56c7207befdc6522070bc8d0c928ec76dd9b1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sat, 9 Mar 2024 01:48:16 +0500 Subject: [PATCH 06/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Rename=20classes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Controls/CellsComponentBase.cs | 5 +- src/TUI/Components/Controls/Dashboard.cs | 4 +- .../Components/Controls/HeaderContainer.cs | 40 ++++-------- src/TUI/Components/Controls/Tag.cs | 4 +- src/TUI/Components/Layouts/DashboardLayout.cs | 3 +- src/TUI/Components/Views/DependenciesView.cs | 6 +- .../Nodes/Attributes/Alignments/Alignment.cs | 2 +- .../{AlignmentHorizontal.cs => Horizontal.cs} | 2 +- .../Nodes/Attributes/Alignments/IAlignable.cs | 10 +++ .../Attributes/Alignments/IWithAlignment.cs | 8 --- .../Nodes/Attributes/Paddings/IPaddingable.cs | 14 ++++ .../Nodes/Attributes/Paddings/IWithPadding.cs | 17 ----- .../Nodes/Attributes/Paddings/Padding.cs | 8 +-- .../Nodes/Attributes/Resizing/IResizable.cs | 14 ++++ .../{Resizings => Resizing}/Resizing.cs | 2 +- .../Attributes/Resizings/IWithResizing.cs | 10 --- .../Engine/Nodes/Components/ComponentBase.cs | 60 +++++++++++------ .../Nodes/Components/ComponentStaticBase.cs | 2 +- src/TUI/Engine/Nodes/Components/IComponent.cs | 4 +- .../Engine/Nodes/Containers/ContainerBase.cs | 10 +++ .../Nodes/Containers/ContainerExtension.cs | 33 ++++++++-- src/TUI/Engine/Nodes/Containers/IContainer.cs | 4 +- src/TUI/Engine/Nodes/INode.cs | 4 +- src/TUI/Engine/Nodes/NodeBase.cs | 64 +++++++++++++++++++ .../Engine/Rendering/ContainerCraftsman.cs | 22 ++++++- src/TUI/Engine/Rendering/ICanvas.cs | 2 - src/TUI/Pages/DependenciesPage.cs | 7 +- tests/WIdgets/TUI.Tests/ComponentBaseTests.cs | 36 +++++------ .../WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs | 46 ++++++------- 29 files changed, 279 insertions(+), 164 deletions(-) rename src/TUI/Engine/Nodes/Attributes/Alignments/{AlignmentHorizontal.cs => Horizontal.cs} (74%) create mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs delete mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs delete mode 100644 src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs create mode 100644 src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs rename src/TUI/Engine/Nodes/Attributes/{Resizings => Resizing}/Resizing.cs (53%) delete mode 100644 src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs create mode 100644 src/TUI/Engine/Nodes/Containers/ContainerBase.cs create mode 100644 src/TUI/Engine/Nodes/NodeBase.cs diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Components/Controls/CellsComponentBase.cs index 28a1188..86b26bc 100644 --- a/src/TUI/Components/Controls/CellsComponentBase.cs +++ b/src/TUI/Components/Controls/CellsComponentBase.cs @@ -12,13 +12,12 @@ public class CellsComponentBase : ComponentBase, IComponent private readonly IEnumerable _cells; - public CellsComponentBase(IEnumerable cells) { _cells = cells; } - public void Render(AlignmentHorizontal alignmentHorizontal, Size size) + public void Render(Horizontal horizontal, Size size) { var content = new StringBuilder(); foreach (var cell in _cells) @@ -30,7 +29,7 @@ public class CellsComponentBase : ComponentBase, IComponent // base.Render(content, position, size); } - public override Sketch Draw() + public override Sketch DrawComponent() { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs index 969fd25..46f0dcf 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -16,7 +16,7 @@ public class Dashboard : ComponentBase, IComponent _title = title; } - public void Render(AlignmentHorizontal alignmentHorizontal, Size size) + public void Render(Horizontal horizontal, Size size) { var dashboardBuilder = new StringBuilder(); @@ -61,7 +61,7 @@ public class Dashboard : ComponentBase, IComponent dashboardBuilder.Append(Symbols.Angles.RightBottom); } - public override Sketch Draw() + public override Sketch DrawComponent() { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Controls/HeaderContainer.cs b/src/TUI/Components/Controls/HeaderContainer.cs index 471e044..912ce23 100644 --- a/src/TUI/Components/Controls/HeaderContainer.cs +++ b/src/TUI/Components/Controls/HeaderContainer.cs @@ -1,47 +1,33 @@ using TUI.Components.Controls.Statics; using TUI.Components.Controls.Statics.Hints; 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.Resizings; using TUI.Engine.Nodes.Containers; using TUI.Engine.Theme; namespace TUI.Components.Controls; -public abstract class ContainerBase : IContainer -{ - public Orientation Orientation => Orientation.Horizontal; - - 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() { - var versionHints = new VersionHints() - .Set(Indentation.Default); + var versionHints = new VersionHints(); + versionHints.SetPadding(Indentation.Default); - var tagsHints = new TagHints() - .Set(Indentation.Default); + var tagsHints = new TagHints(); + tagsHints.SetPadding(Indentation.Default); - var appTypeHints = new AppTypeHints() - .Set(Indentation.Default); + var appTypeHints = new AppTypeHints(); + appTypeHints.SetPadding(Indentation.Default); - var hotkeysHints = new HotkeysHint() - .Set(Indentation.Default); + var hotkeysHints = new HotkeysHint(); + hotkeysHints.SetPadding(Indentation.Default); - var logo = new Logo() - .Set(AlignmentHorizontal.Right) - .Set(left: Indentation.Default, bottom: Indentation.Default, right: Indentation.Default); + var logo = new Logo(); + logo.SetAlignment(Horizontal.Right); + logo.SetPaddingLeft(Indentation.Default); + logo.SetPaddingBottom(Indentation.Default); + logo.SetPaddingRight(Indentation.Default); return new Nodes { versionHints, tagsHints, appTypeHints, hotkeysHints, logo }; } diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Components/Controls/Tag.cs index ee15f32..e7eca6e 100644 --- a/src/TUI/Components/Controls/Tag.cs +++ b/src/TUI/Components/Controls/Tag.cs @@ -24,7 +24,7 @@ public class Tag : ComponentBase _gitType = gitType; } - public void Render(AlignmentHorizontal alignmentHorizontal, Size size) + public void Render(Horizontal horizontal, Size size) { var tagBuilder = new StringBuilder(); @@ -59,7 +59,7 @@ public class Tag : ComponentBase _ => Symbols.Git }; - public override Sketch Draw() + public override Sketch DrawComponent() { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Layouts/DashboardLayout.cs b/src/TUI/Components/Layouts/DashboardLayout.cs index e8507e7..b4fe8fc 100644 --- a/src/TUI/Components/Layouts/DashboardLayout.cs +++ b/src/TUI/Components/Layouts/DashboardLayout.cs @@ -1,7 +1,6 @@ -using TUI.Components.Controls; using TUI.Engine.Nodes; using TUI.Engine.Nodes.Attributes.Orientations; -using TUI.Engine.Nodes.Attributes.Resizings; +using TUI.Engine.Nodes.Attributes.Resizing; using TUI.Engine.Nodes.Components; using TUI.Engine.Nodes.Containers; diff --git a/src/TUI/Components/Views/DependenciesView.cs b/src/TUI/Components/Views/DependenciesView.cs index a965eac..88c02b1 100644 --- a/src/TUI/Components/Views/DependenciesView.cs +++ b/src/TUI/Components/Views/DependenciesView.cs @@ -18,12 +18,12 @@ public class DependenciesView : ComponentBase, IComponent _developmentStack = developmentStack; } - public void Render(AlignmentHorizontal alignmentHorizontal, Size size) + public void Render(Horizontal horizontal, Size size) { var dashboardTitle = _developmentStack.Icon + Symbols.Space + ViewName; var dashboard = new Dashboard(dashboardTitle); - Add(dashboard); + // Add(dashboard); } // private const int TitleWidth = 25; @@ -153,7 +153,7 @@ public class DependenciesView : ComponentBase, IComponent // { // _table.Previous(); // } - public override Sketch Draw() + public override Sketch DrawComponent() { throw new NotImplementedException(); } diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs index f7e1b2d..1ddb95c 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs @@ -1,3 +1,3 @@ namespace TUI.Engine.Nodes.Attributes.Alignments; -public record Alignment(AlignmentHorizontal AlignmentHorizontal, Vertical Vertical); \ No newline at end of file +public record Alignment(Horizontal Horizontal, Vertical Vertical); \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/AlignmentHorizontal.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs similarity index 74% rename from src/TUI/Engine/Nodes/Attributes/Alignments/AlignmentHorizontal.cs rename to src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs index b278263..cbc839a 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/AlignmentHorizontal.cs +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs @@ -1,6 +1,6 @@ namespace TUI.Engine.Nodes.Attributes.Alignments; -public enum AlignmentHorizontal +public enum Horizontal { Left = 0, Center = 1, diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs new file mode 100644 index 0000000..875408b --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs @@ -0,0 +1,10 @@ +namespace TUI.Engine.Nodes.Attributes.Alignments; + +public interface IAlignable +{ + Alignment Alignment { get; } + + void SetAlignment(Vertical vertical); + + void SetAlignment(Horizontal horizontal); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs deleted file mode 100644 index d2fca44..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/IWithAlignment.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace TUI.Engine.Nodes.Attributes.Alignments; - -public interface IWithAlignment where TNode : INode -{ - public Alignment Alignment { get; } - - public TNode Set(AlignmentHorizontal alignmentHorizontal = AlignmentHorizontal.Left, Vertical vertical = Vertical.Top); -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs b/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs new file mode 100644 index 0000000..6932bcb --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs @@ -0,0 +1,14 @@ +using TUI.Engine.Theme; + +namespace TUI.Engine.Nodes.Attributes.Paddings; + +public interface IPaddingable +{ + Padding? Padding { get; } + + void SetPadding(Level level); + void SetPaddingLeft(Level level); + void SetPaddingTop(Level level); + void SetPaddingBottom(Level level); + void SetPaddingRight(Level level); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs b/src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs deleted file mode 100644 index 493fc45..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Paddings/IWithPadding.cs +++ /dev/null @@ -1,17 +0,0 @@ -using TUI.Engine.Theme; - -namespace TUI.Engine.Nodes.Attributes.Paddings; - -public interface IWithPadding where TNode : INode -{ - public Padding? Padding { get; } - - public TNode Set(Level padding); - - public TNode Set( - Level? left = Level.None, - Level? top = Level.None, - Level? right = Level.None, - Level? bottom = Level.None - ); -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs b/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs index f7ccf52..0efbea8 100644 --- a/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs +++ b/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs @@ -3,10 +3,10 @@ using TUI.Engine.Theme; namespace TUI.Engine.Nodes.Attributes.Paddings; public record Padding( - Level? Left = Level.None, - Level? Top = Level.None, - Level? Right = Level.None, - Level? Bottom = Level.None + Level Left = Level.None, + Level Top = Level.None, + Level Right = Level.None, + Level Bottom = Level.None ) { public Padding(Level padding) : this(Left: padding, Top: padding, Right: padding, Bottom: padding) diff --git a/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs b/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs new file mode 100644 index 0000000..6c6f2f6 --- /dev/null +++ b/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs @@ -0,0 +1,14 @@ +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 SetHug(Orientation orientation); + void SetFixed(Orientation orientation, int value); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs b/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs similarity index 53% rename from src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs rename to src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs index a268d52..db3984d 100644 --- a/src/TUI/Engine/Nodes/Attributes/Resizings/Resizing.cs +++ b/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs @@ -1,4 +1,4 @@ -namespace TUI.Engine.Nodes.Attributes.Resizings; +namespace TUI.Engine.Nodes.Attributes.Resizing; public enum Resizing { diff --git a/src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs b/src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs deleted file mode 100644 index 6b483b4..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Resizings/IWithResizing.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TUI.Engine.Nodes.Attributes.Resizings; - -public interface IWithResizing -{ - Resizing ResizingHorizontal { get; } - - Resizing ResizingVertical { get; } - - Size Fixed { get; } -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentBase.cs b/src/TUI/Engine/Nodes/Components/ComponentBase.cs index da36b46..7027dbb 100644 --- a/src/TUI/Engine/Nodes/Components/ComponentBase.cs +++ b/src/TUI/Engine/Nodes/Components/ComponentBase.cs @@ -1,21 +1,46 @@ +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 : List, IComponent + +public abstract class ComponentBase : NodeBase, IComponent { - public abstract Sketch Draw(); + private Size _sketchSize; + + public abstract Sketch DrawComponent(); + + public Sketch Draw() + { + 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(AlignmentHorizontal.Center, Vertical.Top); + public Alignment Alignment { get; private set; } = new(Horizontal.Center, Vertical.Top); - public IComponent Set(AlignmentHorizontal alignmentHorizontal = AlignmentHorizontal.Left, Vertical vertical = Vertical.Top) + public void SetAlignment(Vertical vertical) { - Alignment = new Alignment(alignmentHorizontal, vertical); - return this; + Alignment = Alignment with { Vertical = vertical }; + } + + public void SetAlignment(Horizontal horizontal) + { + Alignment = Alignment with { Horizontal = horizontal }; } #endregion @@ -24,22 +49,15 @@ public abstract class ComponentBase : List, IComponent public Padding Padding { get; private set; } = new(Level.None); - public IComponent Set(Level padding) - { - Padding = new Padding(padding); - return this; - } + public void SetPadding(Level level) => Padding = new Padding(level); - public IComponent Set( - Level? left = Level.None, - Level? top = Level.None, - Level? right = Level.None, - Level? bottom = Level.None - ) - { - Padding = new Padding(left, top, right, bottom); - return this; - } + 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 } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs b/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs index 67c341f..15cc414 100644 --- a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs +++ b/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs @@ -8,7 +8,7 @@ public abstract class ComponentStaticBase : ComponentBase protected abstract void RenderWithCache(StringBuilder builder); - public override Sketch Draw() + public override Sketch DrawComponent() { if (_cache is not null) { diff --git a/src/TUI/Engine/Nodes/Components/IComponent.cs b/src/TUI/Engine/Nodes/Components/IComponent.cs index c44f65b..4883d76 100644 --- a/src/TUI/Engine/Nodes/Components/IComponent.cs +++ b/src/TUI/Engine/Nodes/Components/IComponent.cs @@ -3,9 +3,7 @@ using TUI.Engine.Nodes.Attributes.Paddings; namespace TUI.Engine.Nodes.Components; -public interface IComponent : INode, - IWithAlignment, - IWithPadding +public interface IComponent : INode, IAlignable, IPaddingable { Sketch Draw(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/ContainerBase.cs b/src/TUI/Engine/Nodes/Containers/ContainerBase.cs new file mode 100644 index 0000000..60c499f --- /dev/null +++ b/src/TUI/Engine/Nodes/Containers/ContainerBase.cs @@ -0,0 +1,10 @@ +using TUI.Engine.Nodes.Attributes.Orientations; + +namespace TUI.Engine.Nodes.Containers; + +public abstract class ContainerBase : NodeBase, IContainer +{ + public Orientation Orientation => Orientation.Horizontal; + + public abstract Nodes GetNodes(); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs index a938bdc..a508e98 100644 --- a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs +++ b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs @@ -7,6 +7,27 @@ namespace TUI.Engine.Nodes.Containers; public static class ContainerExtension { + // public static Position GetNextNodePosition(this INode node, + // Orientation orientation, + // Size allowableSize, + // Position currentChildrenPosition) + // { + // var nodeSize = node.GetSize(allowableSize); + // + // return orientation switch + // { + // Orientation.Horizontal => currentChildrenPosition with + // { + // Left = currentChildrenPosition.Left + nodeSize.Width + // }, + // Orientation.Vertical => currentChildrenPosition with + // { + // Top = currentChildrenPosition.Top + nodeSize.Height + // }, + // _ => throw new ArgumentOutOfRangeException() + // }; + // } + public static Size GetSize(this IContainer container, Size allowableSize) { var nodeCount = container.GetNodes().Count; @@ -27,19 +48,19 @@ public static class ComponentExtensions Size actualSize) { var left = sketchPosition.Left + (int)(component.Padding?.Left ?? 0) + - CompensationLeft(component.Alignment.AlignmentHorizontal, allowableSize, actualSize); + CompensationLeft(component.Alignment.Horizontal, 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, + private static int CompensationLeft(Horizontal componentHorizontal, Size defaultSize, Size realSize) => - componentAlignmentHorizontal switch + componentHorizontal switch { - AlignmentHorizontal.Left => 0, - AlignmentHorizontal.Center => (defaultSize.Width - realSize.Width) / 2, - AlignmentHorizontal.Right => defaultSize.Width - realSize.Width, + Horizontal.Left => 0, + Horizontal.Center => (defaultSize.Width - realSize.Width) / 2, + Horizontal.Right => defaultSize.Width - realSize.Width, _ => 0 }; diff --git a/src/TUI/Engine/Nodes/Containers/IContainer.cs b/src/TUI/Engine/Nodes/Containers/IContainer.cs index 1dfaa7e..4c37659 100644 --- a/src/TUI/Engine/Nodes/Containers/IContainer.cs +++ b/src/TUI/Engine/Nodes/Containers/IContainer.cs @@ -1,11 +1,9 @@ using TUI.Engine.Nodes.Attributes.Orientations; -using TUI.Engine.Nodes.Attributes.Resizings; namespace TUI.Engine.Nodes.Containers; public interface IContainer : INode, - IWithOrientation, - IWithResizing + IWithOrientation { public Nodes GetNodes(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/INode.cs b/src/TUI/Engine/Nodes/INode.cs index 52874c7..efbdfd7 100644 --- a/src/TUI/Engine/Nodes/INode.cs +++ b/src/TUI/Engine/Nodes/INode.cs @@ -1,5 +1,7 @@ +using TUI.Engine.Nodes.Attributes.Resizing; + namespace TUI.Engine.Nodes; -public interface INode +public interface INode : IResizable { } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/NodeBase.cs b/src/TUI/Engine/Nodes/NodeBase.cs new file mode 100644 index 0000000..021c06a --- /dev/null +++ b/src/TUI/Engine/Nodes/NodeBase.cs @@ -0,0 +1,64 @@ +using TUI.Engine.Nodes.Attributes.Orientations; +using TUI.Engine.Nodes.Attributes.Resizing; + +namespace TUI.Engine.Nodes; + +public abstract class NodeBase : INode +{ + private int _fixedWidth; + private int _fixedHeight; + + #region Resizing + + public Resizing ResizingHorizontal { get; private set; } = Resizing.Adaptive; + public Resizing ResizingVertical { get; private set; } = Resizing.Hug; + + public void SetAdaptive(Orientation orientation) + { + switch (orientation) + { + case Orientation.Horizontal: + ResizingHorizontal = Resizing.Adaptive; + break; + case Orientation.Vertical: + ResizingVertical = Resizing.Adaptive; + break; + default: + throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null); + } + } + + public void SetHug(Orientation orientation) + { + switch (orientation) + { + case Orientation.Horizontal: + ResizingHorizontal = Resizing.Hug; + break; + case Orientation.Vertical: + ResizingVertical = Resizing.Hug; + break; + default: + throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null); + } + } + + public void SetFixed(Orientation orientation, int value) + { + switch (orientation) + { + case Orientation.Horizontal: + ResizingHorizontal = Resizing.Fixed; + _fixedWidth = value; + break; + case Orientation.Vertical: + ResizingVertical = Resizing.Fixed; + _fixedHeight = value; + break; + default: + throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null); + } + } + + #endregion Resizing +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ContainerCraftsman.cs b/src/TUI/Engine/Rendering/ContainerCraftsman.cs index 42eda37..05f363d 100644 --- a/src/TUI/Engine/Rendering/ContainerCraftsman.cs +++ b/src/TUI/Engine/Rendering/ContainerCraftsman.cs @@ -1,4 +1,3 @@ -using System.Diagnostics; using TUI.Engine.Nodes; using TUI.Engine.Nodes.Attributes; using TUI.Engine.Nodes.Attributes.Orientations; @@ -67,4 +66,23 @@ public sealed class ContainerCraftsman : CraftsmanBase, IDrawable throw new InvalidCastException(); } } -} \ No newline at end of file +} + + +// private int GetWidth() => +// ResizingHorizontal switch +// { +// Resizing.Fixed => _fixedWidth, +// Resizing.Hug => GetAllowableSize().Width, +// Resizing.Adaptive => GetAllowableSize().Width, +// _ => 0 +// }; +// +// private int GetHeight() => +// ResizingVertical switch +// { +// Resizing.Fixed => _fixedHeight, +// Resizing.Hug => GetAllowableSize().Height, +// Resizing.Adaptive => GetAllowableSize().Height, +// _ => 0 +// }; diff --git a/src/TUI/Engine/Rendering/ICanvas.cs b/src/TUI/Engine/Rendering/ICanvas.cs index ef1e82c..88781c1 100644 --- a/src/TUI/Engine/Rendering/ICanvas.cs +++ b/src/TUI/Engine/Rendering/ICanvas.cs @@ -1,5 +1,3 @@ -using TUI.Engine.Nodes.Attributes; - namespace TUI.Engine.Rendering; public interface ICanvas diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 7742452..5456d84 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -21,9 +21,10 @@ public class DependenciesPage var nodeCraftsman = new NodeCraftsman(componentCraftsman, containerCraftsman); var header = new HeaderContainer(); - var copyright = new Copyright() - .Set(right: Level.Normal) - .Set(AlignmentHorizontal.Right, Vertical.Bottom); + var copyright = new Copyright(); + copyright.SetPaddingRight(Level.Normal); + copyright.SetAlignment(Horizontal.Right); + copyright.SetAlignment(Vertical.Bottom); var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright); // CommandLine = new CommandLine(); diff --git a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs b/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs index 9c67ad1..0d657a5 100644 --- a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs +++ b/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs @@ -10,16 +10,17 @@ public class ComponentBaseTests [Fact] public void WhenUseChainingSaveAllChange() { - var component = new Logo() - .Set(Level.Normal) - .Set(vertical: Vertical.Center, alignmentHorizontal: AlignmentHorizontal.Center); + var logo = new Logo(); + logo.SetPadding(Level.Normal); + logo.SetAlignment(Vertical.Center); + logo.SetAlignment(Horizontal.Center); - component.Padding.Top.Should().Be(Level.Normal); - component.Padding.Left.Should().Be(Level.Normal); - component.Padding.Bottom.Should().Be(Level.Normal); - component.Padding.Right.Should().Be(Level.Normal); - component.Alignment.AlignmentHorizontal.Should().Be(AlignmentHorizontal.Center); - component.Alignment.Vertical.Should().Be(Vertical.Center); + logo.Padding.Top.Should().Be(Level.Normal); + logo.Padding.Left.Should().Be(Level.Normal); + logo.Padding.Bottom.Should().Be(Level.Normal); + logo.Padding.Right.Should().Be(Level.Normal); + logo.Alignment.Horizontal.Should().Be(Horizontal.Center); + logo.Alignment.Vertical.Should().Be(Vertical.Center); } [Fact] @@ -27,7 +28,7 @@ public class ComponentBaseTests { var component = new Logo(); - component.Set(Level.Normal); + component.SetPadding(Level.Normal); component.Padding.Top.Should().Be(Level.Normal); component.Padding.Left.Should().Be(Level.Normal); @@ -43,22 +44,21 @@ public class ComponentBaseTests { var component = new Logo(); - component.Set(vertical: alignment); + component.SetAlignment(alignment); component.Alignment.Vertical.Should().Be(alignment); } [Theory] - [InlineData(AlignmentHorizontal.Left)] - [InlineData(AlignmentHorizontal.Center)] - [InlineData(AlignmentHorizontal.Right)] - public void WhenSetHorizontalAlignSaveAllChange(AlignmentHorizontal alignment) + [InlineData(Horizontal.Left)] + [InlineData(Horizontal.Center)] + [InlineData(Horizontal.Right)] + public void WhenSetHorizontalAlignSaveAllChange(Horizontal alignment) { var component = new Logo(); - component.Set(alignmentHorizontal: alignment); + component.SetAlignment(alignment); - component.Alignment.AlignmentHorizontal.Should().Be(alignment); + component.Alignment.Horizontal.Should().Be(alignment); } - } \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs index e4c1f87..127665c 100644 --- a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs +++ b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs @@ -2,7 +2,7 @@ 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.Attributes.Resizing; using TUI.Engine.Nodes.Components; using TUI.Engine.Nodes.Containers; using TUI.Engine.Rendering; @@ -17,7 +17,7 @@ public class NodeCraftsmanTests { _component = Mock.Of(c => c.Draw() == new Sketch("Lorem") && - c.Alignment == new Alignment(AlignmentHorizontal.Left, Vertical.Top)); + c.Alignment == new Alignment(Horizontal.Left, Vertical.Top)); } [Fact] @@ -36,14 +36,14 @@ public class NodeCraftsmanTests } [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, + [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(w => w.Width == canvasSize && w.Height == canvasSize); @@ -79,7 +79,7 @@ public class NodeCraftsmanTests { var canvas = Mock.Of(w => w.Width == canvasSize && w.Height == canvasSize); var component = Mock.Of(c => c.Draw() == new Sketch(content) && - c.Alignment == new Alignment(AlignmentHorizontal.Left, alignment)); + c.Alignment == new Alignment(Horizontal.Left, alignment)); var nodes = new Nodes { component }; var root = Mock.Of(r => r.GetNodes() == nodes); @@ -94,21 +94,21 @@ public class NodeCraftsmanTests } [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, + [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(w => w.Width == 6 && w.Height == 5); var component = Mock.Of(c => c.Draw() == new Sketch("VV") && - c.Alignment == new Alignment(alignmentHorizontal, vertical)); + c.Alignment == new Alignment(horizontal, vertical)); var nodes = new Nodes { component }; var root = Mock.Of(r => r.GetNodes() == nodes); @@ -157,7 +157,7 @@ public class NodeCraftsmanTests { var canvas = Mock.Of(w => w.Width == 10 && w.Height == 1); var nodes = new Nodes { _component, _component }; - var container = Mock.Of(g => g.GetNodes() == nodes); + var container = Mock.Of(g => g.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); var containerCraftsman = new ContainerCraftsman(componentCraftsman); From f32c34ff9e43a1a3fa3e0b848fa0586865393965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sat, 9 Mar 2024 13:25:37 +0500 Subject: [PATCH 07/23] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Refactor=20draw=20no?= =?UTF-8?q?de=20on=20container=20craftsman,?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Nodes/Containers/ContainerExtension.cs | 63 ++++++++++----- .../Engine/Rendering/ContainerCraftsman.cs | 79 +++++++------------ src/TUI/Engine/Rendering/IntegerExtension.cs | 6 ++ 3 files changed, 79 insertions(+), 69 deletions(-) create mode 100644 src/TUI/Engine/Rendering/IntegerExtension.cs diff --git a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs index a508e98..513d289 100644 --- a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs +++ b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs @@ -1,32 +1,55 @@ 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; namespace TUI.Engine.Nodes.Containers; public static class ContainerExtension { - // public static Position GetNextNodePosition(this INode node, - // Orientation orientation, - // Size allowableSize, - // Position currentChildrenPosition) - // { - // var nodeSize = node.GetSize(allowableSize); - // - // return orientation switch - // { - // Orientation.Horizontal => currentChildrenPosition with - // { - // Left = currentChildrenPosition.Left + nodeSize.Width - // }, - // Orientation.Vertical => currentChildrenPosition with - // { - // Top = currentChildrenPosition.Top + nodeSize.Height - // }, - // _ => throw new ArgumentOutOfRangeException() - // }; - // } + public static Size GetSize(this IContainer container, Resizing resizing) + { + int width = resizing switch + { + // Resizing.Fixed => _fixedWeight, + // Resizing.Hug => GetAllowableSize().Width, + // Resizing.Adaptive => GetAllowableSize().Width, + _ => 0 + }; + + int height = resizing switch + { + // Resizing.Fixed => _fixedHeight, + // Resizing.Hug => GetAllowableSize().Height, + // Resizing.Adaptive => GetAllowableSize().Height, + _ => 0 + }; + + return new Size(width, height); + } + + public static Position GetNextNodePosition(this IContainer container, Orientation orientation, Size allowableSize, + Position containerPosition) + { + var nodeSize = container.GetSize(allowableSize); + + return GetNextNodePosition(orientation, nodeSize, containerPosition); + } + + private static Position GetNextNodePosition(Orientation orientation, Size nodeSize, Position nodePosition) => + orientation switch + { + Orientation.Horizontal => nodePosition with + { + Left = nodePosition.Left + nodeSize.Width + }, + Orientation.Vertical => nodePosition with + { + Top = nodePosition.Top + nodeSize.Height + }, + _ => throw new ArgumentOutOfRangeException() + }; public static Size GetSize(this IContainer container, Size allowableSize) { diff --git a/src/TUI/Engine/Rendering/ContainerCraftsman.cs b/src/TUI/Engine/Rendering/ContainerCraftsman.cs index 05f363d..2a70802 100644 --- a/src/TUI/Engine/Rendering/ContainerCraftsman.cs +++ b/src/TUI/Engine/Rendering/ContainerCraftsman.cs @@ -19,14 +19,13 @@ public sealed class ContainerCraftsman : CraftsmanBase, IDrawable public Size Draw(IContainer container, Position sketchPosition, Size allowableSize) { var sketchSize = container.GetSize(allowableSize); - var controlNumber = 0; + var nodes = container.GetNodes(); - while (controlNumber < container.GetNodes().Count) + while (controlNumber < nodes.Count) { - var node = container.GetNodes()[controlNumber]; - - sketchPosition = RenderNode(node, container.Orientation, sketchSize, sketchPosition); + var node = nodes[controlNumber]; + sketchPosition = DrawNode(node, container.Orientation, sketchPosition, sketchSize); controlNumber++; } @@ -34,55 +33,37 @@ public sealed class ContainerCraftsman : CraftsmanBase, IDrawable return sketchSize; } - private Position RenderNode(INode node, Orientation orientation, Size defaultSize, Position position) + private Position DrawNode(INode node, Orientation orientation, Position sketchPosition, Size sketchSize) { 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) - }; + case IContainer childContainer: + Draw(childContainer, sketchPosition, sketchSize); + return GetNextNodePosition(orientation, sketchSize, sketchPosition); + case IComponent childComponent: + var componentSize = _componentCraftsman.Draw(childComponent, sketchPosition, sketchSize); + return GetNextNodePosition(orientation, sketchSize, sketchPosition, componentSize); default: throw new InvalidCastException(); } } -} - -// private int GetWidth() => -// ResizingHorizontal switch -// { -// Resizing.Fixed => _fixedWidth, -// Resizing.Hug => GetAllowableSize().Width, -// Resizing.Adaptive => GetAllowableSize().Width, -// _ => 0 -// }; -// -// private int GetHeight() => -// ResizingVertical switch -// { -// Resizing.Fixed => _fixedHeight, -// Resizing.Hug => GetAllowableSize().Height, -// Resizing.Adaptive => GetAllowableSize().Height, -// _ => 0 -// }; + private static Position GetNextNodePosition( + Orientation orientation, + Size defaultSize, + Position position, + Size? componentSize = null) + { + switch (orientation) + { + case Orientation.Horizontal: + var componentWidth = componentSize?.Width.Max(defaultSize.Width) ?? defaultSize.Width; + return position with { Left = position.Left + componentWidth }; + case Orientation.Vertical: + var componentHeight = componentSize?.Height.Max(defaultSize.Height) ?? defaultSize.Height; + return position with { Top = position.Top + componentHeight }; + default: + throw new InvalidCastException(); + } + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IntegerExtension.cs b/src/TUI/Engine/Rendering/IntegerExtension.cs new file mode 100644 index 0000000..af53b8b --- /dev/null +++ b/src/TUI/Engine/Rendering/IntegerExtension.cs @@ -0,0 +1,6 @@ +namespace TUI.Engine.Rendering; + +public static class IntegerExtension +{ + public static int Max(this int value, int maxValue) => maxValue <= value ? value : maxValue; +} \ No newline at end of file From e15e42dbe8df18bb0edbf6e112e3237a13c22fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sun, 10 Mar 2024 01:09:28 +0500 Subject: [PATCH 08/23] =?UTF-8?q?=F0=9F=A7=AA=20Change=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/Controls/HeaderContainer.cs | 4 + src/TUI/Engine/Helper.cs | 2 +- .../Nodes/Attributes/Paddings/IPaddingable.cs | 2 +- .../Nodes/Attributes/Resizing/IResizable.cs | 2 +- .../Nodes/Attributes/Resizing/Resizing.cs | 3 +- .../Engine/Nodes/Components/ComponentBase.cs | 2 +- src/TUI/Engine/Nodes/Components/IComponent.cs | 2 +- src/TUI/Engine/Nodes/Components/Sketch.cs | 2 +- .../Engine/Nodes/Containers/ContainerBase.cs | 6 ++ .../Nodes/Containers/ContainerExtension.cs | 93 ++++++------------- src/TUI/Engine/Nodes/Containers/IContainer.cs | 7 +- src/TUI/Engine/Nodes/NodeBase.cs | 20 +--- .../Engine/Rendering/ComponentCraftsman.cs | 24 ++--- .../Engine/Rendering/ContainerCraftsman.cs | 41 +++++--- src/TUI/Engine/Rendering/IDrawable.cs | 2 +- src/TUI/Engine/Rendering/IntegerExtension.cs | 2 +- src/TUI/Engine/Rendering/NodeCraftsman.cs | 9 +- .../WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs | 61 ++++++------ tests/WIdgets/TUI.Tests/Controls/LogoTests.cs | 2 +- tests/WIdgets/TUI.Tests/IntegerTests.cs | 22 +++++ tests/WIdgets/TUI.Tests/TestComponent.cs | 18 ++++ 21 files changed, 167 insertions(+), 159 deletions(-) create mode 100644 tests/WIdgets/TUI.Tests/IntegerTests.cs create mode 100644 tests/WIdgets/TUI.Tests/TestComponent.cs diff --git a/src/TUI/Components/Controls/HeaderContainer.cs b/src/TUI/Components/Controls/HeaderContainer.cs index 912ce23..0a01794 100644 --- a/src/TUI/Components/Controls/HeaderContainer.cs +++ b/src/TUI/Components/Controls/HeaderContainer.cs @@ -13,15 +13,19 @@ public class HeaderContainer : ContainerBase, IContainer { var versionHints = new VersionHints(); versionHints.SetPadding(Indentation.Default); + versionHints.SetAlignment(Horizontal.Left); var tagsHints = new TagHints(); tagsHints.SetPadding(Indentation.Default); + tagsHints.SetAlignment(Horizontal.Left); var appTypeHints = new AppTypeHints(); appTypeHints.SetPadding(Indentation.Default); + appTypeHints.SetAlignment(Horizontal.Left); var hotkeysHints = new HotkeysHint(); hotkeysHints.SetPadding(Indentation.Default); + hotkeysHints.SetAlignment(Horizontal.Left); var logo = new Logo(); logo.SetAlignment(Horizontal.Right); diff --git a/src/TUI/Engine/Helper.cs b/src/TUI/Engine/Helper.cs index 2ea4241..ab871c0 100644 --- a/src/TUI/Engine/Helper.cs +++ b/src/TUI/Engine/Helper.cs @@ -22,7 +22,7 @@ public static class Helper public static void ShowBackground(Position position, Size size) { - return; + return; var color = Colors.Dequeue(); var top = position.Top; diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs b/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs index 6932bcb..b100181 100644 --- a/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs +++ b/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs @@ -4,7 +4,7 @@ namespace TUI.Engine.Nodes.Attributes.Paddings; public interface IPaddingable { - Padding? Padding { get; } + Padding Padding { get; } void SetPadding(Level level); void SetPaddingLeft(Level level); diff --git a/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs b/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs index 6c6f2f6..2773ce8 100644 --- a/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs +++ b/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs @@ -9,6 +9,6 @@ public interface IResizable Resizing ResizingVertical { get; } void SetAdaptive(Orientation orientation); - void SetHug(Orientation orientation); void SetFixed(Orientation orientation, int value); + Size GetFixedSize(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs b/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs index db3984d..a213eb1 100644 --- a/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs +++ b/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs @@ -3,6 +3,5 @@ namespace TUI.Engine.Nodes.Attributes.Resizing; public enum Resizing { Adaptive, - Fixed, - Hug, + Fixed } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentBase.cs b/src/TUI/Engine/Nodes/Components/ComponentBase.cs index 7027dbb..862547e 100644 --- a/src/TUI/Engine/Nodes/Components/ComponentBase.cs +++ b/src/TUI/Engine/Nodes/Components/ComponentBase.cs @@ -14,7 +14,7 @@ public abstract class ComponentBase : NodeBase, IComponent public abstract Sketch DrawComponent(); - public Sketch Draw() + public Sketch MakeSketch() { var sketch = DrawComponent(); _sketchSize = sketch.GetSize(); diff --git a/src/TUI/Engine/Nodes/Components/IComponent.cs b/src/TUI/Engine/Nodes/Components/IComponent.cs index 4883d76..a1bf772 100644 --- a/src/TUI/Engine/Nodes/Components/IComponent.cs +++ b/src/TUI/Engine/Nodes/Components/IComponent.cs @@ -5,5 +5,5 @@ namespace TUI.Engine.Nodes.Components; public interface IComponent : INode, IAlignable, IPaddingable { - Sketch Draw(); + Sketch MakeSketch(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/Sketch.cs b/src/TUI/Engine/Nodes/Components/Sketch.cs index f5c8768..aba0983 100644 --- a/src/TUI/Engine/Nodes/Components/Sketch.cs +++ b/src/TUI/Engine/Nodes/Components/Sketch.cs @@ -10,7 +10,7 @@ public sealed class Sketch : IEnumerable public IEnumerator GetEnumerator() => ContentRows.GetEnumerator(); - public IEnumerable Rows(Size maxSize) => + public IEnumerable Crop(Size maxSize) => ContentRows.Where(row => maxSize.Width >= row.GetWidth()).Take(maxSize.Height).ToArray(); public Size GetSize() diff --git a/src/TUI/Engine/Nodes/Containers/ContainerBase.cs b/src/TUI/Engine/Nodes/Containers/ContainerBase.cs index 60c499f..416a5e9 100644 --- a/src/TUI/Engine/Nodes/Containers/ContainerBase.cs +++ b/src/TUI/Engine/Nodes/Containers/ContainerBase.cs @@ -1,3 +1,4 @@ +using TUI.Engine.Nodes.Attributes; using TUI.Engine.Nodes.Attributes.Orientations; namespace TUI.Engine.Nodes.Containers; @@ -6,5 +7,10 @@ public abstract class ContainerBase : NodeBase, IContainer { public Orientation Orientation => Orientation.Horizontal; + public Size GetSketchSize() + { + throw new NotImplementedException(); + } + public abstract Nodes GetNodes(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs index 513d289..b1ebcb6 100644 --- a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs +++ b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs @@ -8,55 +8,17 @@ namespace TUI.Engine.Nodes.Containers; public static class ContainerExtension { - public static Size GetSize(this IContainer container, Resizing resizing) - { - int width = resizing switch - { - // Resizing.Fixed => _fixedWeight, - // Resizing.Hug => GetAllowableSize().Width, - // Resizing.Adaptive => GetAllowableSize().Width, - _ => 0 - }; - - int height = resizing switch - { - // Resizing.Fixed => _fixedHeight, - // Resizing.Hug => GetAllowableSize().Height, - // Resizing.Adaptive => GetAllowableSize().Height, - _ => 0 - }; - - return new Size(width, height); - } - - public static Position GetNextNodePosition(this IContainer container, Orientation orientation, Size allowableSize, - Position containerPosition) - { - var nodeSize = container.GetSize(allowableSize); - - return GetNextNodePosition(orientation, nodeSize, containerPosition); - } - - private static Position GetNextNodePosition(Orientation orientation, Size nodeSize, Position nodePosition) => - orientation switch - { - Orientation.Horizontal => nodePosition with - { - Left = nodePosition.Left + nodeSize.Width - }, - Orientation.Vertical => nodePosition with - { - Top = nodePosition.Top + nodeSize.Height - }, - _ => throw new ArgumentOutOfRangeException() - }; - 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 width = container.ResizingHorizontal switch + { + Resizing.Adaptive => container.Orientation == Orientation.Horizontal + ? allowableSize.Width / nodeCount + : allowableSize.Width, + Resizing.Fixed => container.GetFixedSize().Width, + _ => throw new ArgumentOutOfRangeException() + }; var height = container.Orientation == Orientation.Vertical ? allowableSize.Height / nodeCount : allowableSize.Height; @@ -67,33 +29,32 @@ public static class ContainerExtension public static class ComponentExtensions { - public static Position GetPosition(this IComponent component, Position sketchPosition, Size allowableSize, - Size actualSize) + public static Position CorrectPosition(this IComponent component, Position pencil, Size maxSize, Size sketchSize) { - var left = sketchPosition.Left + (int)(component.Padding?.Left ?? 0) + - CompensationLeft(component.Alignment.Horizontal, allowableSize, actualSize); - var top = sketchPosition.Top + (int)(component.Padding?.Top ?? 0) + - CompensationTop(component.Alignment.Vertical, allowableSize, actualSize); + 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 CompensationLeft(Horizontal componentHorizontal, Size defaultSize, - Size realSize) => - componentHorizontal switch + private static int GetAlignmentCompensationLeft(Horizontal alignment, Size maxSize, Size sketchSize) => + alignment switch { Horizontal.Left => 0, - Horizontal.Center => (defaultSize.Width - realSize.Width) / 2, - Horizontal.Right => defaultSize.Width - realSize.Width, + Horizontal.Center => (maxSize.Width - sketchSize.Width) / 2, + Horizontal.Right => maxSize.Width - sketchSize.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 - }; + 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 + }; } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/IContainer.cs b/src/TUI/Engine/Nodes/Containers/IContainer.cs index 4c37659..85c2500 100644 --- a/src/TUI/Engine/Nodes/Containers/IContainer.cs +++ b/src/TUI/Engine/Nodes/Containers/IContainer.cs @@ -1,9 +1,10 @@ +using TUI.Engine.Nodes.Attributes; using TUI.Engine.Nodes.Attributes.Orientations; namespace TUI.Engine.Nodes.Containers; -public interface IContainer : INode, - IWithOrientation +public interface IContainer : INode, IWithOrientation { - public Nodes GetNodes(); + Size GetSketchSize(); + Nodes GetNodes(); } \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/NodeBase.cs b/src/TUI/Engine/Nodes/NodeBase.cs index 021c06a..ec121ef 100644 --- a/src/TUI/Engine/Nodes/NodeBase.cs +++ b/src/TUI/Engine/Nodes/NodeBase.cs @@ -1,3 +1,4 @@ +using TUI.Engine.Nodes.Attributes; using TUI.Engine.Nodes.Attributes.Orientations; using TUI.Engine.Nodes.Attributes.Resizing; @@ -8,10 +9,12 @@ public abstract class NodeBase : INode private int _fixedWidth; private int _fixedHeight; + public Size GetFixedSize() => new(_fixedWidth, _fixedHeight); + #region Resizing public Resizing ResizingHorizontal { get; private set; } = Resizing.Adaptive; - public Resizing ResizingVertical { get; private set; } = Resizing.Hug; + public Resizing ResizingVertical { get; private set; } = Resizing.Adaptive; public void SetAdaptive(Orientation orientation) { @@ -28,21 +31,6 @@ public abstract class NodeBase : INode } } - public void SetHug(Orientation orientation) - { - switch (orientation) - { - case Orientation.Horizontal: - ResizingHorizontal = Resizing.Hug; - break; - case Orientation.Vertical: - ResizingVertical = Resizing.Hug; - break; - default: - throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null); - } - } - public void SetFixed(Orientation orientation, int value) { switch (orientation) diff --git a/src/TUI/Engine/Rendering/ComponentCraftsman.cs b/src/TUI/Engine/Rendering/ComponentCraftsman.cs index 577eed5..8182efe 100644 --- a/src/TUI/Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI/Engine/Rendering/ComponentCraftsman.cs @@ -14,23 +14,23 @@ public sealed class ComponentCraftsman : CraftsmanBase, IDrawable _canvas = canvas; } - public Size Draw(IComponent component, Position sketchPosition, Size allowableSize) + public Size Draw(IComponent component, Position pencil, Size maxSize) { - var sketch = component.Draw(); - var actualSize = sketch.GetSize(); - var maxSize = _canvas.GetSize() - sketchPosition; - var pencilPosition = component.GetPosition(sketchPosition, allowableSize, actualSize); + var sketch = component.MakeSketch(); + var sketchSize = sketch.GetSize(); - foreach (var row in sketch.Rows(maxSize)) + var correctedPencil = component.CorrectPosition(pencil, maxSize, sketchSize); + + Debug(correctedPencil, pencil, maxSize); + + foreach (var line in sketch.Crop(maxSize)) { - _canvas.SetPencil(pencilPosition.Left, pencilPosition.Top); - _canvas.Paint(row); + _canvas.SetPencil(correctedPencil.Left, correctedPencil.Top); + _canvas.Paint(line); - pencilPosition = pencilPosition with { Top = pencilPosition.Top + 1 }; + correctedPencil = correctedPencil with { Top = correctedPencil.Top + 1 }; } - Debug(pencilPosition, sketchPosition, allowableSize); - - return actualSize; + return sketchSize; } } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ContainerCraftsman.cs b/src/TUI/Engine/Rendering/ContainerCraftsman.cs index 2a70802..cad67f9 100644 --- a/src/TUI/Engine/Rendering/ContainerCraftsman.cs +++ b/src/TUI/Engine/Rendering/ContainerCraftsman.cs @@ -1,6 +1,7 @@ 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; @@ -15,52 +16,64 @@ public sealed class ContainerCraftsman : CraftsmanBase, IDrawable _componentCraftsman = componentCraftsman; } - - public Size Draw(IContainer container, Position sketchPosition, Size allowableSize) + public Size Draw(IContainer container, Position pencil, Size maxSize) { - var sketchSize = container.GetSize(allowableSize); var controlNumber = 0; + var nextNodePosition = pencil; var nodes = container.GetNodes(); + var sketchSize = container.GetSize(maxSize); + Debug(nextNodePosition, nextNodePosition, maxSize); while (controlNumber < nodes.Count) { var node = nodes[controlNumber]; - sketchPosition = DrawNode(node, container.Orientation, sketchPosition, sketchSize); + nextNodePosition = DrawNode(node, container, nextNodePosition, sketchSize); controlNumber++; } - Debug(sketchPosition, sketchPosition, allowableSize); return sketchSize; } - private Position DrawNode(INode node, Orientation orientation, Position sketchPosition, Size sketchSize) + private Position DrawNode(INode node, IContainer container, Position nodePosition, Size maxSize) { switch (node) { case IContainer childContainer: - Draw(childContainer, sketchPosition, sketchSize); - return GetNextNodePosition(orientation, sketchSize, sketchPosition); + var containerSize = Draw(childContainer, nodePosition, maxSize); + return GetNextNodePosition(container, containerSize, nodePosition); case IComponent childComponent: - var componentSize = _componentCraftsman.Draw(childComponent, sketchPosition, sketchSize); - return GetNextNodePosition(orientation, sketchSize, sketchPosition, componentSize); + var componentSize = _componentCraftsman.Draw(childComponent, nodePosition, maxSize); + return GetNextNodePosition(container, maxSize, nodePosition, componentSize); default: throw new InvalidCastException(); } } private static Position GetNextNodePosition( - Orientation orientation, + IContainer container, Size defaultSize, Position position, Size? componentSize = null) { - switch (orientation) + switch (container.Orientation) { case Orientation.Horizontal: - var componentWidth = componentSize?.Width.Max(defaultSize.Width) ?? defaultSize.Width; + var componentWidth = container.ResizingHorizontal switch + { + Resizing.Adaptive => defaultSize.Width, + Resizing.Fixed => componentSize?.Width.Max(container.GetFixedSize().Width) ?? + container.GetFixedSize().Width, + _ => 0 + }; return position with { Left = position.Left + componentWidth }; case Orientation.Vertical: - var componentHeight = componentSize?.Height.Max(defaultSize.Height) ?? defaultSize.Height; + var componentHeight = container.ResizingVertical switch + { + Resizing.Adaptive => defaultSize.Height, + Resizing.Fixed => componentSize?.Height.Max(container.GetFixedSize().Height) ?? + container.GetFixedSize().Height, + _ => 0 + }; return position with { Top = position.Top + componentHeight }; default: throw new InvalidCastException(); diff --git a/src/TUI/Engine/Rendering/IDrawable.cs b/src/TUI/Engine/Rendering/IDrawable.cs index a196386..05ae2bc 100644 --- a/src/TUI/Engine/Rendering/IDrawable.cs +++ b/src/TUI/Engine/Rendering/IDrawable.cs @@ -5,5 +5,5 @@ namespace TUI.Engine.Rendering; public interface IDrawable where TItem : INode { - Size Draw(TItem item, Position sketchPosition, Size allowableSize); + Size Draw(TItem item, Position pencil, Size maxSize); } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IntegerExtension.cs b/src/TUI/Engine/Rendering/IntegerExtension.cs index af53b8b..d31959d 100644 --- a/src/TUI/Engine/Rendering/IntegerExtension.cs +++ b/src/TUI/Engine/Rendering/IntegerExtension.cs @@ -2,5 +2,5 @@ namespace TUI.Engine.Rendering; public static class IntegerExtension { - public static int Max(this int value, int maxValue) => maxValue <= value ? value : maxValue; + public static int Max(this int value, int maxValue) => value <= maxValue ? value : maxValue; } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/NodeCraftsman.cs b/src/TUI/Engine/Rendering/NodeCraftsman.cs index a73c939..ec62349 100644 --- a/src/TUI/Engine/Rendering/NodeCraftsman.cs +++ b/src/TUI/Engine/Rendering/NodeCraftsman.cs @@ -5,6 +5,9 @@ using TUI.Engine.Nodes.Containers; namespace TUI.Engine.Rendering; +/// +/// 🍀 +/// public sealed class NodeCraftsman : IDrawable { private readonly IDrawable _componentCraftsman; @@ -18,11 +21,11 @@ public sealed class NodeCraftsman : IDrawable _containerCraftsman = containerCraftsman; } - public Size Draw(INode node, Position sketchPosition, Size allowableSize) => + public Size Draw(INode node, Position pencil, Size maxSize) => node switch { - IContainer container => _containerCraftsman.Draw(container, sketchPosition, allowableSize), - IComponent component => _componentCraftsman.Draw(component, sketchPosition, allowableSize), + IContainer container => _containerCraftsman.Draw(container, pencil, maxSize), + IComponent component => _componentCraftsman.Draw(component, pencil, maxSize), _ => throw new InvalidCastException("Unknown node type.") }; } \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs index 127665c..e5a2bfc 100644 --- a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs +++ b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs @@ -1,9 +1,9 @@ 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.Components; using TUI.Engine.Nodes.Containers; using TUI.Engine.Rendering; @@ -11,25 +11,22 @@ namespace Widgets.Tests; public class NodeCraftsmanTests { - private readonly IComponent _component; + private readonly TestComponent _component; public NodeCraftsmanTests() { - _component = Mock.Of(c => - c.Draw() == new Sketch("Lorem") && - c.Alignment == new Alignment(Horizontal.Left, Vertical.Top)); + _component = new TestComponent(); + _component.SetAlignment(Horizontal.Left); + _component.SetAlignment(Vertical.Top); } [Fact] public void DrawSimple() { var canvas = Mock.Of(w => w.Width == 9 && w.Height == 1); - var nodes = new Nodes { _component }; - var root = Mock.Of(r => r.GetNodes() == nodes); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + 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()); @@ -47,14 +44,12 @@ public class NodeCraftsmanTests int expectedPosition) { var canvas = Mock.Of(w => w.Width == canvasSize && w.Height == canvasSize); - var component = Mock.Of(c => c.Draw() == new Sketch(content) && - c.Alignment == new Alignment(alignment, Vertical.Top)); - var nodes = new Nodes { component }; - var root = Mock.Of(r => r.GetNodes() == nodes); + _component.SetContent(content); + _component.SetAlignment(Vertical.Top); + _component.SetAlignment(alignment); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + 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()); @@ -78,14 +73,12 @@ public class NodeCraftsmanTests public void DrawWithVerticalAlignment(Vertical alignment, string content, int canvasSize, int[] expectedPositions) { var canvas = Mock.Of(w => w.Width == canvasSize && w.Height == canvasSize); - var component = Mock.Of(c => c.Draw() == new Sketch(content) && - c.Alignment == new Alignment(Horizontal.Left, alignment)); - var nodes = new Nodes { component }; - var root = Mock.Of(r => r.GetNodes() == nodes); + _component.SetContent(content); + _component.SetAlignment(Horizontal.Left); + _component.SetAlignment(alignment); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + componentCraftsman.Draw(_component, Position.Default, canvas.GetSize()); foreach (var expectedCursorPosition in expectedPositions) { @@ -107,14 +100,12 @@ public class NodeCraftsmanTests int expectedTop) { var canvas = Mock.Of(w => w.Width == 6 && w.Height == 5); - var component = Mock.Of(c => c.Draw() == new Sketch("VV") && - c.Alignment == new Alignment(horizontal, vertical)); - var nodes = new Nodes { component }; - var root = Mock.Of(r => r.GetNodes() == nodes); + _component.SetContent("VV"); + _component.SetAlignment(horizontal); + _component.SetAlignment(vertical); var componentCraftsman = new ComponentCraftsman(canvas); - var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + componentCraftsman.Draw(_component, Position.Default, canvas.GetSize()); Mock.Get(canvas).Verify(w => w.SetPencil(expectedLeft, expectedTop), Times.Once()); } @@ -130,7 +121,7 @@ public class NodeCraftsmanTests var componentCraftsman = new ComponentCraftsman(canvas); var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + containerCraftsman.Draw(root, Position.Default, canvas.GetSize()); Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Once()); Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Once()); @@ -177,7 +168,7 @@ public class NodeCraftsmanTests var componentCraftsman = new ComponentCraftsman(canvas); var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + 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)); @@ -196,7 +187,7 @@ public class NodeCraftsmanTests var componentCraftsman = new ComponentCraftsman(canvas); var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + 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)); @@ -204,20 +195,22 @@ public class NodeCraftsmanTests } [Theory] - [InlineData(Resizing.Hug, 5)] + [InlineData(Resizing.Fixed, 6)] [InlineData(Resizing.Fixed, 3)] [InlineData(Resizing.Adaptive, 10)] - public void DrawWithResizeContainer(Resizing resizing, int expectedCursorPosition) + public void DrawResizingContainer(Resizing resizing, int expectedCursorPosition) { var canvas = Mock.Of(w => w.Width == 20 && w.Height == 2); var container = - Mock.Of(c => c.GetNodes() == new Nodes { _component } && c.ResizingHorizontal == resizing); + Mock.Of(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(r => r.GetNodes() == nodes && r.Orientation == Orientation.Horizontal); var componentCraftsman = new ComponentCraftsman(canvas); var containerCraftsman = new ContainerCraftsman(componentCraftsman); - new NodeCraftsman(componentCraftsman, containerCraftsman).Draw(root, Position.Default, canvas.GetSize()); + 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)); diff --git a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs index 306b9ac..9455f0f 100644 --- a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs +++ b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs @@ -9,7 +9,7 @@ public class LogoTests { var logo = new Logo(); - var render = logo.Draw().ToString(); + 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", diff --git a/tests/WIdgets/TUI.Tests/IntegerTests.cs b/tests/WIdgets/TUI.Tests/IntegerTests.cs new file mode 100644 index 0000000..71e9e7e --- /dev/null +++ b/tests/WIdgets/TUI.Tests/IntegerTests.cs @@ -0,0 +1,22 @@ +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); + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/TestComponent.cs b/tests/WIdgets/TUI.Tests/TestComponent.cs new file mode 100644 index 0000000..d018319 --- /dev/null +++ b/tests/WIdgets/TUI.Tests/TestComponent.cs @@ -0,0 +1,18 @@ +using TUI.Engine.Nodes.Components; + +namespace Widgets.Tests; + +internal class TestComponent : ComponentBase +{ + private string _content = "Lorem"; + + public void SetContent(string content) + { + _content = content; + } + + public override Sketch DrawComponent() + { + return new Sketch(_content); + } +} \ No newline at end of file From 3c2f945480abfea20f20c213ebdd538502c73237 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Thu, 14 Mar 2024 00:09:18 +0500 Subject: [PATCH 09/23] =?UTF-8?q?=E2=9C=A8=20Finish=20overload=20by=20vert?= =?UTF-8?q?ical.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI/Engine/Helper.cs | 11 ++- src/TUI/Engine/Nodes/Components/Sketch.cs | 6 +- .../Nodes/Containers/ContainerExtension.cs | 84 +++++++++++++++---- .../Engine/Rendering/ComponentCraftsman.cs | 2 +- .../Engine/Rendering/ContainerCraftsman.cs | 18 ++-- src/TUI/Engine/Rendering/CraftsmanBase.cs | 4 +- src/TUI/Engine/Rendering/IntegerExtension.cs | 1 + src/TUI/Pages/DependenciesPage.cs | 3 + .../WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs | 29 ++++++- 9 files changed, 124 insertions(+), 34 deletions(-) diff --git a/src/TUI/Engine/Helper.cs b/src/TUI/Engine/Helper.cs index ab871c0..2217059 100644 --- a/src/TUI/Engine/Helper.cs +++ b/src/TUI/Engine/Helper.cs @@ -8,7 +8,7 @@ public static class Helper { private static readonly Queue Colors = new(); - static Helper() + private static void Init() { Colors.Enqueue(ConsoleColor.DarkYellow); Colors.Enqueue(ConsoleColor.DarkMagenta); @@ -22,9 +22,14 @@ public static class Helper public static void ShowBackground(Position position, Size size) { - return; + // return; + if (!Colors.Any()) + { + Init(); + } + var color = Colors.Dequeue(); - + var top = position.Top; var height = 0; diff --git a/src/TUI/Engine/Nodes/Components/Sketch.cs b/src/TUI/Engine/Nodes/Components/Sketch.cs index aba0983..d2c02a5 100644 --- a/src/TUI/Engine/Nodes/Components/Sketch.cs +++ b/src/TUI/Engine/Nodes/Components/Sketch.cs @@ -10,8 +10,10 @@ public sealed class Sketch : IEnumerable public IEnumerator GetEnumerator() => ContentRows.GetEnumerator(); - public IEnumerable Crop(Size maxSize) => - ContentRows.Where(row => maxSize.Width >= row.GetWidth()).Take(maxSize.Height).ToArray(); + public IEnumerable Crop(Size maxSize) => ContentRows + .Select(row => maxSize.Width < row.GetWidth() ? row[..maxSize.Width] : row) + .Take(maxSize.Height) + .ToArray(); public Size GetSize() { diff --git a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs index b1ebcb6..02e9b83 100644 --- a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs +++ b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs @@ -3,28 +3,84 @@ using TUI.Engine.Nodes.Attributes.Alignments; using TUI.Engine.Nodes.Attributes.Orientations; using TUI.Engine.Nodes.Attributes.Resizing; using TUI.Engine.Nodes.Components; +using TUI.Engine.Rendering; namespace TUI.Engine.Nodes.Containers; public static class ContainerExtension { - public static Size GetSize(this IContainer container, Size allowableSize) + public static Size GetSize(this INode node, IContainer parentContainer, int nodeNumber, Size allowableSize) { - var nodeCount = container.GetNodes().Count; - var width = container.ResizingHorizontal switch - { - Resizing.Adaptive => container.Orientation == Orientation.Horizontal - ? allowableSize.Width / nodeCount - : allowableSize.Width, - Resizing.Fixed => container.GetFixedSize().Width, - _ => throw new ArgumentOutOfRangeException() - }; - var height = container.Orientation == Orientation.Vertical - ? allowableSize.Height / nodeCount - : allowableSize.Height; - + var width = GetWidth(node, parentContainer, allowableSize.Width); + var height = GetHeight(node, parentContainer, allowableSize.Height, nodeNumber); return new Size(width, height); } + + private static IEnumerable 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 diff --git a/src/TUI/Engine/Rendering/ComponentCraftsman.cs b/src/TUI/Engine/Rendering/ComponentCraftsman.cs index 8182efe..27e293c 100644 --- a/src/TUI/Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI/Engine/Rendering/ComponentCraftsman.cs @@ -21,7 +21,7 @@ public sealed class ComponentCraftsman : CraftsmanBase, IDrawable var correctedPencil = component.CorrectPosition(pencil, maxSize, sketchSize); - Debug(correctedPencil, pencil, maxSize); + Debug(pencil, maxSize); foreach (var line in sketch.Crop(maxSize)) { diff --git a/src/TUI/Engine/Rendering/ContainerCraftsman.cs b/src/TUI/Engine/Rendering/ContainerCraftsman.cs index cad67f9..7999ad0 100644 --- a/src/TUI/Engine/Rendering/ContainerCraftsman.cs +++ b/src/TUI/Engine/Rendering/ContainerCraftsman.cs @@ -18,20 +18,22 @@ public sealed class ContainerCraftsman : CraftsmanBase, IDrawable public Size Draw(IContainer container, Position pencil, Size maxSize) { - var controlNumber = 0; + var nodeNumber = 0; var nextNodePosition = pencil; var nodes = container.GetNodes(); - var sketchSize = container.GetSize(maxSize); - Debug(nextNodePosition, nextNodePosition, maxSize); - while (controlNumber < nodes.Count) + Debug(nextNodePosition, maxSize); + + while (nodeNumber < nodes.Count) { - var node = nodes[controlNumber]; - nextNodePosition = DrawNode(node, container, nextNodePosition, sketchSize); - controlNumber++; + var node = nodes[nodeNumber]; + var nodeSize = node.GetSize(container, nodeNumber, maxSize); + + nextNodePosition = DrawNode(node, container, nextNodePosition, nodeSize); + nodeNumber++; } - return sketchSize; + return maxSize; } private Position DrawNode(INode node, IContainer container, Position nodePosition, Size maxSize) diff --git a/src/TUI/Engine/Rendering/CraftsmanBase.cs b/src/TUI/Engine/Rendering/CraftsmanBase.cs index 20d8ad6..6c50bf9 100644 --- a/src/TUI/Engine/Rendering/CraftsmanBase.cs +++ b/src/TUI/Engine/Rendering/CraftsmanBase.cs @@ -6,9 +6,9 @@ namespace TUI.Engine.Rendering; public abstract class CraftsmanBase { - protected void Debug(Position pencilPosition, Position sketchPosition, Size allowableSize) + protected void Debug(Position pencilPosition, Size allowableSize) { Debugger.Log(0, "Draw", $"{pencilPosition}{GetType().Name}.\n"); - Helper.ShowBackground(sketchPosition, allowableSize); + Helper.ShowBackground(pencilPosition, allowableSize); } } \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IntegerExtension.cs b/src/TUI/Engine/Rendering/IntegerExtension.cs index d31959d..b142d85 100644 --- a/src/TUI/Engine/Rendering/IntegerExtension.cs +++ b/src/TUI/Engine/Rendering/IntegerExtension.cs @@ -3,4 +3,5 @@ namespace TUI.Engine.Rendering; public static class IntegerExtension { public static int Max(this int value, int maxValue) => value <= maxValue ? value : maxValue; + public static int Min(this int value, int minValue) => value > minValue ? value : minValue; } \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 5456d84..03a9713 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -3,6 +3,7 @@ using TUI.Components.Controls; using TUI.Components.Layouts; using TUI.Engine.Nodes; using TUI.Engine.Nodes.Attributes.Alignments; +using TUI.Engine.Nodes.Attributes.Orientations; using TUI.Engine.Rendering; using TUI.Engine.Theme; @@ -21,6 +22,8 @@ public class DependenciesPage var nodeCraftsman = new NodeCraftsman(componentCraftsman, containerCraftsman); var header = new HeaderContainer(); + header.SetFixed(Orientation.Vertical, 6); + var copyright = new Copyright(); copyright.SetPaddingRight(Level.Normal); copyright.SetAlignment(Horizontal.Right); diff --git a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs index e5a2bfc..b8c969b 100644 --- a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs +++ b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs @@ -112,8 +112,7 @@ public class NodeCraftsmanTests [Theory] [InlineData(Orientation.Horizontal, 9, 1)] - [InlineData(Orientation.Vertical, 5, 1)] - public void DrawWithOverload(Orientation orientation, int rootWidth, int rootHeight) + public void DrawWithOverloadHorizontal(Orientation orientation, int rootWidth, int rootHeight) { var canvas = Mock.Of(w => w.Width == rootWidth && w.Height == rootHeight); var nodes = new Nodes { _component, _component }; @@ -124,7 +123,30 @@ public class NodeCraftsmanTests containerCraftsman.Draw(root, Position.Default, canvas.GetSize()); Mock.Get(canvas).Verify(w => w.SetPencil(0, 0), Times.Once()); - Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Once()); + Mock.Get(canvas).Verify(w => w.SetPencil(4, 0), Times.Once()); + Mock.Get(canvas).Verify(w => w.Paint("Lore"), Times.Exactly(2)); + } + + + [Theory] + [InlineData(4, 4, new[] { 0, 1, 2, 3 })] + public void DrawWithOverloadVertical(int rootWidth, int rootHeight, int[] expectedTopPositions) + { + var canvas = Mock.Of(w => w.Width == rootWidth && w.Height == rootHeight); + _component.SetContent("Lorem\nLorem\nLorem"); + var nodes = new Nodes { _component, _component }; + var root = Mock.Of(r => r.GetNodes() == nodes && r.Orientation == Orientation.Vertical); + + var componentCraftsman = new ComponentCraftsman(canvas); + var containerCraftsman = new ContainerCraftsman(componentCraftsman); + containerCraftsman.Draw(root, Position.Default, canvas.GetSize()); + + foreach (var expectedTopPosition in expectedTopPositions) + { + Mock.Get(canvas).Verify(w => w.SetPencil(0, expectedTopPosition), Times.Once()); + } + + Mock.Get(canvas).Verify(w => w.Paint("Lorem"), Times.Exactly(rootHeight)); } [Fact] @@ -196,7 +218,6 @@ public class NodeCraftsmanTests [Theory] [InlineData(Resizing.Fixed, 6)] - [InlineData(Resizing.Fixed, 3)] [InlineData(Resizing.Adaptive, 10)] public void DrawResizingContainer(Resizing resizing, int expectedCursorPosition) { From 634beddf77079b36a93fcd1fa321fefa71f5fe44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sat, 16 Mar 2024 00:13:09 +0500 Subject: [PATCH 10/23] =?UTF-8?q?=F0=9F=A7=AA=20Refactoring=20tests.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TLD.sln | 8 +- src/Dashboard/Dashboard.csproj | 10 - src/Dashboard/Program.cs | 9 - .../Attributes/Alignments/Alignment.cs | 2 +- .../Attributes/Alignments/Horizontal.cs | 2 +- .../Attributes/Alignments/IWithAlignment.cs | 10 + .../Attributes/Alignments/Vertical.cs | 2 +- .../Orientations/IWithOrientation.cs | 9 + .../Attributes/Orientations/Orientation.cs | 2 +- .../Attributes/Paddings/IWithPadding.cs} | 4 +- .../Attributes/Paddings/Padding.cs | 2 +- .../Attributes/Resizings/IResizable.cs | 16 ++ .../Attributes/Resizings/Resizing.cs | 7 + .../Resizings/ResizingExtensions.cs | 58 +++++ .../Nodes => TUI.Engine}/Attributes/Size.cs | 4 +- .../Components/ComponentAttribute.cs | 50 ++++ .../Components/ComponentExtensions.cs | 40 +++ src/TUI.Engine/Components/IComponent.cs | 10 + .../Nodes => TUI.Engine}/Components/Sketch.cs | 4 +- .../Components/StaticComponentAttribute.cs} | 8 +- src/TUI.Engine/Containers/ContainerBase.cs | 24 ++ .../Containers/ContainerExtensions.cs | 22 ++ src/TUI.Engine/Containers/IContainer.cs | 9 + src/{TUI => TUI.Engine}/Extensions.cs | 13 +- src/{TUI/Engine => TUI.Engine}/Helper.cs | 5 +- src/{TUI/Engine => TUI.Engine}/Nodes/INode.cs | 2 +- .../Engine => TUI.Engine}/Nodes/NodeBase.cs | 18 +- src/TUI.Engine/Nodes/NodeExtensions.cs | 15 ++ src/{TUI/Engine => TUI.Engine}/Nodes/Nodes.cs | 0 .../Engine => TUI.Engine}/Nodes/Position.cs | 1 + .../Rendering/Canvas/ConsoleCanvas.cs | 35 +++ src/TUI.Engine/Rendering/Canvas/ICanvas.cs | 17 ++ .../Rendering/ComponentCraftsman.cs | 12 +- .../Rendering/ContainerCraftsman.cs | 12 +- .../Rendering/CraftsmanBase.cs | 2 +- .../Rendering/IDrawable.cs | 2 +- .../Rendering/NodeCraftsman.cs | 13 +- src/{TUI/Engine => TUI.Engine}/Symbols.cs | 0 src/TUI.Engine/TUI.Engine.csproj | 20 ++ src/TUI.Engine/Theme/Defaults.cs | 20 ++ .../Theme/Indentation.cs | 0 src/{TUI/Engine => TUI.Engine}/Theme/Level.cs | 0 .../Engine => TUI.Engine}/Theme/Palette.cs | 0 ...nentBase.cs => CellsComponentAttribute.cs} | 12 +- src/TUI/Components/Controls/Copyright.cs | 4 +- src/TUI/Components/Controls/Dashboard.cs | 10 +- .../Components/Controls/HeaderContainer.cs | 4 +- .../Controls/Statics/Hints/AppTypeHints.cs | 4 +- .../Controls/Statics/Hints/HotkeysHint.cs | 4 +- .../Controls/Statics/Hints/TagHints.cs | 4 +- .../Controls/Statics/Hints/VersionHints.cs | 4 +- src/TUI/Components/Controls/Statics/Logo.cs | 4 +- src/TUI/Components/Controls/Tag.cs | 15 +- src/TUI/Components/Layouts/DashboardLayout.cs | 18 +- src/TUI/Components/Views/DependenciesView.cs | 10 +- src/TUI/Domain/Package.cs | 1 + .../Nodes/Attributes/Alignments/IAlignable.cs | 10 - .../Orientations/IWithOrientation.cs | 6 - .../Nodes/Attributes/Resizing/IResizable.cs | 14 - .../Nodes/Attributes/Resizing/Resizing.cs | 7 - .../Engine/Nodes/Components/ComponentBase.cs | 63 ----- src/TUI/Engine/Nodes/Components/IComponent.cs | 9 - .../Engine/Nodes/Containers/ContainerBase.cs | 16 -- .../Nodes/Containers/ContainerExtension.cs | 116 --------- src/TUI/Engine/Nodes/Containers/IContainer.cs | 10 - src/TUI/Engine/Rendering/CanvasExtensions.cs | 8 - src/TUI/Engine/Rendering/ConsoleCanvas.cs | 13 - src/TUI/Engine/Rendering/ICanvas.cs | 9 - src/TUI/Engine/Rendering/IntegerExtension.cs | 7 - src/TUI/Pages/DependenciesPage.cs | 15 +- src/TUI/Store/DependenciesStore.cs | 1 + src/TUI/TUI.csproj | 4 + .../DrawTests/ComponentAttributeTests.cs} | 16 +- .../DrawTests/DrawResizingTests.cs | 55 ++++ tests/TUI.Engine.Tests/DrawTests/DrawTests.cs | 218 ++++++++++++++++ .../DrawTests/IntegerTests.cs | 26 ++ tests/TUI.Engine.Tests/MockExtensions.cs | 18 ++ tests/TUI.Engine.Tests/Stubs/Prepare.cs | 22 ++ .../Stubs}/TestComponent.cs | 8 +- tests/TUI.Engine.Tests/Stubs/TestContainer.cs | 20 ++ .../TUI.Engine.Tests.csproj} | 5 +- .../TUI.Tests => TUI.Engine.Tests}/Usings.cs | 0 .../WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs | 240 ------------------ tests/WIdgets/TUI.Tests/Controls/LogoTests.cs | 18 -- tests/WIdgets/TUI.Tests/IntegerTests.cs | 22 -- 85 files changed, 863 insertions(+), 706 deletions(-) delete mode 100644 src/Dashboard/Dashboard.csproj delete mode 100644 src/Dashboard/Program.cs rename src/{TUI/Engine/Nodes => TUI.Engine}/Attributes/Alignments/Alignment.cs (55%) rename src/{TUI/Engine/Nodes => TUI.Engine}/Attributes/Alignments/Horizontal.cs (58%) create mode 100644 src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs rename src/{TUI/Engine/Nodes => TUI.Engine}/Attributes/Alignments/Vertical.cs (52%) create mode 100644 src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs rename src/{TUI/Engine/Nodes => TUI.Engine}/Attributes/Orientations/Orientation.cs (51%) rename src/{TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs => TUI.Engine/Attributes/Paddings/IWithPadding.cs} (75%) rename src/{TUI/Engine/Nodes => TUI.Engine}/Attributes/Paddings/Padding.cs (85%) create mode 100644 src/TUI.Engine/Attributes/Resizings/IResizable.cs create mode 100644 src/TUI.Engine/Attributes/Resizings/Resizing.cs create mode 100644 src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs rename src/{TUI/Engine/Nodes => TUI.Engine}/Attributes/Size.cs (79%) create mode 100644 src/TUI.Engine/Components/ComponentAttribute.cs create mode 100644 src/TUI.Engine/Components/ComponentExtensions.cs create mode 100644 src/TUI.Engine/Components/IComponent.cs rename src/{TUI/Engine/Nodes => TUI.Engine}/Components/Sketch.cs (92%) rename src/{TUI/Engine/Nodes/Components/ComponentStaticBase.cs => TUI.Engine/Components/StaticComponentAttribute.cs} (70%) create mode 100644 src/TUI.Engine/Containers/ContainerBase.cs create mode 100644 src/TUI.Engine/Containers/ContainerExtensions.cs create mode 100644 src/TUI.Engine/Containers/IContainer.cs rename src/{TUI => TUI.Engine}/Extensions.cs (81%) rename src/{TUI/Engine => TUI.Engine}/Helper.cs (89%) rename src/{TUI/Engine => TUI.Engine}/Nodes/INode.cs (60%) rename src/{TUI/Engine => TUI.Engine}/Nodes/NodeBase.cs (70%) create mode 100644 src/TUI.Engine/Nodes/NodeExtensions.cs rename src/{TUI/Engine => TUI.Engine}/Nodes/Nodes.cs (100%) rename src/{TUI/Engine => TUI.Engine}/Nodes/Position.cs (98%) create mode 100644 src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs create mode 100644 src/TUI.Engine/Rendering/Canvas/ICanvas.cs rename src/{TUI/Engine => TUI.Engine}/Rendering/ComponentCraftsman.cs (64%) rename src/{TUI/Engine => TUI.Engine}/Rendering/ContainerCraftsman.cs (90%) rename src/{TUI/Engine => TUI.Engine}/Rendering/CraftsmanBase.cs (90%) rename src/{TUI/Engine => TUI.Engine}/Rendering/IDrawable.cs (82%) rename src/{TUI/Engine => TUI.Engine}/Rendering/NodeCraftsman.cs (77%) rename src/{TUI/Engine => TUI.Engine}/Symbols.cs (100%) create mode 100644 src/TUI.Engine/TUI.Engine.csproj create mode 100644 src/TUI.Engine/Theme/Defaults.cs rename src/{TUI/Engine => TUI.Engine}/Theme/Indentation.cs (100%) rename src/{TUI/Engine => TUI.Engine}/Theme/Level.cs (100%) rename src/{TUI/Engine => TUI.Engine}/Theme/Palette.cs (100%) rename src/TUI/Components/Controls/{CellsComponentBase.cs => CellsComponentAttribute.cs} (68%) delete mode 100644 src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs delete mode 100644 src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs delete mode 100644 src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs delete mode 100644 src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs delete mode 100644 src/TUI/Engine/Nodes/Components/ComponentBase.cs delete mode 100644 src/TUI/Engine/Nodes/Components/IComponent.cs delete mode 100644 src/TUI/Engine/Nodes/Containers/ContainerBase.cs delete mode 100644 src/TUI/Engine/Nodes/Containers/ContainerExtension.cs delete mode 100644 src/TUI/Engine/Nodes/Containers/IContainer.cs delete mode 100644 src/TUI/Engine/Rendering/CanvasExtensions.cs delete mode 100644 src/TUI/Engine/Rendering/ConsoleCanvas.cs delete mode 100644 src/TUI/Engine/Rendering/ICanvas.cs delete mode 100644 src/TUI/Engine/Rendering/IntegerExtension.cs rename tests/{WIdgets/TUI.Tests/ComponentBaseTests.cs => TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs} (82%) create mode 100644 tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs create mode 100644 tests/TUI.Engine.Tests/DrawTests/DrawTests.cs create mode 100644 tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs create mode 100644 tests/TUI.Engine.Tests/MockExtensions.cs create mode 100644 tests/TUI.Engine.Tests/Stubs/Prepare.cs rename tests/{WIdgets/TUI.Tests => TUI.Engine.Tests/Stubs}/TestComponent.cs (52%) create mode 100644 tests/TUI.Engine.Tests/Stubs/TestContainer.cs rename tests/{WIdgets/TUI.Tests/TUI.Tests.csproj => TUI.Engine.Tests/TUI.Engine.Tests.csproj} (86%) rename tests/{WIdgets/TUI.Tests => TUI.Engine.Tests}/Usings.cs (100%) delete mode 100644 tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs delete mode 100644 tests/WIdgets/TUI.Tests/Controls/LogoTests.cs delete mode 100644 tests/WIdgets/TUI.Tests/IntegerTests.cs diff --git a/TLD.sln b/TLD.sln index a779c60..be4f9f0 100644 --- a/TLD.sln +++ b/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 diff --git a/src/Dashboard/Dashboard.csproj b/src/Dashboard/Dashboard.csproj deleted file mode 100644 index 2b14c81..0000000 --- a/src/Dashboard/Dashboard.csproj +++ /dev/null @@ -1,10 +0,0 @@ - - - - Exe - net7.0 - enable - enable - - - diff --git a/src/Dashboard/Program.cs b/src/Dashboard/Program.cs deleted file mode 100644 index c462094..0000000 --- a/src/Dashboard/Program.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Dashboard; - -class Program -{ - static void Main(string[] args) - { - Console.WriteLine("Hello, World!"); - } -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs b/src/TUI.Engine/Attributes/Alignments/Alignment.cs similarity index 55% rename from src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs rename to src/TUI.Engine/Attributes/Alignments/Alignment.cs index 1ddb95c..ffa9430 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/Alignment.cs +++ b/src/TUI.Engine/Attributes/Alignments/Alignment.cs @@ -1,3 +1,3 @@ -namespace TUI.Engine.Nodes.Attributes.Alignments; +namespace TUI.Engine.Attributes.Alignments; public record Alignment(Horizontal Horizontal, Vertical Vertical); \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs b/src/TUI.Engine/Attributes/Alignments/Horizontal.cs similarity index 58% rename from src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs rename to src/TUI.Engine/Attributes/Alignments/Horizontal.cs index cbc839a..10e010d 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/Horizontal.cs +++ b/src/TUI.Engine/Attributes/Alignments/Horizontal.cs @@ -1,4 +1,4 @@ -namespace TUI.Engine.Nodes.Attributes.Alignments; +namespace TUI.Engine.Attributes.Alignments; public enum Horizontal { diff --git a/src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs b/src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs new file mode 100644 index 0000000..b8272e5 --- /dev/null +++ b/src/TUI.Engine/Attributes/Alignments/IWithAlignment.cs @@ -0,0 +1,10 @@ +namespace TUI.Engine.Attributes.Alignments; + +public interface IWithAlignment +{ + internal Alignment Alignment { get; } + + void SetAlignment(Vertical vertical); + + void SetAlignment(Horizontal horizontal); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs b/src/TUI.Engine/Attributes/Alignments/Vertical.cs similarity index 52% rename from src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs rename to src/TUI.Engine/Attributes/Alignments/Vertical.cs index f03c6fa..9c26c2d 100644 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/Vertical.cs +++ b/src/TUI.Engine/Attributes/Alignments/Vertical.cs @@ -1,4 +1,4 @@ -namespace TUI.Engine.Nodes.Attributes.Alignments; +namespace TUI.Engine.Attributes.Alignments; public enum Vertical { diff --git a/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs b/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs new file mode 100644 index 0000000..1d6f5e9 --- /dev/null +++ b/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs @@ -0,0 +1,9 @@ +namespace TUI.Engine.Attributes.Orientations; + +public interface IWithOrientation +{ + internal Orientation Orientation { get; } + + public void SetOrientationHorizontal(); + public void SetOrientationVertical(); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Orientations/Orientation.cs b/src/TUI.Engine/Attributes/Orientations/Orientation.cs similarity index 51% rename from src/TUI/Engine/Nodes/Attributes/Orientations/Orientation.cs rename to src/TUI.Engine/Attributes/Orientations/Orientation.cs index 16b8b41..66f3a1f 100644 --- a/src/TUI/Engine/Nodes/Attributes/Orientations/Orientation.cs +++ b/src/TUI.Engine/Attributes/Orientations/Orientation.cs @@ -1,4 +1,4 @@ -namespace TUI.Engine.Nodes.Attributes.Orientations; +namespace TUI.Engine.Attributes.Orientations; public enum Orientation { diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs b/src/TUI.Engine/Attributes/Paddings/IWithPadding.cs similarity index 75% rename from src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs rename to src/TUI.Engine/Attributes/Paddings/IWithPadding.cs index b100181..453ea7e 100644 --- a/src/TUI/Engine/Nodes/Attributes/Paddings/IPaddingable.cs +++ b/src/TUI.Engine/Attributes/Paddings/IWithPadding.cs @@ -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; } diff --git a/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs b/src/TUI.Engine/Attributes/Paddings/Padding.cs similarity index 85% rename from src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs rename to src/TUI.Engine/Attributes/Paddings/Padding.cs index 0efbea8..ac97f6e 100644 --- a/src/TUI/Engine/Nodes/Attributes/Paddings/Padding.cs +++ b/src/TUI.Engine/Attributes/Paddings/Padding.cs @@ -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, diff --git a/src/TUI.Engine/Attributes/Resizings/IResizable.cs b/src/TUI.Engine/Attributes/Resizings/IResizable.cs new file mode 100644 index 0000000..2e28b18 --- /dev/null +++ b/src/TUI.Engine/Attributes/Resizings/IResizable.cs @@ -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); +} \ No newline at end of file diff --git a/src/TUI.Engine/Attributes/Resizings/Resizing.cs b/src/TUI.Engine/Attributes/Resizings/Resizing.cs new file mode 100644 index 0000000..163ac95 --- /dev/null +++ b/src/TUI.Engine/Attributes/Resizings/Resizing.cs @@ -0,0 +1,7 @@ +namespace TUI.Engine.Attributes.Resizings; + +public enum Resizing +{ + Adaptive, + Fixed +} \ No newline at end of file diff --git a/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs b/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs new file mode 100644 index 0000000..e502342 --- /dev/null +++ b/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs @@ -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; + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Size.cs b/src/TUI.Engine/Attributes/Size.cs similarity index 79% rename from src/TUI/Engine/Nodes/Attributes/Size.cs rename to src/TUI.Engine/Attributes/Size.cs index 4848283..6f74084 100644 --- a/src/TUI/Engine/Nodes/Attributes/Size.cs +++ b/src/TUI.Engine/Attributes/Size.cs @@ -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) { diff --git a/src/TUI.Engine/Components/ComponentAttribute.cs b/src/TUI.Engine/Components/ComponentAttribute.cs new file mode 100644 index 0000000..949c8cc --- /dev/null +++ b/src/TUI.Engine/Components/ComponentAttribute.cs @@ -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 +} \ No newline at end of file diff --git a/src/TUI.Engine/Components/ComponentExtensions.cs b/src/TUI.Engine/Components/ComponentExtensions.cs new file mode 100644 index 0000000..6c5e4ca --- /dev/null +++ b/src/TUI.Engine/Components/ComponentExtensions.cs @@ -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 + }; +} \ No newline at end of file diff --git a/src/TUI.Engine/Components/IComponent.cs b/src/TUI.Engine/Components/IComponent.cs new file mode 100644 index 0000000..b990aca --- /dev/null +++ b/src/TUI.Engine/Components/IComponent.cs @@ -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(); +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/Sketch.cs b/src/TUI.Engine/Components/Sketch.cs similarity index 92% rename from src/TUI/Engine/Nodes/Components/Sketch.cs rename to src/TUI.Engine/Components/Sketch.cs index d2c02a5..6cd7da4 100644 --- a/src/TUI/Engine/Nodes/Components/Sketch.cs +++ b/src/TUI.Engine/Components/Sketch.cs @@ -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 { diff --git a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs b/src/TUI.Engine/Components/StaticComponentAttribute.cs similarity index 70% rename from src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs rename to src/TUI.Engine/Components/StaticComponentAttribute.cs index 15cc414..50c4b24 100644 --- a/src/TUI/Engine/Nodes/Components/ComponentStaticBase.cs +++ b/src/TUI.Engine/Components/StaticComponentAttribute.cs @@ -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; diff --git a/src/TUI.Engine/Containers/ContainerBase.cs b/src/TUI.Engine/Containers/ContainerBase.cs new file mode 100644 index 0000000..e2b5141 --- /dev/null +++ b/src/TUI.Engine/Containers/ContainerBase.cs @@ -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(); +} \ No newline at end of file diff --git a/src/TUI.Engine/Containers/ContainerExtensions.cs b/src/TUI.Engine/Containers/ContainerExtensions.cs new file mode 100644 index 0000000..3b6eb36 --- /dev/null +++ b/src/TUI.Engine/Containers/ContainerExtensions.cs @@ -0,0 +1,22 @@ +using TUI.Engine.Attributes.Resizings; +using TUI.Engine.Nodes; + +namespace TUI.Engine.Containers; + +internal static class ContainerExtensions +{ + internal static IEnumerable 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); + } +} \ No newline at end of file diff --git a/src/TUI.Engine/Containers/IContainer.cs b/src/TUI.Engine/Containers/IContainer.cs new file mode 100644 index 0000000..b195750 --- /dev/null +++ b/src/TUI.Engine/Containers/IContainer.cs @@ -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(); +} \ No newline at end of file diff --git a/src/TUI/Extensions.cs b/src/TUI.Engine/Extensions.cs similarity index 81% rename from src/TUI/Extensions.cs rename to src/TUI.Engine/Extensions.cs index 6da3e2f..b54b99b 100644 --- a/src/TUI/Extensions.cs +++ b/src/TUI.Engine/Extensions.cs @@ -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 array, string findValue) { return array.Any(item => item == findValue); diff --git a/src/TUI/Engine/Helper.cs b/src/TUI.Engine/Helper.cs similarity index 89% rename from src/TUI/Engine/Helper.cs rename to src/TUI.Engine/Helper.cs index 2217059..8a73f30 100644 --- a/src/TUI/Engine/Helper.cs +++ b/src/TUI.Engine/Helper.cs @@ -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; diff --git a/src/TUI/Engine/Nodes/INode.cs b/src/TUI.Engine/Nodes/INode.cs similarity index 60% rename from src/TUI/Engine/Nodes/INode.cs rename to src/TUI.Engine/Nodes/INode.cs index efbdfd7..6bdfb87 100644 --- a/src/TUI/Engine/Nodes/INode.cs +++ b/src/TUI.Engine/Nodes/INode.cs @@ -1,4 +1,4 @@ -using TUI.Engine.Nodes.Attributes.Resizing; +using TUI.Engine.Attributes.Resizings; namespace TUI.Engine.Nodes; diff --git a/src/TUI/Engine/Nodes/NodeBase.cs b/src/TUI.Engine/Nodes/NodeBase.cs similarity index 70% rename from src/TUI/Engine/Nodes/NodeBase.cs rename to src/TUI.Engine/Nodes/NodeBase.cs index ec121ef..bb28979 100644 --- a/src/TUI/Engine/Nodes/NodeBase.cs +++ b/src/TUI.Engine/Nodes/NodeBase.cs @@ -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) { diff --git a/src/TUI.Engine/Nodes/NodeExtensions.cs b/src/TUI.Engine/Nodes/NodeExtensions.cs new file mode 100644 index 0000000..efdb506 --- /dev/null +++ b/src/TUI.Engine/Nodes/NodeExtensions.cs @@ -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); + } +} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Nodes.cs b/src/TUI.Engine/Nodes/Nodes.cs similarity index 100% rename from src/TUI/Engine/Nodes/Nodes.cs rename to src/TUI.Engine/Nodes/Nodes.cs diff --git a/src/TUI/Engine/Nodes/Position.cs b/src/TUI.Engine/Nodes/Position.cs similarity index 98% rename from src/TUI/Engine/Nodes/Position.cs rename to src/TUI.Engine/Nodes/Position.cs index edaa9d8..bc566d2 100644 --- a/src/TUI/Engine/Nodes/Position.cs +++ b/src/TUI.Engine/Nodes/Position.cs @@ -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}]"; } \ No newline at end of file diff --git a/src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs b/src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs new file mode 100644 index 0000000..9313148 --- /dev/null +++ b/src/TUI.Engine/Rendering/Canvas/ConsoleCanvas.cs @@ -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); + } +} \ No newline at end of file diff --git a/src/TUI.Engine/Rendering/Canvas/ICanvas.cs b/src/TUI.Engine/Rendering/Canvas/ICanvas.cs new file mode 100644 index 0000000..efe3efe --- /dev/null +++ b/src/TUI.Engine/Rendering/Canvas/ICanvas.cs @@ -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); +} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ComponentCraftsman.cs b/src/TUI.Engine/Rendering/ComponentCraftsman.cs similarity index 64% rename from src/TUI/Engine/Rendering/ComponentCraftsman.cs rename to src/TUI.Engine/Rendering/ComponentCraftsman.cs index 27e293c..6d03a26 100644 --- a/src/TUI/Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI.Engine/Rendering/ComponentCraftsman.cs @@ -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 +internal sealed class ComponentCraftsman : CraftsmanBase, IDrawable { private readonly ICanvas _canvas; @@ -19,13 +19,13 @@ public sealed class ComponentCraftsman : CraftsmanBase, IDrawable 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 }; diff --git a/src/TUI/Engine/Rendering/ContainerCraftsman.cs b/src/TUI.Engine/Rendering/ContainerCraftsman.cs similarity index 90% rename from src/TUI/Engine/Rendering/ContainerCraftsman.cs rename to src/TUI.Engine/Rendering/ContainerCraftsman.cs index 7999ad0..22d139c 100644 --- a/src/TUI/Engine/Rendering/ContainerCraftsman.cs +++ b/src/TUI.Engine/Rendering/ContainerCraftsman.cs @@ -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 +internal sealed class ContainerCraftsman : CraftsmanBase, IDrawable { private readonly IDrawable _componentCraftsman; diff --git a/src/TUI/Engine/Rendering/CraftsmanBase.cs b/src/TUI.Engine/Rendering/CraftsmanBase.cs similarity index 90% rename from src/TUI/Engine/Rendering/CraftsmanBase.cs rename to src/TUI.Engine/Rendering/CraftsmanBase.cs index 6c50bf9..a411d86 100644 --- a/src/TUI/Engine/Rendering/CraftsmanBase.cs +++ b/src/TUI.Engine/Rendering/CraftsmanBase.cs @@ -1,6 +1,6 @@ using System.Diagnostics; +using TUI.Engine.Attributes; using TUI.Engine.Nodes; -using TUI.Engine.Nodes.Attributes; namespace TUI.Engine.Rendering; diff --git a/src/TUI/Engine/Rendering/IDrawable.cs b/src/TUI.Engine/Rendering/IDrawable.cs similarity index 82% rename from src/TUI/Engine/Rendering/IDrawable.cs rename to src/TUI.Engine/Rendering/IDrawable.cs index 05ae2bc..dcf7ff0 100644 --- a/src/TUI/Engine/Rendering/IDrawable.cs +++ b/src/TUI.Engine/Rendering/IDrawable.cs @@ -1,5 +1,5 @@ +using TUI.Engine.Attributes; using TUI.Engine.Nodes; -using TUI.Engine.Nodes.Attributes; namespace TUI.Engine.Rendering; diff --git a/src/TUI/Engine/Rendering/NodeCraftsman.cs b/src/TUI.Engine/Rendering/NodeCraftsman.cs similarity index 77% rename from src/TUI/Engine/Rendering/NodeCraftsman.cs rename to src/TUI.Engine/Rendering/NodeCraftsman.cs index ec62349..ccce935 100644 --- a/src/TUI/Engine/Rendering/NodeCraftsman.cs +++ b/src/TUI.Engine/Rendering/NodeCraftsman.cs @@ -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; -/// -/// 🍀 -/// -public sealed class NodeCraftsman : IDrawable +internal sealed class DrawCraftsman : IDrawable { private readonly IDrawable _componentCraftsman; private readonly IDrawable _containerCraftsman; - public NodeCraftsman( + public DrawCraftsman( IDrawable componentCraftsman, IDrawable containerCraftsman) { diff --git a/src/TUI/Engine/Symbols.cs b/src/TUI.Engine/Symbols.cs similarity index 100% rename from src/TUI/Engine/Symbols.cs rename to src/TUI.Engine/Symbols.cs diff --git a/src/TUI.Engine/TUI.Engine.csproj b/src/TUI.Engine/TUI.Engine.csproj new file mode 100644 index 0000000..270ccf7 --- /dev/null +++ b/src/TUI.Engine/TUI.Engine.csproj @@ -0,0 +1,20 @@ + + + + net7.0 + enable + enable + + + + + + + <_Parameter1>$(MSBuildProjectName).Tests + + + <_Parameter1>Other.Assembly.Name + + + + diff --git a/src/TUI.Engine/Theme/Defaults.cs b/src/TUI.Engine/Theme/Defaults.cs new file mode 100644 index 0000000..b22e9d0 --- /dev/null +++ b/src/TUI.Engine/Theme/Defaults.cs @@ -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; +} \ No newline at end of file diff --git a/src/TUI/Engine/Theme/Indentation.cs b/src/TUI.Engine/Theme/Indentation.cs similarity index 100% rename from src/TUI/Engine/Theme/Indentation.cs rename to src/TUI.Engine/Theme/Indentation.cs diff --git a/src/TUI/Engine/Theme/Level.cs b/src/TUI.Engine/Theme/Level.cs similarity index 100% rename from src/TUI/Engine/Theme/Level.cs rename to src/TUI.Engine/Theme/Level.cs diff --git a/src/TUI/Engine/Theme/Palette.cs b/src/TUI.Engine/Theme/Palette.cs similarity index 100% rename from src/TUI/Engine/Theme/Palette.cs rename to src/TUI.Engine/Theme/Palette.cs diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Components/Controls/CellsComponentAttribute.cs similarity index 68% rename from src/TUI/Components/Controls/CellsComponentBase.cs rename to src/TUI/Components/Controls/CellsComponentAttribute.cs index 86b26bc..de7f9b5 100644 --- a/src/TUI/Components/Controls/CellsComponentBase.cs +++ b/src/TUI/Components/Controls/CellsComponentAttribute.cs @@ -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 _cells; - public CellsComponentBase(IEnumerable cells) + public CellsComponentAttribute(IEnumerable 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(); } diff --git a/src/TUI/Components/Controls/Copyright.cs b/src/TUI/Components/Controls/Copyright.cs index 0cd2d2a..c7d6e1b 100644 --- a/src/TUI/Components/Controls/Copyright.cs +++ b/src/TUI/Components/Controls/Copyright.cs @@ -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) { diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs index 46f0dcf..b5eae7b 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -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(); } diff --git a/src/TUI/Components/Controls/HeaderContainer.cs b/src/TUI/Components/Controls/HeaderContainer.cs index 0a01794..cb8ceee 100644 --- a/src/TUI/Components/Controls/HeaderContainer.cs +++ b/src/TUI/Components/Controls/HeaderContainer.cs @@ -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; diff --git a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs b/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs index 31520d0..381defc 100644 --- a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs +++ b/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs @@ -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 _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs b/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs index 630177e..1d780b5 100644 --- a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs +++ b/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs @@ -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 _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs b/src/TUI/Components/Controls/Statics/Hints/TagHints.cs index 54cb140..75680b7 100644 --- a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs +++ b/src/TUI/Components/Controls/Statics/Hints/TagHints.cs @@ -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 _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs b/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs index fa5f3fd..4237e18 100644 --- a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs +++ b/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs @@ -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 _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Logo.cs b/src/TUI/Components/Controls/Statics/Logo.cs index 41c54b8..f63944e 100644 --- a/src/TUI/Components/Controls/Statics/Logo.cs +++ b/src/TUI/Components/Controls/Statics/Logo.cs @@ -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) { diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Components/Controls/Tag.cs index e7eca6e..8c8d443 100644 --- a/src/TUI/Components/Controls/Tag.cs +++ b/src/TUI/Components/Controls/Tag.cs @@ -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 _tags; private string _gitType; - public Tag(NodeCraftsman drawEngine) - { - } - public void Bind(IEnumerable 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(); } diff --git a/src/TUI/Components/Layouts/DashboardLayout.cs b/src/TUI/Components/Layouts/DashboardLayout.cs index b4fe8fc..0b1ff26 100644 --- a/src/TUI/Components/Layouts/DashboardLayout.cs +++ b/src/TUI/Components/Layouts/DashboardLayout.cs @@ -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; } \ No newline at end of file diff --git a/src/TUI/Components/Views/DependenciesView.cs b/src/TUI/Components/Views/DependenciesView.cs index 88c02b1..5ef6bdd 100644 --- a/src/TUI/Components/Views/DependenciesView.cs +++ b/src/TUI/Components/Views/DependenciesView.cs @@ -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(); } diff --git a/src/TUI/Domain/Package.cs b/src/TUI/Domain/Package.cs index c56d4a3..b9d5519 100644 --- a/src/TUI/Domain/Package.cs +++ b/src/TUI/Domain/Package.cs @@ -1,5 +1,6 @@ using System.Text.Json.Nodes; using System.Text.Json.Serialization; +using TUI.Engine; namespace TUI.Domain; diff --git a/src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs b/src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs deleted file mode 100644 index 875408b..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Alignments/IAlignable.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TUI.Engine.Nodes.Attributes.Alignments; - -public interface IAlignable -{ - Alignment Alignment { get; } - - void SetAlignment(Vertical vertical); - - void SetAlignment(Horizontal horizontal); -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs b/src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs deleted file mode 100644 index 2d5fda9..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Orientations/IWithOrientation.cs +++ /dev/null @@ -1,6 +0,0 @@ -namespace TUI.Engine.Nodes.Attributes.Orientations; - -public interface IWithOrientation -{ - public Orientation Orientation { get; } -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs b/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs deleted file mode 100644 index 2773ce8..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Resizing/IResizable.cs +++ /dev/null @@ -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(); -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs b/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs deleted file mode 100644 index a213eb1..0000000 --- a/src/TUI/Engine/Nodes/Attributes/Resizing/Resizing.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace TUI.Engine.Nodes.Attributes.Resizing; - -public enum Resizing -{ - Adaptive, - Fixed -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/ComponentBase.cs b/src/TUI/Engine/Nodes/Components/ComponentBase.cs deleted file mode 100644 index 862547e..0000000 --- a/src/TUI/Engine/Nodes/Components/ComponentBase.cs +++ /dev/null @@ -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 -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Components/IComponent.cs b/src/TUI/Engine/Nodes/Components/IComponent.cs deleted file mode 100644 index a1bf772..0000000 --- a/src/TUI/Engine/Nodes/Components/IComponent.cs +++ /dev/null @@ -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(); -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/ContainerBase.cs b/src/TUI/Engine/Nodes/Containers/ContainerBase.cs deleted file mode 100644 index 416a5e9..0000000 --- a/src/TUI/Engine/Nodes/Containers/ContainerBase.cs +++ /dev/null @@ -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(); -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs b/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs deleted file mode 100644 index 02e9b83..0000000 --- a/src/TUI/Engine/Nodes/Containers/ContainerExtension.cs +++ /dev/null @@ -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 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 - }; -} \ No newline at end of file diff --git a/src/TUI/Engine/Nodes/Containers/IContainer.cs b/src/TUI/Engine/Nodes/Containers/IContainer.cs deleted file mode 100644 index 85c2500..0000000 --- a/src/TUI/Engine/Nodes/Containers/IContainer.cs +++ /dev/null @@ -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(); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/CanvasExtensions.cs b/src/TUI/Engine/Rendering/CanvasExtensions.cs deleted file mode 100644 index 5dfe4cf..0000000 --- a/src/TUI/Engine/Rendering/CanvasExtensions.cs +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ConsoleCanvas.cs b/src/TUI/Engine/Rendering/ConsoleCanvas.cs deleted file mode 100644 index 18227c4..0000000 --- a/src/TUI/Engine/Rendering/ConsoleCanvas.cs +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/ICanvas.cs b/src/TUI/Engine/Rendering/ICanvas.cs deleted file mode 100644 index 88781c1..0000000 --- a/src/TUI/Engine/Rendering/ICanvas.cs +++ /dev/null @@ -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); -} \ No newline at end of file diff --git a/src/TUI/Engine/Rendering/IntegerExtension.cs b/src/TUI/Engine/Rendering/IntegerExtension.cs deleted file mode 100644 index b142d85..0000000 --- a/src/TUI/Engine/Rendering/IntegerExtension.cs +++ /dev/null @@ -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; -} \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 03a9713..ca97f42 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -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; diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index 141484f..82eb923 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,5 +1,6 @@ using System.Text.Json; using TUI.Domain; +using TUI.Engine; using TUI.Settings; namespace TUI.Store; diff --git a/src/TUI/TUI.csproj b/src/TUI/TUI.csproj index 8e11941..ee7b7f3 100644 --- a/src/TUI/TUI.csproj +++ b/src/TUI/TUI.csproj @@ -19,4 +19,8 @@ + + + + diff --git a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs b/tests/TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs similarity index 82% rename from tests/WIdgets/TUI.Tests/ComponentBaseTests.cs rename to tests/TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs index 0d657a5..06501fc 100644 --- a/tests/WIdgets/TUI.Tests/ComponentBaseTests.cs +++ b/tests/TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs @@ -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); diff --git a/tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs b/tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs new file mode 100644 index 0000000..fbe3438 --- /dev/null +++ b/tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs @@ -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(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)); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/DrawTests/DrawTests.cs b/tests/TUI.Engine.Tests/DrawTests/DrawTests.cs new file mode 100644 index 0000000..0ccd630 --- /dev/null +++ b/tests/TUI.Engine.Tests/DrawTests/DrawTests.cs @@ -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(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(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(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(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(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(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(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(w => w.Size == new Size(10, 1)); + var nodes = new Nodes.Nodes { _component, _component }; + var container = Mock.Of(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(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(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)); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs b/tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs new file mode 100644 index 0000000..f2f7608 --- /dev/null +++ b/tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs @@ -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); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/MockExtensions.cs b/tests/TUI.Engine.Tests/MockExtensions.cs new file mode 100644 index 0000000..3322533 --- /dev/null +++ b/tests/TUI.Engine.Tests/MockExtensions.cs @@ -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(this Mock 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(this Mock mock, Position position) where T : class, ICanvas + { + mock.Verify(w => w.SetPencil(position), Times.Exactly(1)); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/Stubs/Prepare.cs b/tests/TUI.Engine.Tests/Stubs/Prepare.cs new file mode 100644 index 0000000..428dff2 --- /dev/null +++ b/tests/TUI.Engine.Tests/Stubs/Prepare.cs @@ -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; + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/TestComponent.cs b/tests/TUI.Engine.Tests/Stubs/TestComponent.cs similarity index 52% rename from tests/WIdgets/TUI.Tests/TestComponent.cs rename to tests/TUI.Engine.Tests/Stubs/TestComponent.cs index d018319..1d4be6c 100644 --- a/tests/WIdgets/TUI.Tests/TestComponent.cs +++ b/tests/TUI.Engine.Tests/Stubs/TestComponent.cs @@ -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); } diff --git a/tests/TUI.Engine.Tests/Stubs/TestContainer.cs b/tests/TUI.Engine.Tests/Stubs/TestContainer.cs new file mode 100644 index 0000000..f34d65b --- /dev/null +++ b/tests/TUI.Engine.Tests/Stubs/TestContainer.cs @@ -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; + } +} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/TUI.Tests.csproj b/tests/TUI.Engine.Tests/TUI.Engine.Tests.csproj similarity index 86% rename from tests/WIdgets/TUI.Tests/TUI.Tests.csproj rename to tests/TUI.Engine.Tests/TUI.Engine.Tests.csproj index 5f8628f..ba7433b 100644 --- a/tests/WIdgets/TUI.Tests/TUI.Tests.csproj +++ b/tests/TUI.Engine.Tests/TUI.Engine.Tests.csproj @@ -7,7 +7,8 @@ false true - Widgets.Tests + TUI.Engine.Tests + TUI.Engine.Tests @@ -26,7 +27,7 @@ - + diff --git a/tests/WIdgets/TUI.Tests/Usings.cs b/tests/TUI.Engine.Tests/Usings.cs similarity index 100% rename from tests/WIdgets/TUI.Tests/Usings.cs rename to tests/TUI.Engine.Tests/Usings.cs diff --git a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs b/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs deleted file mode 100644 index b8c969b..0000000 --- a/tests/WIdgets/TUI.Tests/ConsoleDrawNodeTests.cs +++ /dev/null @@ -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(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(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(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(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(w => w.Width == rootWidth && w.Height == rootHeight); - var nodes = new Nodes { _component, _component }; - var root = Mock.Of(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(w => w.Width == rootWidth && w.Height == rootHeight); - _component.SetContent("Lorem\nLorem\nLorem"); - var nodes = new Nodes { _component, _component }; - var root = Mock.Of(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(w => w.Height == 2 && w.Width == 10); - var nodes = new Nodes { _component, _component }; - var root = Mock.Of(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(w => w.Width == 10 && w.Height == 1); - var nodes = new Nodes { _component, _component }; - var container = Mock.Of(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(w => w.Width == 24 && w.Height == 1); - var nodes = new Nodes { _component, _component, _component, _component }; - var root = Mock.Of(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(w => w.Width == 10 && w.Height == 2); - var container = Mock.Of(c => c.GetNodes() == new Nodes { _component }); - var nodes = new Nodes { container, _component }; - var root = Mock.Of(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(w => w.Width == 20 && w.Height == 2); - var container = - Mock.Of(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(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)); - } -} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs b/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs deleted file mode 100644 index 9455f0f..0000000 --- a/tests/WIdgets/TUI.Tests/Controls/LogoTests.cs +++ /dev/null @@ -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); - } -} \ No newline at end of file diff --git a/tests/WIdgets/TUI.Tests/IntegerTests.cs b/tests/WIdgets/TUI.Tests/IntegerTests.cs deleted file mode 100644 index 71e9e7e..0000000 --- a/tests/WIdgets/TUI.Tests/IntegerTests.cs +++ /dev/null @@ -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); - } -} \ No newline at end of file From 91555925b6c1c8553d86d04fc9d2e63ba7d3d15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sun, 17 Mar 2024 00:39:58 +0500 Subject: [PATCH 11/23] =?UTF-8?q?=E2=9C=85=20Refactoring=20test=20director?= =?UTF-8?q?ies.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Orientations/IWithOrientation.cs | 1 + src/TUI.Engine/Helper.cs | 4 +- .../ComponentAttributeTests.cs | 7 +- .../Draw/ComponentBaseTests.cs | 18 ++ .../Draw/DrawAlignmentTests.cs | 89 +++++++ .../Draw/DrawOverloadTests.cs | 46 ++++ .../{DrawTests => Draw}/DrawResizingTests.cs | 17 +- tests/TUI.Engine.Tests/Draw/DrawTests.cs | 87 +++++++ tests/TUI.Engine.Tests/DrawTests/DrawTests.cs | 218 ------------------ .../{DrawTests => Primitives}/IntegerTests.cs | 4 +- tests/TUI.Engine.Tests/Stubs/TestContainer.cs | 2 +- 11 files changed, 260 insertions(+), 233 deletions(-) rename tests/TUI.Engine.Tests/{DrawTests => Components}/ComponentAttributeTests.cs (88%) create mode 100644 tests/TUI.Engine.Tests/Draw/ComponentBaseTests.cs create mode 100644 tests/TUI.Engine.Tests/Draw/DrawAlignmentTests.cs create mode 100644 tests/TUI.Engine.Tests/Draw/DrawOverloadTests.cs rename tests/TUI.Engine.Tests/{DrawTests => Draw}/DrawResizingTests.cs (77%) create mode 100644 tests/TUI.Engine.Tests/Draw/DrawTests.cs delete mode 100644 tests/TUI.Engine.Tests/DrawTests/DrawTests.cs rename tests/TUI.Engine.Tests/{DrawTests => Primitives}/IntegerTests.cs (82%) diff --git a/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs b/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs index 1d6f5e9..6b379f3 100644 --- a/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs +++ b/src/TUI.Engine/Attributes/Orientations/IWithOrientation.cs @@ -5,5 +5,6 @@ public interface IWithOrientation internal Orientation Orientation { get; } public void SetOrientationHorizontal(); + public void SetOrientationVertical(); } \ No newline at end of file diff --git a/src/TUI.Engine/Helper.cs b/src/TUI.Engine/Helper.cs index 8a73f30..b63adc9 100644 --- a/src/TUI.Engine/Helper.cs +++ b/src/TUI.Engine/Helper.cs @@ -3,7 +3,7 @@ using Pastel; using TUI.Engine.Attributes; using TUI.Engine.Nodes; -[assembly:InternalsVisibleTo("TUI.Engine.Tests", AllInternalsVisible = true)] +[assembly: InternalsVisibleTo("TUI.Engine.Tests", AllInternalsVisible = true)] namespace TUI.Engine; @@ -25,7 +25,7 @@ public static class Helper public static void ShowBackground(Position position, Size size) { - // return; + return; if (!Colors.Any()) { Init(); diff --git a/tests/TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs b/tests/TUI.Engine.Tests/Components/ComponentAttributeTests.cs similarity index 88% rename from tests/TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs rename to tests/TUI.Engine.Tests/Components/ComponentAttributeTests.cs index 06501fc..33797d0 100644 --- a/tests/TUI.Engine.Tests/DrawTests/ComponentAttributeTests.cs +++ b/tests/TUI.Engine.Tests/Components/ComponentAttributeTests.cs @@ -1,13 +1,15 @@ using FluentAssertions; using TUI.Engine.Attributes.Alignments; +using TUI.Engine.Components; using TUI.Engine.Tests.Stubs; using TUI.Engine.Theme; -namespace TUI.Engine.Tests.DrawTests; +namespace TUI.Engine.Tests.Components; public class ComponentAttributeTests { [Fact] + [Trait("Category", nameof(IComponent))] public void WhenUseChainingSaveAllChange() { var logo = new TestComponent(); @@ -24,6 +26,7 @@ public class ComponentAttributeTests } [Fact] + [Trait("Category", nameof(IComponent))] public void WhenSetPaddingsSaveAllChange() { var component = new TestComponent(); @@ -37,6 +40,7 @@ public class ComponentAttributeTests } [Theory] + [Trait("Category", nameof(IComponent))] [InlineData(Vertical.Bottom)] [InlineData(Vertical.Center)] [InlineData(Vertical.Top)] @@ -50,6 +54,7 @@ public class ComponentAttributeTests } [Theory] + [Trait("Category", nameof(IComponent))] [InlineData(Horizontal.Left)] [InlineData(Horizontal.Center)] [InlineData(Horizontal.Right)] diff --git a/tests/TUI.Engine.Tests/Draw/ComponentBaseTests.cs b/tests/TUI.Engine.Tests/Draw/ComponentBaseTests.cs new file mode 100644 index 0000000..7a5dd07 --- /dev/null +++ b/tests/TUI.Engine.Tests/Draw/ComponentBaseTests.cs @@ -0,0 +1,18 @@ +using TUI.Engine.Nodes; +using TUI.Engine.Rendering; +using TUI.Engine.Rendering.Canvas; +using TUI.Engine.Tests.Stubs; + +namespace TUI.Engine.Tests.Draw; + +public class ComponentBaseTests +{ + protected readonly TestComponent Component = Prepare.Component(); + + protected IDrawable Craftsman(ICanvas canvas) + { + var componentCraftsman = new ComponentCraftsman(canvas); + var containerCraftsman = new ContainerCraftsman(componentCraftsman); + return new DrawCraftsman(componentCraftsman, containerCraftsman); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/Draw/DrawAlignmentTests.cs b/tests/TUI.Engine.Tests/Draw/DrawAlignmentTests.cs new file mode 100644 index 0000000..32354c7 --- /dev/null +++ b/tests/TUI.Engine.Tests/Draw/DrawAlignmentTests.cs @@ -0,0 +1,89 @@ +using Moq; +using TUI.Engine.Attributes; +using TUI.Engine.Attributes.Alignments; +using TUI.Engine.Nodes; +using TUI.Engine.Rendering; +using TUI.Engine.Rendering.Canvas; + +namespace TUI.Engine.Tests.Draw; + +public class DrawAlignmentTests : ComponentBaseTests +{ + [Theory] + [Trait("Category", nameof(IDrawable.Draw))] + [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(w => w.Size == new Size(canvasSize, canvasSize)); + Component.SetContent(content); + Component.SetAlignment(Vertical.Top); + Component.SetAlignment(alignment); + + Craftsman(canvas).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] + [Trait("Category", nameof(IDrawable.Draw))] + [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(w => w.Size == new Size(canvasSize, canvasSize)); + Component.SetContent(content); + Component.SetAlignment(Horizontal.Left); + Component.SetAlignment(alignment); + + Craftsman(canvas).Draw(Component, Position.Default, canvas.Size); + + foreach (var expectedPencilPosition in expectedPositions) + { + Mock.Get(canvas).VerifyPositionOnce(0, expectedPencilPosition); + } + } + + [Theory] + [Trait("Category", nameof(IDrawable.Draw))] + [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(w => w.Size == new Size(6, 5)); + Component.SetContent("VV"); + Component.SetAlignment(horizontal); + Component.SetAlignment(vertical); + + Craftsman(canvas).Draw(Component, Position.Default, canvas.Size); + + Mock.Get(canvas).VerifyPositionOnce(expectedLeft, expectedTop); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/Draw/DrawOverloadTests.cs b/tests/TUI.Engine.Tests/Draw/DrawOverloadTests.cs new file mode 100644 index 0000000..6ea8d0f --- /dev/null +++ b/tests/TUI.Engine.Tests/Draw/DrawOverloadTests.cs @@ -0,0 +1,46 @@ +using Moq; +using TUI.Engine.Attributes; +using TUI.Engine.Nodes; +using TUI.Engine.Rendering; +using TUI.Engine.Rendering.Canvas; +using TUI.Engine.Tests.Stubs; + +namespace TUI.Engine.Tests.Draw; + +public class DrawOverloadTests : ComponentBaseTests +{ + [Fact] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawWithOverloadHorizontal() + { + var canvas = Mock.Of(w => w.Size == new Size(9, 1)); + var root = Prepare.Container(Component, Component); + root.SetOrientationHorizontal(); + + Craftsman(canvas).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 })] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawWithOverloadVertical(int rootWidth, int rootHeight, int[] expectedTopPositions) + { + var canvas = Mock.Of(w => w.Size == new Size(rootWidth, rootHeight)); + Component.SetContent("Lorem\nLorem\nLorem"); + var root = Prepare.Container(Component, Component); + root.SetOrientationVertical(); + + Craftsman(canvas).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)); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs b/tests/TUI.Engine.Tests/Draw/DrawResizingTests.cs similarity index 77% rename from tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs rename to tests/TUI.Engine.Tests/Draw/DrawResizingTests.cs index fbe3438..3505af5 100644 --- a/tests/TUI.Engine.Tests/DrawTests/DrawResizingTests.cs +++ b/tests/TUI.Engine.Tests/Draw/DrawResizingTests.cs @@ -6,35 +6,31 @@ using TUI.Engine.Rendering; using TUI.Engine.Rendering.Canvas; using TUI.Engine.Tests.Stubs; -namespace TUI.Engine.Tests.DrawTests; +namespace TUI.Engine.Tests.Draw; -public class DrawResizingTests +public class DrawResizingTests : ComponentBaseTests { - private readonly ICanvas _canvas; private readonly TestContainer _container; - private readonly ContainerCraftsman _craftsman; private readonly TestContainer _root; + private readonly ICanvas _canvas; public DrawResizingTests() { var component = Prepare.Component(); _canvas = Mock.Of(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] + [Trait("Category", nameof(IDrawable.Draw))] public void DrawResizingFixedContainer() { _container.SetFixed(Orientation.Horizontal, 6); _container.SetFixed(Orientation.Vertical, 2); - _craftsman.Draw(_root, Position.Default, _canvas.Size); + Craftsman(_canvas).Draw(_root, Position.Default, _canvas.Size); Mock.Get(_canvas).VerifyPositionOnce(Position.Default); Mock.Get(_canvas).VerifyPositionOnce(6, 0); @@ -42,11 +38,12 @@ public class DrawResizingTests } [Fact] + [Trait("Category", nameof(IDrawable.Draw))] public void DrawResizingAdaptiveContainer() { _container.SetAdaptive(Orientation.Horizontal); - _craftsman.Draw(_root, Position.Default, _canvas.Size); + Craftsman(_canvas).Draw(_root, Position.Default, _canvas.Size); Mock.Get(_canvas).VerifyPositionOnce(Position.Default); Mock.Get(_canvas).VerifyPositionOnce(10, 0); diff --git a/tests/TUI.Engine.Tests/Draw/DrawTests.cs b/tests/TUI.Engine.Tests/Draw/DrawTests.cs new file mode 100644 index 0000000..7734af2 --- /dev/null +++ b/tests/TUI.Engine.Tests/Draw/DrawTests.cs @@ -0,0 +1,87 @@ +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.Draw; + +public class DrawCraftsmanTests : ComponentBaseTests +{ + [Fact] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawSimple() + { + var canvas = Mock.Of(w => w.Size == new Size(9, 1)); + + Craftsman(canvas).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()); + } + + [Fact] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawVerticalWithDoubleComponent() + { + var canvas = Mock.Of(w => w.Size == new Size(10, 2)); + var root = Prepare.Container(Component, Component); + root.SetOrientationVertical(); + + Craftsman(canvas).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] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawHorizontalWithDoubleComponent() + { + var canvas = Mock.Of(w => w.Size == new Size(10, 1)); + var container = Prepare.Container(Component, Component); + container.SetOrientationHorizontal(); + + Craftsman(canvas).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] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawWithMultipleComponent() + { + var canvas = Mock.Of(w => w.Size == new Size(24, 1)); + var root = Prepare.Container(Component, Component, Component, Component); + + Craftsman(canvas).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] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawWithContainerAndComponent() + { + var canvas = Mock.Of(w => w.Size == new Size(10, 2)); + var container = Prepare.Container(Component); + var root = Prepare.Container(container, Component); + root.SetAdaptive(Orientation.Vertical); + root.SetOrientationVertical(); + + Craftsman(canvas).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)); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/DrawTests/DrawTests.cs b/tests/TUI.Engine.Tests/DrawTests/DrawTests.cs deleted file mode 100644 index 0ccd630..0000000 --- a/tests/TUI.Engine.Tests/DrawTests/DrawTests.cs +++ /dev/null @@ -1,218 +0,0 @@ -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(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(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(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(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(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(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(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(w => w.Size == new Size(10, 1)); - var nodes = new Nodes.Nodes { _component, _component }; - var container = Mock.Of(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(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(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)); - } -} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs b/tests/TUI.Engine.Tests/Primitives/IntegerTests.cs similarity index 82% rename from tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs rename to tests/TUI.Engine.Tests/Primitives/IntegerTests.cs index f2f7608..ed6d113 100644 --- a/tests/TUI.Engine.Tests/DrawTests/IntegerTests.cs +++ b/tests/TUI.Engine.Tests/Primitives/IntegerTests.cs @@ -1,10 +1,11 @@ using FluentAssertions; -namespace TUI.Engine.Tests.DrawTests; +namespace TUI.Engine.Tests.Draw; public class IntegerTests { [Theory] + [Trait("Category", "Primitives")] [InlineData(5, 10, 5)] [InlineData(5, 5, 5)] [InlineData(5, 3, 3)] @@ -15,6 +16,7 @@ public class IntegerTests } [Theory] + [Trait("Category", "Primitives")] [InlineData(5, 10, 10)] [InlineData(5, 5, 5)] [InlineData(5, 3, 5)] diff --git a/tests/TUI.Engine.Tests/Stubs/TestContainer.cs b/tests/TUI.Engine.Tests/Stubs/TestContainer.cs index f34d65b..07d8d20 100644 --- a/tests/TUI.Engine.Tests/Stubs/TestContainer.cs +++ b/tests/TUI.Engine.Tests/Stubs/TestContainer.cs @@ -5,7 +5,7 @@ namespace TUI.Engine.Tests.Stubs; public class TestContainer : ContainerBase { - private Nodes.Nodes _nodes = new(); + private readonly Nodes.Nodes _nodes = new(); public override Nodes.Nodes GetNodes() { From 0dd105679ed7dd601e5314d01304a8201cfa7067 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sun, 17 Mar 2024 01:31:13 +0500 Subject: [PATCH 12/23] =?UTF-8?q?=E2=9C=A8=20Add=20dashboard=20to=20deps?= =?UTF-8?q?=20page.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ComponentAttribute.cs => ComponentBase.cs} | 21 +++----- ...entAttribute.cs => StaticComponentBase.cs} | 2 +- src/TUI.Engine/Helper.cs | 2 +- ...nentAttribute.cs => CellsComponentBase.cs} | 4 +- src/TUI/Components/Controls/Copyright.cs | 2 +- src/TUI/Components/Controls/Dashboard.cs | 54 +++++++++---------- .../Controls/Statics/Hints/AppTypeHints.cs | 2 +- .../Controls/Statics/Hints/HotkeysHint.cs | 2 +- .../Controls/Statics/Hints/TagHints.cs | 2 +- .../Controls/Statics/Hints/VersionHints.cs | 2 +- src/TUI/Components/Controls/Statics/Logo.cs | 2 +- src/TUI/Components/Controls/Tag.cs | 2 +- src/TUI/Components/Layouts/DashboardLayout.cs | 23 +++++--- src/TUI/Components/Views/DependenciesView.cs | 2 +- src/TUI/Pages/DependenciesPage.cs | 12 ++--- ...ttributeTests.cs => ComponentBaseTests.cs} | 2 +- tests/TUI.Engine.Tests/Stubs/TestComponent.cs | 2 +- 17 files changed, 71 insertions(+), 67 deletions(-) rename src/TUI.Engine/Components/{ComponentAttribute.cs => ComponentBase.cs} (77%) rename src/TUI.Engine/Components/{StaticComponentAttribute.cs => StaticComponentBase.cs} (86%) rename src/TUI/Components/Controls/{CellsComponentAttribute.cs => CellsComponentBase.cs} (84%) rename tests/TUI.Engine.Tests/Components/{ComponentAttributeTests.cs => ComponentBaseTests.cs} (98%) diff --git a/src/TUI.Engine/Components/ComponentAttribute.cs b/src/TUI.Engine/Components/ComponentBase.cs similarity index 77% rename from src/TUI.Engine/Components/ComponentAttribute.cs rename to src/TUI.Engine/Components/ComponentBase.cs index 949c8cc..4dedf09 100644 --- a/src/TUI.Engine/Components/ComponentAttribute.cs +++ b/src/TUI.Engine/Components/ComponentBase.cs @@ -5,7 +5,7 @@ using TUI.Engine.Theme; namespace TUI.Engine.Components; -public abstract class ComponentAttribute : NodeBase, IComponent +public abstract class ComponentBase : NodeBase, IComponent { protected abstract Sketch DrawComponent(); @@ -13,29 +13,22 @@ public abstract class ComponentAttribute : NodeBase, IComponent #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 }; - } + internal Alignment Alignment { get; private set; } = new(Defaults.HorizontalAlignment, Defaults.VerticalAlignment); - public void SetAlignment(Horizontal horizontal) - { - Alignment = Alignment with { Horizontal = horizontal }; - } + 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; + internal Padding Padding { get; private set; } = new(Defaults.Padding); + public void SetPadding(Level level) => Padding = new Padding(level); public void SetPaddingTop(Level level) => Padding = Padding with { Top = level }; diff --git a/src/TUI.Engine/Components/StaticComponentAttribute.cs b/src/TUI.Engine/Components/StaticComponentBase.cs similarity index 86% rename from src/TUI.Engine/Components/StaticComponentAttribute.cs rename to src/TUI.Engine/Components/StaticComponentBase.cs index 50c4b24..8b5285c 100644 --- a/src/TUI.Engine/Components/StaticComponentAttribute.cs +++ b/src/TUI.Engine/Components/StaticComponentBase.cs @@ -2,7 +2,7 @@ using System.Text; namespace TUI.Engine.Components; -public abstract class StaticComponentAttribute : ComponentAttribute +public abstract class StaticComponentBase : ComponentBase { private Sketch? _cache; diff --git a/src/TUI.Engine/Helper.cs b/src/TUI.Engine/Helper.cs index b63adc9..64e6f36 100644 --- a/src/TUI.Engine/Helper.cs +++ b/src/TUI.Engine/Helper.cs @@ -25,7 +25,7 @@ public static class Helper public static void ShowBackground(Position position, Size size) { - return; + // return; if (!Colors.Any()) { Init(); diff --git a/src/TUI/Components/Controls/CellsComponentAttribute.cs b/src/TUI/Components/Controls/CellsComponentBase.cs similarity index 84% rename from src/TUI/Components/Controls/CellsComponentAttribute.cs rename to src/TUI/Components/Controls/CellsComponentBase.cs index de7f9b5..b1c25b3 100644 --- a/src/TUI/Components/Controls/CellsComponentAttribute.cs +++ b/src/TUI/Components/Controls/CellsComponentBase.cs @@ -6,13 +6,13 @@ using TUI.Engine.Components; namespace TUI.Components.Controls; -public class CellsComponentAttribute : ComponentAttribute, IComponent +public class CellsComponentBase : ComponentBase, IComponent { private const int MaxCellWidth = 10; private readonly IEnumerable _cells; - public CellsComponentAttribute(IEnumerable cells) + public CellsComponentBase(IEnumerable cells) { _cells = cells; } diff --git a/src/TUI/Components/Controls/Copyright.cs b/src/TUI/Components/Controls/Copyright.cs index c7d6e1b..eaf419e 100644 --- a/src/TUI/Components/Controls/Copyright.cs +++ b/src/TUI/Components/Controls/Copyright.cs @@ -5,7 +5,7 @@ using TUI.Engine.Theme; namespace TUI.Components.Controls; -public class Copyright : StaticComponentAttribute +public class Copyright : StaticComponentBase { protected override void RenderWithCache(StringBuilder builder) { diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs index b5eae7b..c0ba041 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -7,7 +7,7 @@ using TUI.Engine.Theme; namespace TUI.Components.Controls; -public class Dashboard : ComponentAttribute, IComponent +public class Dashboard : ComponentBase, IComponent { private readonly string _title; @@ -16,53 +16,53 @@ public class Dashboard : ComponentAttribute, IComponent _title = title; } - public void Render(Horizontal horizontal, Size size) - { - var dashboardBuilder = new StringBuilder(); - - RenderTopLine(dashboardBuilder, size, _title); - RenderMiddleLine(dashboardBuilder, size); - RenderBottomLine(dashboardBuilder, size); - - // base.Render(dashboardBuilder, position, size); - } - - private static void RenderTopLine(StringBuilder dashboardBuilder, Size size, string title) + private static void RenderTopLine(StringBuilder builder, Size size, string title) { var halfWidth = (size.Width - title.GetWidth() - (int)Indentation.BorderWidth * 2 - (int)Indentation.Default * 2) / 2; - dashboardBuilder.Append(Symbols.Angles.LeftTop); - dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); - dashboardBuilder.AppendFormat("{0}{1}{0}", Symbols.Space.Repeat(Convert.ToInt32(Indentation.Default)), title); - dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); - dashboardBuilder.Append(Symbols.Angles.RightTop); + builder.Append(Symbols.Angles.LeftTop); + builder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); + builder.AppendFormat("{0}{1}{0}", Symbols.Space.Repeat(Convert.ToInt32(Indentation.Default)), title); + builder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); + builder.Append(Symbols.Angles.RightTop); + builder.Append(Symbols.LineBreak); } - private static void RenderMiddleLine(StringBuilder dashboardBuilder, Size size) + private static void RenderMiddleLine(StringBuilder builder, Size size) { var dashboardHeight = size.Height - (int)Indentation.BorderWidth * 2; while (dashboardHeight > 0) { var bodyWidth = size.Width - (int)Indentation.BorderWidth * 2; - dashboardBuilder.Append(Symbols.Lines.Vertical); - dashboardBuilder.Append(Symbols.Space.Repeat(bodyWidth)); - dashboardBuilder.Append(Symbols.Lines.Vertical); + builder.Append(Symbols.Lines.Vertical); + builder.Append(Symbols.Space.Repeat(bodyWidth)); + builder.Append(Symbols.Lines.Vertical); + builder.Append(Symbols.LineBreak); dashboardHeight--; } } - private static void RenderBottomLine(StringBuilder dashboardBuilder, Size size) + private static void RenderBottomLine(StringBuilder builder, Size size) { var width = size.Width - (int)Indentation.BorderWidth * 2; - dashboardBuilder.Append(Symbols.Angles.LeftBottom); - dashboardBuilder.Append(Symbols.Lines.Horizontal.Repeat(width)); - dashboardBuilder.Append(Symbols.Angles.RightBottom); + builder.Append(Symbols.Angles.LeftBottom); + builder.Append(Symbols.Lines.Horizontal.Repeat(width)); + builder.Append(Symbols.Angles.RightBottom); + builder.Append(Symbols.LineBreak); } protected override Sketch DrawComponent() { - throw new NotImplementedException(); + var builder = new StringBuilder(); + + var size = new Size(40, 5); + + RenderTopLine(builder, size, _title); + RenderMiddleLine(builder, size); + RenderBottomLine(builder, size); + + return new Sketch(builder.ToString()); } } \ No newline at end of file diff --git a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs b/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs index 381defc..2f7d959 100644 --- a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs +++ b/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs @@ -6,7 +6,7 @@ using TUI.UserInterface; namespace TUI.Components.Controls.Statics.Hints; -public class AppTypeHints : StaticComponentAttribute +public class AppTypeHints : StaticComponentBase { private readonly Dictionary _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs b/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs index 1d780b5..12c80ba 100644 --- a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs +++ b/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs @@ -5,7 +5,7 @@ using TUI.Engine.Theme; namespace TUI.Components.Controls.Statics.Hints; -public class HotkeysHint : StaticComponentAttribute +public class HotkeysHint : StaticComponentBase { private readonly Dictionary _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs b/src/TUI/Components/Controls/Statics/Hints/TagHints.cs index 75680b7..766f52f 100644 --- a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs +++ b/src/TUI/Components/Controls/Statics/Hints/TagHints.cs @@ -6,7 +6,7 @@ using TUI.UserInterface; namespace TUI.Components.Controls.Statics.Hints; -public class TagHints : StaticComponentAttribute +public class TagHints : StaticComponentBase { private readonly Dictionary _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs b/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs index 4237e18..ee49809 100644 --- a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs +++ b/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs @@ -5,7 +5,7 @@ using TUI.Engine.Theme; namespace TUI.Components.Controls.Statics.Hints; -public class VersionHints : StaticComponentAttribute +public class VersionHints : StaticComponentBase { private readonly Dictionary _hints = new() { diff --git a/src/TUI/Components/Controls/Statics/Logo.cs b/src/TUI/Components/Controls/Statics/Logo.cs index f63944e..bed96db 100644 --- a/src/TUI/Components/Controls/Statics/Logo.cs +++ b/src/TUI/Components/Controls/Statics/Logo.cs @@ -5,7 +5,7 @@ using TUI.Engine.Theme; namespace TUI.Components.Controls.Statics; -public class Logo : StaticComponentAttribute +public class Logo : StaticComponentBase { protected override void RenderWithCache(StringBuilder builder) { diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Components/Controls/Tag.cs index 8c8d443..8afe3ce 100644 --- a/src/TUI/Components/Controls/Tag.cs +++ b/src/TUI/Components/Controls/Tag.cs @@ -8,7 +8,7 @@ using TUI.UserInterface; namespace TUI.Components.Controls; -public class Tag : ComponentAttribute +public class Tag : ComponentBase { private IEnumerable _tags; private string _gitType; diff --git a/src/TUI/Components/Layouts/DashboardLayout.cs b/src/TUI/Components/Layouts/DashboardLayout.cs index 0b1ff26..fefa559 100644 --- a/src/TUI/Components/Layouts/DashboardLayout.cs +++ b/src/TUI/Components/Layouts/DashboardLayout.cs @@ -1,7 +1,9 @@ +using TUI.Engine.Attributes.Alignments; using TUI.Engine.Attributes.Orientations; using TUI.Engine.Components; using TUI.Engine.Containers; using TUI.Engine.Nodes; +using TUI.Engine.Theme; namespace TUI.Components.Layouts; @@ -16,23 +18,32 @@ public class DashboardLayout : ContainerBase, IContainer private INode _header; private INode _footer; + private INode _dashboard; public override Nodes GetNodes() => new() { - _header, _footer + _header, _dashboard, _footer }; - public DashboardLayout AddHeader(IContainer header) + public void AddDashboard(IComponent dashboard) { - _header = header; - return this; + _dashboard = dashboard; } - public DashboardLayout AddFooter(IComponent footer) + public void AddHeader(IContainer header) { + header.SetFixed(Orientation.Vertical, 6); + _header = header; + } + + public void AddFooter(IComponent footer) + { + footer.SetFixed(Orientation.Vertical, 1); + footer.SetPaddingRight(Level.Normal); + footer.SetAlignment(Horizontal.Right); + footer.SetAlignment(Vertical.Bottom); _footer = footer; - return this; } public string Render() diff --git a/src/TUI/Components/Views/DependenciesView.cs b/src/TUI/Components/Views/DependenciesView.cs index 5ef6bdd..1e0e934 100644 --- a/src/TUI/Components/Views/DependenciesView.cs +++ b/src/TUI/Components/Views/DependenciesView.cs @@ -7,7 +7,7 @@ using TUI.Engine.Components; namespace TUI.Components.Views; -public class DependenciesView : ComponentAttribute, IComponent +public class DependenciesView : ComponentBase, IComponent { private const string ViewName = "Dependencies"; diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index ca97f42..6eb8c37 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -17,14 +17,14 @@ public class DependenciesPage ICanvas canvas = new ConsoleCanvas(); var header = new HeaderContainer(); - header.SetFixed(Orientation.Vertical, 6); - var copyright = new Copyright(); - copyright.SetPaddingRight(Level.Normal); - copyright.SetAlignment(Horizontal.Right); - copyright.SetAlignment(Vertical.Bottom); + var dashboard = new Dashboard("Dependencies"); + + var layout = new DashboardLayout(); + layout.AddHeader(header); + layout.AddFooter(copyright); + layout.AddDashboard(dashboard); - var layout = new DashboardLayout().AddHeader(header).AddFooter(copyright); // CommandLine = new CommandLine(); // DependenciesView = new DependenciesView(); diff --git a/tests/TUI.Engine.Tests/Components/ComponentAttributeTests.cs b/tests/TUI.Engine.Tests/Components/ComponentBaseTests.cs similarity index 98% rename from tests/TUI.Engine.Tests/Components/ComponentAttributeTests.cs rename to tests/TUI.Engine.Tests/Components/ComponentBaseTests.cs index 33797d0..5f2c32a 100644 --- a/tests/TUI.Engine.Tests/Components/ComponentAttributeTests.cs +++ b/tests/TUI.Engine.Tests/Components/ComponentBaseTests.cs @@ -6,7 +6,7 @@ using TUI.Engine.Theme; namespace TUI.Engine.Tests.Components; -public class ComponentAttributeTests +public class ComponentBaseTests { [Fact] [Trait("Category", nameof(IComponent))] diff --git a/tests/TUI.Engine.Tests/Stubs/TestComponent.cs b/tests/TUI.Engine.Tests/Stubs/TestComponent.cs index 1d4be6c..069f191 100644 --- a/tests/TUI.Engine.Tests/Stubs/TestComponent.cs +++ b/tests/TUI.Engine.Tests/Stubs/TestComponent.cs @@ -2,7 +2,7 @@ using TUI.Engine.Components; namespace TUI.Engine.Tests.Stubs; -public class TestComponent : ComponentAttribute +public class TestComponent : ComponentBase { private string _content = "Lorem"; From 268c25e604c3f6156334cfce0bf452f9917716b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Sun, 17 Mar 2024 09:30:21 +0500 Subject: [PATCH 13/23] =?UTF-8?q?=E2=9C=A8=20Add=20min=20size=20to=20compo?= =?UTF-8?q?nent.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI.Engine/Components/ComponentBase.cs | 5 +- src/TUI.Engine/Components/IComponent.cs | 3 +- .../Components/StaticComponentBase.cs | 3 +- src/TUI.Engine/Helper.cs | 2 +- .../Rendering/ComponentCraftsman.cs | 2 +- .../Components/Controls/CellsComponentBase.cs | 2 +- src/TUI/Components/Controls/Dashboard.cs | 13 +- src/TUI/Components/Controls/Tag.cs | 2 +- src/TUI/Components/Views/DependenciesView.cs | 160 ------------------ src/TUI/Domain/DevelopmentStack.cs | 3 - src/TUI/Pages/DependenciesPage.cs | 5 - tests/TUI.Engine.Tests/Stubs/TestComponent.cs | 3 +- 12 files changed, 18 insertions(+), 185 deletions(-) delete mode 100644 src/TUI/Components/Views/DependenciesView.cs delete mode 100644 src/TUI/Domain/DevelopmentStack.cs diff --git a/src/TUI.Engine/Components/ComponentBase.cs b/src/TUI.Engine/Components/ComponentBase.cs index 4dedf09..121a059 100644 --- a/src/TUI.Engine/Components/ComponentBase.cs +++ b/src/TUI.Engine/Components/ComponentBase.cs @@ -1,3 +1,4 @@ +using TUI.Engine.Attributes; using TUI.Engine.Attributes.Alignments; using TUI.Engine.Attributes.Paddings; using TUI.Engine.Nodes; @@ -7,9 +8,9 @@ namespace TUI.Engine.Components; public abstract class ComponentBase : NodeBase, IComponent { - protected abstract Sketch DrawComponent(); + protected abstract Sketch DrawComponent(Size minSize); - Sketch IComponent.MakeSketch() => DrawComponent(); + Sketch IComponent.MakeSketch(Size minSize) => DrawComponent(minSize); #region Alignments diff --git a/src/TUI.Engine/Components/IComponent.cs b/src/TUI.Engine/Components/IComponent.cs index b990aca..1beb97f 100644 --- a/src/TUI.Engine/Components/IComponent.cs +++ b/src/TUI.Engine/Components/IComponent.cs @@ -1,3 +1,4 @@ +using TUI.Engine.Attributes; using TUI.Engine.Attributes.Alignments; using TUI.Engine.Attributes.Paddings; using TUI.Engine.Nodes; @@ -6,5 +7,5 @@ namespace TUI.Engine.Components; public interface IComponent : INode, IWithAlignment, IWithPadding { - internal Sketch MakeSketch(); + internal Sketch MakeSketch(Size minSize); } \ No newline at end of file diff --git a/src/TUI.Engine/Components/StaticComponentBase.cs b/src/TUI.Engine/Components/StaticComponentBase.cs index 8b5285c..009d388 100644 --- a/src/TUI.Engine/Components/StaticComponentBase.cs +++ b/src/TUI.Engine/Components/StaticComponentBase.cs @@ -1,4 +1,5 @@ using System.Text; +using TUI.Engine.Attributes; namespace TUI.Engine.Components; @@ -8,7 +9,7 @@ public abstract class StaticComponentBase : ComponentBase protected abstract void RenderWithCache(StringBuilder builder); - protected override Sketch DrawComponent() + protected override Sketch DrawComponent(Size sketchMinSize) { if (_cache is not null) { diff --git a/src/TUI.Engine/Helper.cs b/src/TUI.Engine/Helper.cs index 64e6f36..b63adc9 100644 --- a/src/TUI.Engine/Helper.cs +++ b/src/TUI.Engine/Helper.cs @@ -25,7 +25,7 @@ public static class Helper public static void ShowBackground(Position position, Size size) { - // return; + return; if (!Colors.Any()) { Init(); diff --git a/src/TUI.Engine/Rendering/ComponentCraftsman.cs b/src/TUI.Engine/Rendering/ComponentCraftsman.cs index 6d03a26..70f4044 100644 --- a/src/TUI.Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI.Engine/Rendering/ComponentCraftsman.cs @@ -16,7 +16,7 @@ internal sealed class ComponentCraftsman : CraftsmanBase, IDrawable public Size Draw(IComponent component, Position pencil, Size maxSize) { - var sketch = component.MakeSketch(); + var sketch = component.MakeSketch(maxSize); var sketchSize = sketch.GetSize(); var correctedPencil = component.CorrectContentPosition(pencil, maxSize, sketchSize); diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Components/Controls/CellsComponentBase.cs index b1c25b3..c22e157 100644 --- a/src/TUI/Components/Controls/CellsComponentBase.cs +++ b/src/TUI/Components/Controls/CellsComponentBase.cs @@ -29,7 +29,7 @@ public class CellsComponentBase : ComponentBase, IComponent // base.Render(content, position, size); } - protected override Sketch DrawComponent() + protected override Sketch DrawComponent(Size minSize) { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Components/Controls/Dashboard.cs index c0ba041..7e1f75f 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Components/Controls/Dashboard.cs @@ -1,7 +1,6 @@ using System.Text; using TUI.Engine; using TUI.Engine.Attributes; -using TUI.Engine.Attributes.Alignments; using TUI.Engine.Components; using TUI.Engine.Theme; @@ -53,16 +52,14 @@ public class Dashboard : ComponentBase, IComponent builder.Append(Symbols.LineBreak); } - protected override Sketch DrawComponent() + protected override Sketch DrawComponent(Size minSize) { var builder = new StringBuilder(); - var size = new Size(40, 5); + RenderTopLine(builder, minSize, _title); + RenderMiddleLine(builder, minSize); + RenderBottomLine(builder, minSize); - RenderTopLine(builder, size, _title); - RenderMiddleLine(builder, size); - RenderBottomLine(builder, size); - - return new Sketch(builder.ToString()); + return new Sketch(builder.ToString().Main()); } } \ No newline at end of file diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Components/Controls/Tag.cs index 8afe3ce..45d76e7 100644 --- a/src/TUI/Components/Controls/Tag.cs +++ b/src/TUI/Components/Controls/Tag.cs @@ -54,7 +54,7 @@ public class Tag : ComponentBase _ => Symbols.Git }; - protected override Sketch DrawComponent() + protected override Sketch DrawComponent(Size minSize) { throw new NotImplementedException(); } diff --git a/src/TUI/Components/Views/DependenciesView.cs b/src/TUI/Components/Views/DependenciesView.cs deleted file mode 100644 index 1e0e934..0000000 --- a/src/TUI/Components/Views/DependenciesView.cs +++ /dev/null @@ -1,160 +0,0 @@ -using TUI.Components.Controls; -using TUI.Domain; -using TUI.Engine; -using TUI.Engine.Attributes; -using TUI.Engine.Attributes.Alignments; -using TUI.Engine.Components; - -namespace TUI.Components.Views; - -public class DependenciesView : ComponentBase, IComponent -{ - private const string ViewName = "Dependencies"; - - private DevelopmentStack _developmentStack; - - public void Bind(DevelopmentStack developmentStack) - { - _developmentStack = developmentStack; - } - - public void Render(Horizontal horizontal, Size size) - { - var dashboardTitle = _developmentStack.Icon + Symbols.Space + ViewName; - var dashboard = new Dashboard(dashboardTitle); - - // Add(dashboard); - } - - // private const int TitleWidth = 25; - // private const int ColumnWidth = 10; - - // private readonly DashboardControl _dashboard = new(); - - // public bool IsFocused - // { - // get => _dashboard.IsFocused; - // set => _dashboard.IsFocused = value; - // } - - // public void Render(ProjectDto projectDto, ControlPosition position) - // { - // _dashboard.Render(projectDto.Icon + " Dependencies", position); - // var header = projectDto.Dependencies.Select(GetConventionVersion).ToArray(); - // var rows = projectDto.Sources.Select(GetTitle).ToArray(); - // - // var tablePosition = new ControlPosition( - // position.Left + Theme.BorderWidth, - // position.Top + Theme.BorderWidth); - // - // var tableProps = new TableProps(header, rows, TitleWidth, ColumnWidth); - // _table.Render(tableProps, tablePosition); - // - // for (var rowId = 0; rowId < rows.Length; rowId++) - // { - // var actualDependencies = GetDependencies(projectDto.Sources[rowId], projectDto.Dependencies); - // _table.RenderRow(rowId + 1, rows[rowId] + actualDependencies); - // } - // } - - // private static string GetDependencies(SourceDto sourceDto, IEnumerable conventionDependencies) - // { - // try - // { - // var package = DownloadPackage(sourceDto); - // - // return string.Join("", - // conventionDependencies - // .Select(dependency => GetVersion(dependency, package)) - // .Select(RenderCurrentVersion)); - // } - // catch (HttpRequestException exception) - // { - // switch (exception.StatusCode) - // { - // case HttpStatusCode.BadRequest: - // return " Request have errors.".Pastel(Palette.ErrorColor); - // case HttpStatusCode.Forbidden: - // return " Not enough rights.".Pastel(Palette.ErrorColor); - // case HttpStatusCode.NotFound: - // return " Repository or branch master not found.".Pastel(Palette.ErrorColor); - // } - // - // throw; - // } - // catch (Exception exception) - // { - // Debugger.Break(); - // return "󰋔 We tried to send a request but couldn't. Check your configuration.".Pastel(Palette.ErrorColor); - // } - // } - // - // private static string GetVersion(DependencyDto dependency, Package package) - // { - // var currentVersion = package.ParseVersion(dependency.Name); - // - // if (currentVersion == null) return Icons.NotFound; - // - // var conventionVersion = dependency.Version?.ToVersion(); - // return PaintingVersion(currentVersion, conventionVersion); - // } - // - // private static string PaintingVersion(Version current, Version? convention) - // { - // var textVersion = current.ToString(); - // - // if (current > convention) return textVersion.Info(); - // - // if (current < convention) - // return current.Major == convention.Major ? textVersion.Primary() : textVersion.Warning(); - // - // return textVersion.Hint(); - // } - // - // private static string GetConventionVersion(DependencyDto dependencyDto) - // { - // return dependencyDto.Icon.Pastel(dependencyDto.Color) + dependencyDto.Version.Primary(); - // } - // - // private static string RenderCurrentVersion(string version) - // { - // var versionWidth = version.Width(); - // if (versionWidth == 0) return ' '.Repeat(ColumnWidth - 1) + Icons.NotFound.Hint(); - // - // return ' '.Repeat(ColumnWidth - versionWidth) + version; - // } - // - // private static string GetTitle(SourceDto sourceDto) - // { - // var title = ""; - // - // title += RenderPadding(); - // title += RenderTags(sourceDto); - // if (title.Width() + sourceDto.Name.Length + Theme.Padding <= TitleWidth) - // { - // title += sourceDto.Name; - // } - // else - // { - // var maxNameWidth = TitleWidth - title.Width() - Theme.Padding; - // title += $"{sourceDto.Name[..(maxNameWidth - 1)]}{"#".Hint()}"; - // } - // - // title += RenderPadding(); - // return $"{title}{' '.Repeat(TitleWidth - title.Width())}"; - // } - // - // public void Next() - // { - // _table.Next(); - // } - // - // public void Previous() - // { - // _table.Previous(); - // } - protected override Sketch DrawComponent() - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/src/TUI/Domain/DevelopmentStack.cs b/src/TUI/Domain/DevelopmentStack.cs deleted file mode 100644 index e24631b..0000000 --- a/src/TUI/Domain/DevelopmentStack.cs +++ /dev/null @@ -1,3 +0,0 @@ -namespace TUI.Domain; - -public record DevelopmentStack(string Name, char Icon); \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 6eb8c37..164d5e1 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -1,10 +1,7 @@ using System.Diagnostics; using TUI.Components.Controls; using TUI.Components.Layouts; -using TUI.Engine.Attributes.Alignments; -using TUI.Engine.Attributes.Orientations; using TUI.Engine.Rendering.Canvas; -using TUI.Engine.Theme; namespace TUI.Pages; @@ -19,12 +16,10 @@ public class DependenciesPage var header = new HeaderContainer(); var copyright = new Copyright(); var dashboard = new Dashboard("Dependencies"); - var layout = new DashboardLayout(); layout.AddHeader(header); layout.AddFooter(copyright); layout.AddDashboard(dashboard); - // CommandLine = new CommandLine(); // DependenciesView = new DependenciesView(); diff --git a/tests/TUI.Engine.Tests/Stubs/TestComponent.cs b/tests/TUI.Engine.Tests/Stubs/TestComponent.cs index 069f191..e574c1f 100644 --- a/tests/TUI.Engine.Tests/Stubs/TestComponent.cs +++ b/tests/TUI.Engine.Tests/Stubs/TestComponent.cs @@ -1,3 +1,4 @@ +using TUI.Engine.Attributes; using TUI.Engine.Components; namespace TUI.Engine.Tests.Stubs; @@ -11,7 +12,7 @@ public class TestComponent : ComponentBase _content = content; } - protected override Sketch DrawComponent() + protected override Sketch DrawComponent(Size minSize) { return new Sketch(_content); } From 99fe793c167c62e55de007d1d9ded9a03c992002 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Mon, 18 Mar 2024 00:57:31 +0500 Subject: [PATCH 14/23] =?UTF-8?q?=E2=9C=A8=20Version=20components=20create?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TLD.sln | 6 ++ .../Resizings/ResizingExtensions.cs | 6 +- src/TUI.Engine/Components/ComponentBase.cs | 12 ++++ src/TUI.Engine/Components/IComponent.cs | 6 ++ .../Containers/ContainerExtensions.cs | 24 +++++++- src/TUI.Engine/Extensions.cs | 5 +- .../Rendering/ContainerCraftsman.cs | 6 +- src/TUI.Engine/Symbols.cs | 57 +++++++++++++++---- src/TUI.Engine/TUI.Engine.csproj | 3 - src/TUI.Engine/Theme/Palette.cs | 6 ++ src/TUI/Controls/Common/StubComponent.cs | 33 +++++++++++ .../Components}/CellsComponentBase.cs | 2 +- .../Components/PanelComponent.cs} | 36 ++++++------ .../Controls => Controls/Components}/Tag.cs | 12 ++-- .../Controls/Components/VersionComponent.cs | 36 ++++++++++++ src/TUI/Controls/Components/VersionType.cs | 10 ++++ .../Components/VersionTypeExtensions.cs | 17 ++++++ .../Controls/Containers/ContentContainer.cs | 19 +++++++ .../Controls/Containers/DashboardContainer.cs | 31 ++++++++++ .../Containers/DependencyContainer.cs | 29 ++++++++++ .../Containers}/HeaderContainer.cs | 8 +-- .../Layouts/DashboardLayout.cs | 47 ++++++--------- .../Statics/CopyrightComponent.cs} | 8 +-- .../Controls/Statics/Hints/AppTypeHints.cs | 11 ++-- .../Controls/Statics/Hints/HotkeysHint.cs | 2 +- .../Controls/Statics/Hints/TagHints.cs | 11 ++-- .../Controls/Statics/Hints/VersionHints.cs | 11 ++-- .../Statics/LogoComponent.cs} | 4 +- src/TUI/Domain/NewFile1.txt | 2 +- src/TUI/Pages/DependenciesPage.cs | 19 ++++--- src/TUI/TUI.csproj | 10 +++- src/TUI/UserInterface/Icons.cs | 32 ++--------- .../TUI.Controls.Tests.csproj | 33 +++++++++++ tests/TUI.Controls.Tests/Usings.cs | 1 + .../VersionComponentTests.cs | 26 +++++++++ .../TUI.Engine.Tests/Draw/DrawStaticTests.cs | 38 +++++++++++++ tests/TUI.Engine.Tests/MockExtensions.cs | 4 ++ .../Primitives/IntegerTests.cs | 2 +- 38 files changed, 482 insertions(+), 143 deletions(-) create mode 100644 src/TUI/Controls/Common/StubComponent.cs rename src/TUI/{Components/Controls => Controls/Components}/CellsComponentBase.cs (95%) rename src/TUI/{Components/Controls/Dashboard.cs => Controls/Components/PanelComponent.cs} (57%) rename src/TUI/{Components/Controls => Controls/Components}/Tag.cs (77%) create mode 100644 src/TUI/Controls/Components/VersionComponent.cs create mode 100644 src/TUI/Controls/Components/VersionType.cs create mode 100644 src/TUI/Controls/Components/VersionTypeExtensions.cs create mode 100644 src/TUI/Controls/Containers/ContentContainer.cs create mode 100644 src/TUI/Controls/Containers/DashboardContainer.cs create mode 100644 src/TUI/Controls/Containers/DependencyContainer.cs rename src/TUI/{Components/Controls => Controls/Containers}/HeaderContainer.cs (88%) rename src/TUI/{Components => Controls}/Layouts/DashboardLayout.cs (66%) rename src/TUI/{Components/Controls/Copyright.cs => Controls/Statics/CopyrightComponent.cs} (62%) rename src/TUI/{Components => }/Controls/Statics/Hints/AppTypeHints.cs (69%) rename src/TUI/{Components => }/Controls/Statics/Hints/HotkeysHint.cs (92%) rename src/TUI/{Components => }/Controls/Statics/Hints/TagHints.cs (69%) rename src/TUI/{Components => }/Controls/Statics/Hints/VersionHints.cs (61%) rename src/TUI/{Components/Controls/Statics/Logo.cs => Controls/Statics/LogoComponent.cs} (92%) create mode 100644 tests/TUI.Controls.Tests/TUI.Controls.Tests.csproj create mode 100644 tests/TUI.Controls.Tests/Usings.cs create mode 100644 tests/TUI.Controls.Tests/VersionComponentTests.cs create mode 100644 tests/TUI.Engine.Tests/Draw/DrawStaticTests.cs diff --git a/TLD.sln b/TLD.sln index be4f9f0..aa4e2cc 100644 --- a/TLD.sln +++ b/TLD.sln @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Engine.Tests", "tests\T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Engine", "src\TUI.Engine\TUI.Engine.csproj", "{38E7E2DD-40C1-4B7C-9A7A-E3677AD55431}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TUI.Controls.Tests", "tests\TUI.Controls.Tests\TUI.Controls.Tests.csproj", "{59A0E843-8664-45B9-AD0C-52B8FE38986A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -28,5 +30,9 @@ Global {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 + {59A0E843-8664-45B9-AD0C-52B8FE38986A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59A0E843-8664-45B9-AD0C-52B8FE38986A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59A0E843-8664-45B9-AD0C-52B8FE38986A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59A0E843-8664-45B9-AD0C-52B8FE38986A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs b/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs index e502342..df50d2e 100644 --- a/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs +++ b/src/TUI.Engine/Attributes/Resizings/ResizingExtensions.cs @@ -18,13 +18,15 @@ internal static class ResizingExtensions } var fixedNodes = container.GetFixedNodes().ToArray(); + var absoluteNodes = container.GetAbsoluteNodes().ToArray(); var fixedHeight = fixedNodes.Sum(s => s.GetFixedSize().Height); var allowableHeight = maxHeight - fixedHeight; - var allowableCount = container.GetNodes().Count - fixedNodes.Length; + var allowableCount = container.GetNodes().Count - fixedNodes.Length - absoluteNodes.Length; var nodeHeight = (allowableHeight / allowableCount).Min(1); - var nodeNumber = nodeIndex + 1 - container.GetFixedNodes(nodeIndex).Sum(c => c.GetFixedSize().Height); + var nodeNumber = nodeIndex + 1 - container.GetFixedNodes(nodeIndex).Count() - + container.GetAbsoluteNodes(nodeIndex).Count(); if (allowableHeight - nodeNumber * nodeHeight < nodeHeight) { diff --git a/src/TUI.Engine/Components/ComponentBase.cs b/src/TUI.Engine/Components/ComponentBase.cs index 121a059..1b37294 100644 --- a/src/TUI.Engine/Components/ComponentBase.cs +++ b/src/TUI.Engine/Components/ComponentBase.cs @@ -10,6 +10,18 @@ public abstract class ComponentBase : NodeBase, IComponent { protected abstract Sketch DrawComponent(Size minSize); + public bool IsRelative { get; private set; } = true; + + public void SetRelative() + { + IsRelative = true; + } + + public void SetAbsolute() + { + IsRelative = false; + } + Sketch IComponent.MakeSketch(Size minSize) => DrawComponent(minSize); #region Alignments diff --git a/src/TUI.Engine/Components/IComponent.cs b/src/TUI.Engine/Components/IComponent.cs index 1beb97f..aa79ee7 100644 --- a/src/TUI.Engine/Components/IComponent.cs +++ b/src/TUI.Engine/Components/IComponent.cs @@ -7,5 +7,11 @@ namespace TUI.Engine.Components; public interface IComponent : INode, IWithAlignment, IWithPadding { + internal bool IsRelative { get; } + + public void SetRelative(); + + public void SetAbsolute(); + internal Sketch MakeSketch(Size minSize); } \ No newline at end of file diff --git a/src/TUI.Engine/Containers/ContainerExtensions.cs b/src/TUI.Engine/Containers/ContainerExtensions.cs index 3b6eb36..a53270d 100644 --- a/src/TUI.Engine/Containers/ContainerExtensions.cs +++ b/src/TUI.Engine/Containers/ContainerExtensions.cs @@ -1,10 +1,30 @@ using TUI.Engine.Attributes.Resizings; +using TUI.Engine.Components; using TUI.Engine.Nodes; namespace TUI.Engine.Containers; internal static class ContainerExtensions { + private static readonly Func AbsoluteNodes = node => node is IComponent { IsRelative: false }; + + private static readonly Func FixedNodes = node => node.ResizingVertical == Resizing.Fixed; + + internal static IEnumerable GetAbsoluteNodes(this IContainer container, int? takeNodeNumber = null) + { + if (takeNodeNumber is not null) + { + return container + .GetNodes() + .Take(takeNodeNumber.Value + 1) + .Where(AbsoluteNodes); + } + + return container + .GetNodes() + .Where(AbsoluteNodes); + } + internal static IEnumerable GetFixedNodes(this IContainer container, int? takeNodeNumber = null) { if (takeNodeNumber is not null) @@ -12,11 +32,11 @@ internal static class ContainerExtensions return container .GetNodes() .Take(takeNodeNumber.Value + 1) - .Where(n => n.ResizingVertical == Resizing.Fixed); + .Where(FixedNodes); } return container .GetNodes() - .Where(n => n.ResizingVertical == Resizing.Fixed); + .Where(FixedNodes); } } \ No newline at end of file diff --git a/src/TUI.Engine/Extensions.cs b/src/TUI.Engine/Extensions.cs index b54b99b..9ef3c11 100644 --- a/src/TUI.Engine/Extensions.cs +++ b/src/TUI.Engine/Extensions.cs @@ -1,4 +1,5 @@ using System.Globalization; +using System.Text; using System.Text.RegularExpressions; namespace TUI.Engine; @@ -20,9 +21,9 @@ public static class Extensions return array.Any(item => item == findValue); } - public static string Repeat(this char symbol, int repeatCount) + public static string Repeat(this string value, int count) { - return repeatCount < 0 ? string.Empty : new string(symbol, repeatCount); + return count < 0 ? string.Empty : new StringBuilder(value.Length * count).Insert(0, value, count).ToString(); } public static string RemoveColors(this string text) diff --git a/src/TUI.Engine/Rendering/ContainerCraftsman.cs b/src/TUI.Engine/Rendering/ContainerCraftsman.cs index 22d139c..74b4601 100644 --- a/src/TUI.Engine/Rendering/ContainerCraftsman.cs +++ b/src/TUI.Engine/Rendering/ContainerCraftsman.cs @@ -28,7 +28,7 @@ internal sealed class ContainerCraftsman : CraftsmanBase, IDrawable { var node = nodes[nodeNumber]; var nodeSize = node.GetSize(container, nodeNumber, maxSize); - + nextNodePosition = DrawNode(node, container, nextNodePosition, nodeSize); nodeNumber++; } @@ -45,7 +45,9 @@ internal sealed class ContainerCraftsman : CraftsmanBase, IDrawable return GetNextNodePosition(container, containerSize, nodePosition); case IComponent childComponent: var componentSize = _componentCraftsman.Draw(childComponent, nodePosition, maxSize); - return GetNextNodePosition(container, maxSize, nodePosition, componentSize); + return childComponent.IsRelative + ? GetNextNodePosition(container, maxSize, nodePosition, componentSize) + : nodePosition; default: throw new InvalidCastException(); } diff --git a/src/TUI.Engine/Symbols.cs b/src/TUI.Engine/Symbols.cs index ea35302..3857193 100644 --- a/src/TUI.Engine/Symbols.cs +++ b/src/TUI.Engine/Symbols.cs @@ -1,25 +1,58 @@ +using Pastel; +using TUI.Engine.Theme; + namespace TUI.Engine; public static class Symbols { - public const char Space = ' '; - public const char Copyright = '©'; - public const char GitLab = ''; - public const char GitHub = ''; - public const char Git = ''; - public const char LineBreak = '\n'; + public const string Space = " "; + public const string Copyright = "©"; + public const string GitLab = ""; + public const string GitHub = ""; + public const string Git = ""; + public const string LineBreak = "\n"; + public const string NetworkPublic = "󰞉"; + public const string NetworkPrivate = "󰕑"; + public const string Undefined = ""; + public const string Site = ""; + public const string Api = ""; + public const string DockerImage = ""; + public const string NpmPackage = ""; + public const string SEO = "󰚩"; + public const string Auth = ""; + public const string NotFound = ""; public static class Lines { - public const char Vertical = '│'; - public const char Horizontal = '─'; + public const string Vertical = "│"; + public const string Horizontal = "─"; } public static class Angles { - public const char RightTop = '┐'; - public const char LeftBottom = '└'; - public const char LeftTop = '┌'; - public const char RightBottom = '┘'; + public const string RightTop = "┐"; + public const string LeftBottom = "└"; + public const string LeftTop = "┌"; + public const string RightBottom = "┘"; } } + +public static class CharExtensions +{ + public static string Colorized(this string symbol) => + !SymbolColors.ContainsKey(symbol) ? symbol.Hint() : symbol.Pastel(SymbolColors[symbol]); + + private static readonly Dictionary SymbolColors = new() + { + { Symbols.Git, "F14E32" }, + { Symbols.Site, "BF40BF" }, + { Symbols.GitLab, "E24329" }, + { Symbols.GitHub, "ADBAC7" }, + { Symbols.NetworkPublic, "00FFFF" }, + { Symbols.Api, "7F52FF" }, + { Symbols.DockerImage, "086DD7" }, + { Symbols.NpmPackage, "CB0000" }, + { Symbols.SEO, "4285F4" }, + { Symbols.Auth, "FFD700" }, + }; +} \ No newline at end of file diff --git a/src/TUI.Engine/TUI.Engine.csproj b/src/TUI.Engine/TUI.Engine.csproj index 270ccf7..5e00211 100644 --- a/src/TUI.Engine/TUI.Engine.csproj +++ b/src/TUI.Engine/TUI.Engine.csproj @@ -12,9 +12,6 @@ <_Parameter1>$(MSBuildProjectName).Tests - - <_Parameter1>Other.Assembly.Name - diff --git a/src/TUI.Engine/Theme/Palette.cs b/src/TUI.Engine/Theme/Palette.cs index 4b700d0..5ab1765 100644 --- a/src/TUI.Engine/Theme/Palette.cs +++ b/src/TUI.Engine/Theme/Palette.cs @@ -18,6 +18,8 @@ public static class Palette public static string Hint(this string currentText) => currentText.Pastel(HintColor); + public static string Hint(this char currentText) => currentText.ToString().Pastel(HintColor); + public static string Disable(this string currentText) => currentText.RemoveColors().Pastel(HintColor); public static string Warning(this string currentText) => currentText.Pastel(WarningColor); @@ -25,4 +27,8 @@ public static class Palette public static string Error(this string currentText) => currentText.Pastel(ErrorColor); public static string Info(this string currentText) => currentText.Pastel(InfoColor); + + public static string Info(this char currentText) => currentText.ToString().Pastel(InfoColor); + + public static string Info(this int currentText) => currentText.ToString().Pastel(InfoColor); } \ No newline at end of file diff --git a/src/TUI/Controls/Common/StubComponent.cs b/src/TUI/Controls/Common/StubComponent.cs new file mode 100644 index 0000000..8a498ee --- /dev/null +++ b/src/TUI/Controls/Common/StubComponent.cs @@ -0,0 +1,33 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Attributes; +using TUI.Engine.Attributes.Orientations; +using TUI.Engine.Components; + +namespace TUI.Controls.Common; + +public class StubComponent : ComponentBase +{ + private readonly Size _size; + + public StubComponent(Size size) + { + _size = size; + SetFixed(Orientation.Horizontal, size.Width); + SetFixed(Orientation.Vertical, size.Height); + } + + protected override Sketch DrawComponent(Size minSize) + { + var builder = new StringBuilder(); + var height = 0; + + while (_size.Height > height) + { + builder.Append(Symbols.Space.Repeat(_size.Width)); + height++; + } + + return new Sketch(builder.ToString()); + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/CellsComponentBase.cs b/src/TUI/Controls/Components/CellsComponentBase.cs similarity index 95% rename from src/TUI/Components/Controls/CellsComponentBase.cs rename to src/TUI/Controls/Components/CellsComponentBase.cs index c22e157..a50685c 100644 --- a/src/TUI/Components/Controls/CellsComponentBase.cs +++ b/src/TUI/Controls/Components/CellsComponentBase.cs @@ -4,7 +4,7 @@ using TUI.Engine.Attributes; using TUI.Engine.Attributes.Alignments; using TUI.Engine.Components; -namespace TUI.Components.Controls; +namespace TUI.Controls.Components; public class CellsComponentBase : ComponentBase, IComponent { diff --git a/src/TUI/Components/Controls/Dashboard.cs b/src/TUI/Controls/Components/PanelComponent.cs similarity index 57% rename from src/TUI/Components/Controls/Dashboard.cs rename to src/TUI/Controls/Components/PanelComponent.cs index 7e1f75f..a3536b5 100644 --- a/src/TUI/Components/Controls/Dashboard.cs +++ b/src/TUI/Controls/Components/PanelComponent.cs @@ -3,28 +3,30 @@ using TUI.Engine; using TUI.Engine.Attributes; using TUI.Engine.Components; using TUI.Engine.Theme; +using static TUI.Engine.Symbols; -namespace TUI.Components.Controls; +namespace TUI.Controls.Components; -public class Dashboard : ComponentBase, IComponent +public class PanelComponent : ComponentBase, IComponent { private readonly string _title; - public Dashboard(string title) + public PanelComponent(string title) { _title = title; + SetAbsolute(); } private static void RenderTopLine(StringBuilder builder, Size size, string title) { var halfWidth = (size.Width - title.GetWidth() - (int)Indentation.BorderWidth * 2 - (int)Indentation.Default * 2) / 2; - builder.Append(Symbols.Angles.LeftTop); - builder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); - builder.AppendFormat("{0}{1}{0}", Symbols.Space.Repeat(Convert.ToInt32(Indentation.Default)), title); - builder.Append(Symbols.Lines.Horizontal.Repeat(halfWidth)); - builder.Append(Symbols.Angles.RightTop); - builder.Append(Symbols.LineBreak); + builder.Append(Angles.LeftTop); + builder.Append(Lines.Horizontal.Repeat(halfWidth)); + builder.AppendFormat("{0}{1}{0}", Space.Repeat(Convert.ToInt32(Indentation.Default)), title); + builder.Append(Lines.Horizontal.Repeat(halfWidth)); + builder.Append(Angles.RightTop); + builder.Append(LineBreak); } private static void RenderMiddleLine(StringBuilder builder, Size size) @@ -34,10 +36,10 @@ public class Dashboard : ComponentBase, IComponent while (dashboardHeight > 0) { var bodyWidth = size.Width - (int)Indentation.BorderWidth * 2; - builder.Append(Symbols.Lines.Vertical); - builder.Append(Symbols.Space.Repeat(bodyWidth)); - builder.Append(Symbols.Lines.Vertical); - builder.Append(Symbols.LineBreak); + builder.Append(Lines.Vertical); + builder.Append(Space.Repeat(bodyWidth)); + builder.Append(Lines.Vertical); + builder.Append(LineBreak); dashboardHeight--; } @@ -46,10 +48,10 @@ public class Dashboard : ComponentBase, IComponent private static void RenderBottomLine(StringBuilder builder, Size size) { var width = size.Width - (int)Indentation.BorderWidth * 2; - builder.Append(Symbols.Angles.LeftBottom); - builder.Append(Symbols.Lines.Horizontal.Repeat(width)); - builder.Append(Symbols.Angles.RightBottom); - builder.Append(Symbols.LineBreak); + builder.Append(Angles.LeftBottom); + builder.Append(Lines.Horizontal.Repeat(width)); + builder.Append(Angles.RightBottom); + builder.Append(LineBreak); } protected override Sketch DrawComponent(Size minSize) diff --git a/src/TUI/Components/Controls/Tag.cs b/src/TUI/Controls/Components/Tag.cs similarity index 77% rename from src/TUI/Components/Controls/Tag.cs rename to src/TUI/Controls/Components/Tag.cs index 45d76e7..392064c 100644 --- a/src/TUI/Components/Controls/Tag.cs +++ b/src/TUI/Controls/Components/Tag.cs @@ -6,7 +6,7 @@ using TUI.Engine.Components; using TUI.Engine.Theme; using TUI.UserInterface; -namespace TUI.Components.Controls; +namespace TUI.Controls.Components; public class Tag : ComponentBase { @@ -25,11 +25,11 @@ public class Tag : ComponentBase tagBuilder.Append(GetGitTypeImage(_gitType)); tagBuilder.Append(Symbols.Space); - tagBuilder.Append(_tags.Have("public") ? Icons.NetworkPublic : Icons.NetworkPrivate); + tagBuilder.Append(_tags.Have("public") ? Symbols.NetworkPublic : Symbols.NetworkPrivate); tagBuilder.Append(Symbols.Space); - tagBuilder.Append(_tags.Have("seo") ? Icons.SEO : Icons.SEO.Disable()); + tagBuilder.Append(_tags.Have("seo") ? Symbols.SEO : Symbols.SEO.Disable()); tagBuilder.Append(Symbols.Space); - tagBuilder.Append(_tags.Have("auth") ? Icons.Auth : Icons.Auth.Disable()); + tagBuilder.Append(_tags.Have("auth") ? Symbols.Auth : Symbols.Auth.Disable()); tagBuilder.Append(Symbols.Space); tagBuilder.Append(GetApplicationType()); tagBuilder.Append(Symbols.Space); @@ -43,10 +43,10 @@ public class Tag : ComponentBase if (_tags.Have(application.Value)) return application.Key; - return Icons.Undefined; + return Symbols.Undefined; } - private static char GetGitTypeImage(string gitType) => + private static string GetGitTypeImage(string gitType) => gitType switch { "gitlab" => Symbols.GitLab, diff --git a/src/TUI/Controls/Components/VersionComponent.cs b/src/TUI/Controls/Components/VersionComponent.cs new file mode 100644 index 0000000..86babe3 --- /dev/null +++ b/src/TUI/Controls/Components/VersionComponent.cs @@ -0,0 +1,36 @@ +using System.Text; +using TUI.Engine; +using TUI.Engine.Attributes; +using TUI.Engine.Components; + +namespace TUI.Controls.Components; + +public class VersionComponent : ComponentBase +{ + private readonly VersionType _type; + private readonly string _version; + private readonly string? _icon; + + public VersionComponent(VersionType type, string version, string? icon = null) + { + _type = type; + _version = version; + _icon = icon; + } + + protected override Sketch DrawComponent(Size minSize) + { + var builder = new StringBuilder(); + + if (_icon is not null) + { + builder.Append(_icon.Colorized()); + builder.Append(Symbols.Space); + } + + builder.Append(_version); + var sketch = builder.ToString(); + + return new Sketch(_type.Colorize(sketch)); + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionType.cs b/src/TUI/Controls/Components/VersionType.cs new file mode 100644 index 0000000..108dc0a --- /dev/null +++ b/src/TUI/Controls/Components/VersionType.cs @@ -0,0 +1,10 @@ +namespace TUI.Controls.Components; + +public enum VersionType +{ + Convention, + ToNew, + SoGood, + BeNice, + TooOld, +} \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionTypeExtensions.cs b/src/TUI/Controls/Components/VersionTypeExtensions.cs new file mode 100644 index 0000000..3178ca7 --- /dev/null +++ b/src/TUI/Controls/Components/VersionTypeExtensions.cs @@ -0,0 +1,17 @@ +using TUI.Engine.Theme; + +namespace TUI.Controls.Components; + +public static class VersionTypeExtensions +{ + public static string Colorize(this VersionType versionType, string value) => + versionType switch + { + VersionType.TooOld => value.Warning(), + VersionType.ToNew => value.Info(), + VersionType.SoGood => value.Hint(), + VersionType.BeNice => value.Main(), + VersionType.Convention => value.Main(), + _ => value + }; +} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/ContentContainer.cs b/src/TUI/Controls/Containers/ContentContainer.cs new file mode 100644 index 0000000..0eaa58a --- /dev/null +++ b/src/TUI/Controls/Containers/ContentContainer.cs @@ -0,0 +1,19 @@ +using TUI.Engine.Containers; +using TUI.Engine.Nodes; + +namespace TUI.Controls.Containers; + +public class ContentContainer : ContainerBase +{ + private readonly Nodes _children = new(); + + public void AddChildren(INode node) + { + _children.Add(node); + } + + public override Nodes GetNodes() + { + return _children; + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DashboardContainer.cs b/src/TUI/Controls/Containers/DashboardContainer.cs new file mode 100644 index 0000000..ac27e73 --- /dev/null +++ b/src/TUI/Controls/Containers/DashboardContainer.cs @@ -0,0 +1,31 @@ +using TUI.Controls.Components; +using TUI.Engine.Attributes.Orientations; +using TUI.Engine.Containers; +using TUI.Engine.Nodes; + +namespace TUI.Controls.Containers; + +public class DashboardContainer : ContainerBase +{ + private readonly Nodes _children = new(); + private readonly ContentContainer _content; + + public DashboardContainer() + { + var panel = new PanelComponent("Dependencies"); + _content = new ContentContainer(); + _content.SetOrientationVertical(); + SetOrientationVertical(); + + _children.Add(panel); + _children.Add(_content); + } + + public void AddChildren(IContainer node) + { + node.SetFixed(Orientation.Vertical, 1); + _content.AddChildren(node); + } + + public override Nodes GetNodes() => _children; +} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DependencyContainer.cs b/src/TUI/Controls/Containers/DependencyContainer.cs new file mode 100644 index 0000000..22569c7 --- /dev/null +++ b/src/TUI/Controls/Containers/DependencyContainer.cs @@ -0,0 +1,29 @@ +using TUI.Controls.Common; +using TUI.Controls.Components; +using TUI.Engine; +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.Theme; + +namespace TUI.Controls.Containers; + +public class DependencyContainer : ContainerBase +{ + private const int VersionColumnWidth = 10; + + public override Nodes GetNodes() + { + var stub = new StubComponent(new Size(20, 1)); + stub.SetPadding(Level.Normal); + + var version = new VersionComponent(VersionType.Convention, "10.20.30", Symbols.Site); + version.SetPadding(Level.Normal); + version.SetAlignment(Horizontal.Right); + version.SetFixed(Orientation.Horizontal, VersionColumnWidth); + + return new Nodes { stub, version, version, }; + } +} \ No newline at end of file diff --git a/src/TUI/Components/Controls/HeaderContainer.cs b/src/TUI/Controls/Containers/HeaderContainer.cs similarity index 88% rename from src/TUI/Components/Controls/HeaderContainer.cs rename to src/TUI/Controls/Containers/HeaderContainer.cs index cb8ceee..4090a80 100644 --- a/src/TUI/Components/Controls/HeaderContainer.cs +++ b/src/TUI/Controls/Containers/HeaderContainer.cs @@ -1,11 +1,11 @@ -using TUI.Components.Controls.Statics; -using TUI.Components.Controls.Statics.Hints; +using TUI.Controls.Statics; +using TUI.Controls.Statics.Hints; using TUI.Engine.Attributes.Alignments; using TUI.Engine.Containers; using TUI.Engine.Nodes; using TUI.Engine.Theme; -namespace TUI.Components.Controls; +namespace TUI.Controls.Containers; public class HeaderContainer : ContainerBase, IContainer { @@ -27,7 +27,7 @@ public class HeaderContainer : ContainerBase, IContainer hotkeysHints.SetPadding(Indentation.Default); hotkeysHints.SetAlignment(Horizontal.Left); - var logo = new Logo(); + var logo = new LogoComponent(); logo.SetAlignment(Horizontal.Right); logo.SetPaddingLeft(Indentation.Default); logo.SetPaddingBottom(Indentation.Default); diff --git a/src/TUI/Components/Layouts/DashboardLayout.cs b/src/TUI/Controls/Layouts/DashboardLayout.cs similarity index 66% rename from src/TUI/Components/Layouts/DashboardLayout.cs rename to src/TUI/Controls/Layouts/DashboardLayout.cs index fefa559..9efb3a7 100644 --- a/src/TUI/Components/Layouts/DashboardLayout.cs +++ b/src/TUI/Controls/Layouts/DashboardLayout.cs @@ -5,49 +5,34 @@ using TUI.Engine.Containers; using TUI.Engine.Nodes; using TUI.Engine.Theme; -namespace TUI.Components.Layouts; +namespace TUI.Controls.Layouts; public class DashboardLayout : ContainerBase, IContainer { - public DashboardLayout() + private readonly INode _header; + private readonly INode _footer; + private readonly INode _dashboard; + + public DashboardLayout(INode header, INode dashboard, IComponent footer) { SetOrientationVertical(); SetAdaptive(Orientation.Horizontal); SetAdaptive(Orientation.Vertical); - } - private INode _header; - private INode _footer; - private INode _dashboard; + header.SetFixed(Orientation.Vertical, 6); + footer.SetFixed(Orientation.Vertical, 1); + footer.SetPaddingRight(Level.Normal); + footer.SetAlignment(Horizontal.Right); + footer.SetAlignment(Vertical.Bottom); + + _header = header; + _footer = footer; + _dashboard = dashboard; + } public override Nodes GetNodes() => new() { _header, _dashboard, _footer }; - - public void AddDashboard(IComponent dashboard) - { - _dashboard = dashboard; - } - - public void AddHeader(IContainer header) - { - header.SetFixed(Orientation.Vertical, 6); - _header = header; - } - - public void AddFooter(IComponent footer) - { - footer.SetFixed(Orientation.Vertical, 1); - footer.SetPaddingRight(Level.Normal); - footer.SetAlignment(Horizontal.Right); - footer.SetAlignment(Vertical.Bottom); - _footer = footer; - } - - public string Render() - { - throw new NotImplementedException(); - } } \ No newline at end of file diff --git a/src/TUI/Components/Controls/Copyright.cs b/src/TUI/Controls/Statics/CopyrightComponent.cs similarity index 62% rename from src/TUI/Components/Controls/Copyright.cs rename to src/TUI/Controls/Statics/CopyrightComponent.cs index eaf419e..5e6be7f 100644 --- a/src/TUI/Components/Controls/Copyright.cs +++ b/src/TUI/Controls/Statics/CopyrightComponent.cs @@ -3,16 +3,16 @@ using TUI.Engine; using TUI.Engine.Components; using TUI.Engine.Theme; -namespace TUI.Components.Controls; +namespace TUI.Controls.Statics; -public class Copyright : StaticComponentBase +public class CopyrightComponent : StaticComponentBase { protected override void RenderWithCache(StringBuilder builder) { - builder.Append(Symbols.Copyright); + builder.Append(Symbols.Copyright.Info()); builder.Append(Symbols.Space); builder.Append("Kolosov A. aka \"dnwSilver\"".Hint()); builder.Append(Symbols.Space); - builder.Append(DateTime.Now.Year); + builder.Append(DateTime.Now.Year.Info()); } } diff --git a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs b/src/TUI/Controls/Statics/Hints/AppTypeHints.cs similarity index 69% rename from src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs rename to src/TUI/Controls/Statics/Hints/AppTypeHints.cs index 2f7d959..ee432b2 100644 --- a/src/TUI/Components/Controls/Statics/Hints/AppTypeHints.cs +++ b/src/TUI/Controls/Statics/Hints/AppTypeHints.cs @@ -2,18 +2,17 @@ using System.Text; using TUI.Engine; using TUI.Engine.Components; using TUI.Engine.Theme; -using TUI.UserInterface; -namespace TUI.Components.Controls.Statics.Hints; +namespace TUI.Controls.Statics.Hints; public class AppTypeHints : StaticComponentBase { private readonly Dictionary _hints = new() { - { Icons.NpmPackage, "package" }, - { Icons.DockerImage, "image" }, - { Icons.Site, "site" }, - { Icons.Api, "api" } + { Symbols.NpmPackage, "package" }, + { Symbols.DockerImage, "image" }, + { Symbols.Site, "site" }, + { Symbols.Api, "api" } }; protected override void RenderWithCache(StringBuilder builder) diff --git a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs b/src/TUI/Controls/Statics/Hints/HotkeysHint.cs similarity index 92% rename from src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs rename to src/TUI/Controls/Statics/Hints/HotkeysHint.cs index 12c80ba..a6ca871 100644 --- a/src/TUI/Components/Controls/Statics/Hints/HotkeysHint.cs +++ b/src/TUI/Controls/Statics/Hints/HotkeysHint.cs @@ -3,7 +3,7 @@ using TUI.Engine; using TUI.Engine.Components; using TUI.Engine.Theme; -namespace TUI.Components.Controls.Statics.Hints; +namespace TUI.Controls.Statics.Hints; public class HotkeysHint : StaticComponentBase { diff --git a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs b/src/TUI/Controls/Statics/Hints/TagHints.cs similarity index 69% rename from src/TUI/Components/Controls/Statics/Hints/TagHints.cs rename to src/TUI/Controls/Statics/Hints/TagHints.cs index 766f52f..912c605 100644 --- a/src/TUI/Components/Controls/Statics/Hints/TagHints.cs +++ b/src/TUI/Controls/Statics/Hints/TagHints.cs @@ -2,18 +2,17 @@ using System.Text; using TUI.Engine; using TUI.Engine.Components; using TUI.Engine.Theme; -using TUI.UserInterface; -namespace TUI.Components.Controls.Statics.Hints; +namespace TUI.Controls.Statics.Hints; public class TagHints : StaticComponentBase { private readonly Dictionary _hints = new() { - { Icons.Auth, "Auth" }, - { Icons.NetworkPublic, "WWW" }, - { Icons.SEO, "SEO" }, - { Icons.GitLab, "VCS" } + { Symbols.Auth, "Auth" }, + { Symbols.NetworkPublic, "WWW" }, + { Symbols.SEO, "SEO" }, + { Symbols.Git, "VCS" } }; protected override void RenderWithCache(StringBuilder builder) diff --git a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs b/src/TUI/Controls/Statics/Hints/VersionHints.cs similarity index 61% rename from src/TUI/Components/Controls/Statics/Hints/VersionHints.cs rename to src/TUI/Controls/Statics/Hints/VersionHints.cs index ee49809..1a41614 100644 --- a/src/TUI/Components/Controls/Statics/Hints/VersionHints.cs +++ b/src/TUI/Controls/Statics/Hints/VersionHints.cs @@ -1,18 +1,19 @@ using System.Text; +using TUI.Controls.Components; using TUI.Engine; using TUI.Engine.Components; using TUI.Engine.Theme; -namespace TUI.Components.Controls.Statics.Hints; +namespace TUI.Controls.Statics.Hints; public class VersionHints : StaticComponentBase { private readonly Dictionary _hints = new() { - { "󰎔", "too new".Info() }, - { "", "so good".Hint() }, - { "", "be nice".Main() }, - { "󰬟", "too old".Warning() } + { "󰎔", VersionType.ToNew.Colorize("too new") }, + { "", VersionType.SoGood.Colorize("so good") }, + { "", VersionType.BeNice.Colorize("be nice") }, + { "󰬟", VersionType.TooOld.Colorize("too old") } }; protected override void RenderWithCache(StringBuilder builder) diff --git a/src/TUI/Components/Controls/Statics/Logo.cs b/src/TUI/Controls/Statics/LogoComponent.cs similarity index 92% rename from src/TUI/Components/Controls/Statics/Logo.cs rename to src/TUI/Controls/Statics/LogoComponent.cs index bed96db..6f58008 100644 --- a/src/TUI/Components/Controls/Statics/Logo.cs +++ b/src/TUI/Controls/Statics/LogoComponent.cs @@ -3,9 +3,9 @@ using TUI.Engine; using TUI.Engine.Components; using TUI.Engine.Theme; -namespace TUI.Components.Controls.Statics; +namespace TUI.Controls.Statics; -public class Logo : StaticComponentBase +public class LogoComponent : StaticComponentBase { protected override void RenderWithCache(StringBuilder builder) { diff --git a/src/TUI/Domain/NewFile1.txt b/src/TUI/Domain/NewFile1.txt index 9f63c19..e9fb9e2 100644 --- a/src/TUI/Domain/NewFile1.txt +++ b/src/TUI/Domain/NewFile1.txt @@ -2,7 +2,7 @@ 󰘳 1 󱓟 releases  select prev 󰘳 2 󰧑 competencies  select next 󰘳 3  dependencies 󰬌 toggle head - 󰘳 4 󰬘 quit + 󰘳 4 󰬘 quit 󰎔 too new  Auth  package  so good 󰞉 WWW 󰡨 image diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 164d5e1..f9956e3 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -1,6 +1,7 @@ using System.Diagnostics; -using TUI.Components.Controls; -using TUI.Components.Layouts; +using TUI.Controls.Containers; +using TUI.Controls.Layouts; +using TUI.Controls.Statics; using TUI.Engine.Rendering.Canvas; namespace TUI.Pages; @@ -14,12 +15,14 @@ public class DependenciesPage ICanvas canvas = new ConsoleCanvas(); var header = new HeaderContainer(); - var copyright = new Copyright(); - var dashboard = new Dashboard("Dependencies"); - var layout = new DashboardLayout(); - layout.AddHeader(header); - layout.AddFooter(copyright); - layout.AddDashboard(dashboard); + var copyright = new CopyrightComponent(); + var dashboard = new DashboardContainer(); + var layout = new DashboardLayout(header, dashboard, copyright); + var dependency = new DependencyContainer(); + dashboard.AddChildren(dependency); + dashboard.AddChildren(dependency); + dashboard.AddChildren(dependency); + dashboard.AddChildren(dependency); // CommandLine = new CommandLine(); // DependenciesView = new DependenciesView(); diff --git a/src/TUI/TUI.csproj b/src/TUI/TUI.csproj index ee7b7f3..1250cb0 100644 --- a/src/TUI/TUI.csproj +++ b/src/TUI/TUI.csproj @@ -20,7 +20,15 @@ - + + <_Parameter1>$(MSBuildProjectName).Tests + + + <_Parameter1>$(MSBuildProjectName).Controls.Tests + + + + diff --git a/src/TUI/UserInterface/Icons.cs b/src/TUI/UserInterface/Icons.cs index b86cc29..63ceaea 100644 --- a/src/TUI/UserInterface/Icons.cs +++ b/src/TUI/UserInterface/Icons.cs @@ -1,35 +1,15 @@ -using Pastel; -using TUI.Engine.Theme; +using TUI.Engine; namespace TUI.UserInterface; public static class Icons { - public readonly static Dictionary Applications = new() + public static readonly Dictionary Applications = new() { - { NpmPackage, "package" }, - { DockerImage, "image" }, - { Site, "site" }, - { Api, "api" } + { Symbols.NpmPackage, "package" }, + { Symbols.DockerImage, "image" }, + { Symbols.Site, "site" }, + { Symbols.Api, "api" } }; - - public static string GitLab => GetIcon("", "E24329"); - public static string GitHub => GetIcon("", "ADBAC7"); - public static string Git => GetIcon("", "F14E32"); - public static string NetworkPublic => GetIcon("󰞉", "00FFFF"); - public static string NetworkPrivate => GetIcon("󰕑"); - public static string Undefined => GetIcon(""); - public static string Site => GetIcon("", "BF40BF"); - public static string Api => GetIcon("", "7F52FF"); - public static string DockerImage => GetIcon("󰡨", "086DD7"); - public static string NpmPackage => GetIcon("", "CB0000"); - public static string SEO => GetIcon("󰚩", "4285F4"); - public static string Auth => GetIcon("", "FFD700"); - public static string NotFound => GetIcon(""); - - private static string GetIcon(string icon, string? activeColor = null) - { - return activeColor != null ? icon.Pastel(activeColor) : icon.Hint(); - } } \ No newline at end of file diff --git a/tests/TUI.Controls.Tests/TUI.Controls.Tests.csproj b/tests/TUI.Controls.Tests/TUI.Controls.Tests.csproj new file mode 100644 index 0000000..de51f70 --- /dev/null +++ b/tests/TUI.Controls.Tests/TUI.Controls.Tests.csproj @@ -0,0 +1,33 @@ + + + + net7.0 + enable + enable + + false + true + TUI.Engine.Tests + TUI.Engine.Tests + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + diff --git a/tests/TUI.Controls.Tests/Usings.cs b/tests/TUI.Controls.Tests/Usings.cs new file mode 100644 index 0000000..8c927eb --- /dev/null +++ b/tests/TUI.Controls.Tests/Usings.cs @@ -0,0 +1 @@ +global using Xunit; \ No newline at end of file diff --git a/tests/TUI.Controls.Tests/VersionComponentTests.cs b/tests/TUI.Controls.Tests/VersionComponentTests.cs new file mode 100644 index 0000000..5822173 --- /dev/null +++ b/tests/TUI.Controls.Tests/VersionComponentTests.cs @@ -0,0 +1,26 @@ +using FluentAssertions; +using TUI.Controls.Components; +using TUI.Engine.Attributes; +using TUI.Engine.Components; + +namespace TUI.Engine.Tests +{ + public class VersionComponentTests + { + [Theory] + [Trait("Category", nameof(Sketch))] + [InlineData(VersionType.Convention, "\u001b[38;2;132;186;100m10.12.33\u001b[0m")] + [InlineData(VersionType.BeNice, "\u001b[38;2;132;186;100m10.12.33\u001b[0m")] + [InlineData(VersionType.SoGood, "\u001b[38;2;113;121;126m10.12.33\u001b[0m")] + [InlineData(VersionType.ToNew, "\u001b[38;2;37;121;159m10.12.33\u001b[0m")] + [InlineData(VersionType.TooOld, "\u001b[38;2;236;151;6m10.12.33\u001b[0m")] + public void DrawSketchVersionTypes(VersionType versionType, string expected) + { + var version = new VersionComponent(versionType, "10.12.33"); + + var sketch = (version as IComponent).MakeSketch(new Size(10, 2)); + + sketch.ToString().Should().Be(expected); + } + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/Draw/DrawStaticTests.cs b/tests/TUI.Engine.Tests/Draw/DrawStaticTests.cs new file mode 100644 index 0000000..93a6222 --- /dev/null +++ b/tests/TUI.Engine.Tests/Draw/DrawStaticTests.cs @@ -0,0 +1,38 @@ +using Moq; +using TUI.Engine.Attributes; +using TUI.Engine.Nodes; +using TUI.Engine.Rendering; +using TUI.Engine.Rendering.Canvas; +using TUI.Engine.Tests.Stubs; + +namespace TUI.Engine.Tests.Draw; + +public class DrawStaticTests : ComponentBaseTests +{ + [Fact] + [Trait("Category", nameof(IDrawable.Draw))] + public void DrawStaticComponentVerticalOrientation() + { + var canvas = Mock.Of(w => w.Size == new Size(6, 4)); + + var firstComponent = Prepare.Component(); + firstComponent.SetContent("First"); + firstComponent.SetRelative(); + var secondComponent = Prepare.Component(); + secondComponent.SetContent("Second"); + secondComponent.SetAbsolute(); + var thirdComponent = Prepare.Component(); + thirdComponent.SetContent("Third"); + + var root = Prepare.Container(firstComponent, secondComponent, thirdComponent); + root.SetOrientationVertical(); + + Craftsman(canvas).Draw(root, Position.Default, canvas.Size); + + Mock.Get(canvas).VerifyPositionOnce(Position.Default); + Mock.Get(canvas).VerifyPositionTimes(0, 2, 2); + Mock.Get(canvas).Verify(w => w.Paint("First"), Times.Once()); + Mock.Get(canvas).Verify(w => w.Paint("Second"), Times.Once()); + Mock.Get(canvas).Verify(w => w.Paint("Third"), Times.Once()); + } +} \ No newline at end of file diff --git a/tests/TUI.Engine.Tests/MockExtensions.cs b/tests/TUI.Engine.Tests/MockExtensions.cs index 3322533..f430f49 100644 --- a/tests/TUI.Engine.Tests/MockExtensions.cs +++ b/tests/TUI.Engine.Tests/MockExtensions.cs @@ -10,6 +10,10 @@ public static class MockExtensions { mock.Verify(w => w.SetPencil(new Position(left, top)), Times.Exactly(1)); } + public static void VerifyPositionTimes(this Mock mock, int left, int top, int times) where T : class, ICanvas + { + mock.Verify(w => w.SetPencil(new Position(left, top)), Times.Exactly(times)); + } public static void VerifyPositionOnce(this Mock mock, Position position) where T : class, ICanvas { diff --git a/tests/TUI.Engine.Tests/Primitives/IntegerTests.cs b/tests/TUI.Engine.Tests/Primitives/IntegerTests.cs index ed6d113..57a6e8c 100644 --- a/tests/TUI.Engine.Tests/Primitives/IntegerTests.cs +++ b/tests/TUI.Engine.Tests/Primitives/IntegerTests.cs @@ -1,6 +1,6 @@ using FluentAssertions; -namespace TUI.Engine.Tests.Draw; +namespace TUI.Engine.Tests.Primitives; public class IntegerTests { From 11e9fee9c3ea98fe0a512699a2b33629aead8a36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 22 Mar 2024 01:06:32 +0500 Subject: [PATCH 15/23] =?UTF-8?q?=E2=9C=A8=20Create=20dependencies=20repos?= =?UTF-8?q?itory.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI.Engine/SymbolExtensions.cs | 24 +++++++++ src/TUI.Engine/Symbols.cs | 23 --------- .../Controls/Components/VersionComponent.cs | 11 ++--- .../Controls/Containers/DashboardContainer.cs | 4 +- .../Containers/DependenciesContainer.cs | 49 +++++++++++++++++++ .../Containers/DependencyContainer.cs | 29 ----------- src/TUI/Domain/Brand.cs | 8 +++ src/TUI/Domain/Dependency.cs | 5 ++ src/TUI/Domain/ProjectDto.cs | 27 ---------- src/TUI/Domain/Settings.cs | 22 --------- src/TUI/Pages/DependenciesPage.cs | 49 ++++++++++++++++--- .../Providers/Dependencies/DependenciesDto.cs | 11 +++++ .../Dependencies}/DependencyDto.cs | 3 +- .../Dependencies/DependencyRepository.cs | 43 ++++++++++++++++ src/TUI/Providers/Dependencies/HubDto.cs | 15 ++++++ .../Dependencies}/Package.cs | 3 +- src/TUI/Providers/Dependencies/ProjectDto.cs | 16 ++++++ src/TUI/Providers/Dependencies/StackDto.cs | 17 +++++++ src/TUI/Settings/SourceDto.cs | 20 -------- src/TUI/Store/DependenciesStore.cs | 16 +++--- src/TUI/TUI.csproj | 5 +- src/TUI/UserInterface/Icons.cs | 7 +-- src/TUI/UserInterface/Panel.cs | 4 +- .../VersionComponentTests.cs | 3 +- 24 files changed, 259 insertions(+), 155 deletions(-) create mode 100644 src/TUI.Engine/SymbolExtensions.cs create mode 100644 src/TUI/Controls/Containers/DependenciesContainer.cs delete mode 100644 src/TUI/Controls/Containers/DependencyContainer.cs create mode 100644 src/TUI/Domain/Brand.cs create mode 100644 src/TUI/Domain/Dependency.cs delete mode 100644 src/TUI/Domain/ProjectDto.cs delete mode 100644 src/TUI/Domain/Settings.cs create mode 100644 src/TUI/Providers/Dependencies/DependenciesDto.cs rename src/TUI/{Settings => Providers/Dependencies}/DependencyDto.cs (92%) create mode 100644 src/TUI/Providers/Dependencies/DependencyRepository.cs create mode 100644 src/TUI/Providers/Dependencies/HubDto.cs rename src/TUI/{Domain => Providers/Dependencies}/Package.cs (95%) create mode 100644 src/TUI/Providers/Dependencies/ProjectDto.cs create mode 100644 src/TUI/Providers/Dependencies/StackDto.cs delete mode 100644 src/TUI/Settings/SourceDto.cs diff --git a/src/TUI.Engine/SymbolExtensions.cs b/src/TUI.Engine/SymbolExtensions.cs new file mode 100644 index 0000000..86e6a65 --- /dev/null +++ b/src/TUI.Engine/SymbolExtensions.cs @@ -0,0 +1,24 @@ +using Pastel; +using TUI.Engine.Theme; + +namespace TUI.Engine; + +public static class SymbolExtensions +{ + public static string Colorized(this string symbol) => + !SymbolColors.ContainsKey(symbol) ? symbol.Hint() : symbol.Pastel(SymbolColors[symbol]); + + private static readonly Dictionary SymbolColors = new() + { + { Symbols.Git, "F14E32" }, + { Symbols.Site, "BF40BF" }, + { Symbols.GitLab, "E24329" }, + { Symbols.GitHub, "ADBAC7" }, + { Symbols.NetworkPublic, "00FFFF" }, + { Symbols.Api, "7F52FF" }, + { Symbols.DockerImage, "086DD7" }, + { Symbols.NpmPackage, "CB0000" }, + { Symbols.SEO, "4285F4" }, + { Symbols.Auth, "FFD700" }, + }; +} \ No newline at end of file diff --git a/src/TUI.Engine/Symbols.cs b/src/TUI.Engine/Symbols.cs index 3857193..a96a98f 100644 --- a/src/TUI.Engine/Symbols.cs +++ b/src/TUI.Engine/Symbols.cs @@ -1,6 +1,3 @@ -using Pastel; -using TUI.Engine.Theme; - namespace TUI.Engine; public static class Symbols @@ -35,24 +32,4 @@ public static class Symbols public const string LeftTop = "┌"; public const string RightBottom = "┘"; } -} - -public static class CharExtensions -{ - public static string Colorized(this string symbol) => - !SymbolColors.ContainsKey(symbol) ? symbol.Hint() : symbol.Pastel(SymbolColors[symbol]); - - private static readonly Dictionary SymbolColors = new() - { - { Symbols.Git, "F14E32" }, - { Symbols.Site, "BF40BF" }, - { Symbols.GitLab, "E24329" }, - { Symbols.GitHub, "ADBAC7" }, - { Symbols.NetworkPublic, "00FFFF" }, - { Symbols.Api, "7F52FF" }, - { Symbols.DockerImage, "086DD7" }, - { Symbols.NpmPackage, "CB0000" }, - { Symbols.SEO, "4285F4" }, - { Symbols.Auth, "FFD700" }, - }; } \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionComponent.cs b/src/TUI/Controls/Components/VersionComponent.cs index 86babe3..bd1bd78 100644 --- a/src/TUI/Controls/Components/VersionComponent.cs +++ b/src/TUI/Controls/Components/VersionComponent.cs @@ -9,23 +9,22 @@ public class VersionComponent : ComponentBase { private readonly VersionType _type; private readonly string _version; - private readonly string? _icon; + private readonly Brand? _brand; - public VersionComponent(VersionType type, string version, string? icon = null) + public VersionComponent(VersionType type, string version, Brand? brand) { _type = type; _version = version; - _icon = icon; + _brand = brand; } protected override Sketch DrawComponent(Size minSize) { var builder = new StringBuilder(); - if (_icon is not null) + if (_brand is not null) { - builder.Append(_icon.Colorized()); - builder.Append(Symbols.Space); + builder.Append(_brand.ColorLogo()); } builder.Append(_version); diff --git a/src/TUI/Controls/Containers/DashboardContainer.cs b/src/TUI/Controls/Containers/DashboardContainer.cs index ac27e73..e083c49 100644 --- a/src/TUI/Controls/Containers/DashboardContainer.cs +++ b/src/TUI/Controls/Containers/DashboardContainer.cs @@ -2,6 +2,7 @@ using TUI.Controls.Components; using TUI.Engine.Attributes.Orientations; using TUI.Engine.Containers; using TUI.Engine.Nodes; +using TUI.Engine.Theme; namespace TUI.Controls.Containers; @@ -12,7 +13,8 @@ public class DashboardContainer : ContainerBase public DashboardContainer() { - var panel = new PanelComponent("Dependencies"); + // var panel = new PanelComponent("Dependencies ".Info() + Symbols.Node.Colorized()); + var panel = new PanelComponent("Dependencies".Info()); _content = new ContentContainer(); _content.SetOrientationVertical(); SetOrientationVertical(); diff --git a/src/TUI/Controls/Containers/DependenciesContainer.cs b/src/TUI/Controls/Containers/DependenciesContainer.cs new file mode 100644 index 0000000..37b9c8f --- /dev/null +++ b/src/TUI/Controls/Containers/DependenciesContainer.cs @@ -0,0 +1,49 @@ +using TUI.Controls.Common; +using TUI.Controls.Components; +using TUI.Domain; +using TUI.Engine.Attributes; +using TUI.Engine.Attributes.Alignments; +using TUI.Engine.Attributes.Orientations; +using TUI.Engine.Components; +using TUI.Engine.Containers; +using TUI.Engine.Nodes; +using TUI.Engine.Theme; + +namespace TUI.Controls.Containers; + +public class DependenciesContainer : ContainerBase +{ + private const int VersionColumnWidth = 10; + private const int TitleColumnWidth = 20; + + private readonly Nodes _dependencies = new(); + + public void AddTitleStub() + { + var size = new Size(TitleColumnWidth, 1); + var title = new StubComponent(size); + title.SetPadding(Level.Normal); + + _dependencies.Add(title); + } + + public void AddTitle(IComponent title) + { + title.SetPadding(Level.Normal); + title.SetFixed(Orientation.Horizontal, TitleColumnWidth); + + _dependencies.Add(title); + } + + public void AddDependency(Dependency dependency) + { + var version = new VersionComponent(VersionType.Convention, dependency.Version, dependency.Brand); + version.SetPadding(Level.Normal); + version.SetAlignment(Horizontal.Right); + version.SetFixed(Orientation.Horizontal, VersionColumnWidth); + + _dependencies.Add(version); + } + + public override Nodes GetNodes() => _dependencies; +} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DependencyContainer.cs b/src/TUI/Controls/Containers/DependencyContainer.cs deleted file mode 100644 index 22569c7..0000000 --- a/src/TUI/Controls/Containers/DependencyContainer.cs +++ /dev/null @@ -1,29 +0,0 @@ -using TUI.Controls.Common; -using TUI.Controls.Components; -using TUI.Engine; -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.Theme; - -namespace TUI.Controls.Containers; - -public class DependencyContainer : ContainerBase -{ - private const int VersionColumnWidth = 10; - - public override Nodes GetNodes() - { - var stub = new StubComponent(new Size(20, 1)); - stub.SetPadding(Level.Normal); - - var version = new VersionComponent(VersionType.Convention, "10.20.30", Symbols.Site); - version.SetPadding(Level.Normal); - version.SetAlignment(Horizontal.Right); - version.SetFixed(Orientation.Horizontal, VersionColumnWidth); - - return new Nodes { stub, version, version, }; - } -} \ No newline at end of file diff --git a/src/TUI/Domain/Brand.cs b/src/TUI/Domain/Brand.cs new file mode 100644 index 0000000..0530a0b --- /dev/null +++ b/src/TUI/Domain/Brand.cs @@ -0,0 +1,8 @@ +using Pastel; + +namespace TUI.Controls.Components; + +public record Brand(string Name, string Logo, string Color) +{ + public string ColorLogo() => Logo.Pastel(Color); +}; \ No newline at end of file diff --git a/src/TUI/Domain/Dependency.cs b/src/TUI/Domain/Dependency.cs new file mode 100644 index 0000000..38ff60d --- /dev/null +++ b/src/TUI/Domain/Dependency.cs @@ -0,0 +1,5 @@ +using TUI.Controls.Components; + +namespace TUI.Domain; + +public record Dependency(string Version, Brand Brand); \ No newline at end of file diff --git a/src/TUI/Domain/ProjectDto.cs b/src/TUI/Domain/ProjectDto.cs deleted file mode 100644 index df48aa4..0000000 --- a/src/TUI/Domain/ProjectDto.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Runtime.Serialization; -using TUI.Settings; -using YamlDotNet.Serialization; - - -namespace TUI.Domain; - -[DataContract] -[YamlSerializable] -public class ProjectDto -{ - [YamlMember] - [DataMember] - public string Icon { get; set; } - - [YamlMember] - [DataMember] - public string Name { get; set; } - - [YamlMember] - [DataMember] - public DependencyDto[] Dependencies { get; set; } - - [YamlMember] - [DataMember] - public IList Sources { get; set; } -} \ No newline at end of file diff --git a/src/TUI/Domain/Settings.cs b/src/TUI/Domain/Settings.cs deleted file mode 100644 index 6f03fe8..0000000 --- a/src/TUI/Domain/Settings.cs +++ /dev/null @@ -1,22 +0,0 @@ -using YamlDotNet.Serialization; -using YamlDotNet.Serialization.NamingConventions; - - -namespace TUI.Domain; - -[YamlSerializable] -public class Settings -{ - [YamlMember] - public ProjectDto[] Projects { get; set; } - - public static Settings Init() - { - var deserializer = new DeserializerBuilder() - .WithNamingConvention(UnderscoredNamingConvention.Instance) - .Build(); - - using var sr = new StreamReader("settings.yaml"); - return deserializer.Deserialize(sr.ReadToEnd()); - } -} \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index f9956e3..bd1862a 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -2,33 +2,66 @@ using System.Diagnostics; using TUI.Controls.Containers; using TUI.Controls.Layouts; using TUI.Controls.Statics; +using TUI.Domain; using TUI.Engine.Rendering.Canvas; +using TUI.Providers.Dependencies; namespace TUI.Pages; -public class DependenciesPage +interface IPage +{ + void Open(); + void Render(); + void Bind(); +} + +public abstract class PageBase : IPage { public void Open() { - Debugger.Log(0, "Event", "Open page dependencies\n"); + Debugger.Log(0, "Event", $"Open page ${GetType().UnderlyingSystemType.Name}\n"); + Bind(); + Render(); + } + public abstract void Render(); + + public abstract void Bind(); +} + +public class DependenciesPage : PageBase +{ + private IEnumerable ConventionDependencies; + + public override void Render() + { ICanvas canvas = new ConsoleCanvas(); var header = new HeaderContainer(); var copyright = new CopyrightComponent(); var dashboard = new DashboardContainer(); - var layout = new DashboardLayout(header, dashboard, copyright); - var dependency = new DependencyContainer(); - dashboard.AddChildren(dependency); - dashboard.AddChildren(dependency); - dashboard.AddChildren(dependency); - dashboard.AddChildren(dependency); + var dependenciesHeader = new DependenciesContainer(); + dependenciesHeader.AddTitleStub(); + + foreach (var conventionDependency in ConventionDependencies) + { + dependenciesHeader.AddDependency(conventionDependency); + } + + dashboard.AddChildren(dependenciesHeader); // CommandLine = new CommandLine(); // DependenciesView = new DependenciesView(); + var layout = new DashboardLayout(header, dashboard, copyright); canvas.Draw(layout); } + public override void Bind() + { + var repo = new DependencyRepository(); + ConventionDependencies = repo.Read("javascript"); + } + // private bool _commandLineInDisplay; // private ProjectDto _currentProjectDto; diff --git a/src/TUI/Providers/Dependencies/DependenciesDto.cs b/src/TUI/Providers/Dependencies/DependenciesDto.cs new file mode 100644 index 0000000..f42b152 --- /dev/null +++ b/src/TUI/Providers/Dependencies/DependenciesDto.cs @@ -0,0 +1,11 @@ +using System.Runtime.Serialization; +using YamlDotNet.Serialization; + +namespace TUI.Providers.Dependencies; + +[DataContract] +[YamlSerializable] +public class DependenciesDto +{ + [DataMember] [YamlMember] public StackDto[] Stacks { get; set; } +} \ No newline at end of file diff --git a/src/TUI/Settings/DependencyDto.cs b/src/TUI/Providers/Dependencies/DependencyDto.cs similarity index 92% rename from src/TUI/Settings/DependencyDto.cs rename to src/TUI/Providers/Dependencies/DependencyDto.cs index b341736..10c0715 100644 --- a/src/TUI/Settings/DependencyDto.cs +++ b/src/TUI/Providers/Dependencies/DependencyDto.cs @@ -1,8 +1,7 @@ using System.Runtime.Serialization; using YamlDotNet.Serialization; - -namespace TUI.Settings; +namespace TUI.Providers.Dependencies; [DataContract] [YamlSerializable] diff --git a/src/TUI/Providers/Dependencies/DependencyRepository.cs b/src/TUI/Providers/Dependencies/DependencyRepository.cs new file mode 100644 index 0000000..9b2845d --- /dev/null +++ b/src/TUI/Providers/Dependencies/DependencyRepository.cs @@ -0,0 +1,43 @@ +using TUI.Controls.Components; +using TUI.Domain; +using YamlDotNet.Serialization; +using YamlDotNet.Serialization.NamingConventions; + +namespace TUI.Providers.Dependencies; + +public class DependencyRepository +{ + private DependenciesDto? _dependenciesDto; + + private DependenciesDto DependenciesDto + { + get + { + if (_dependenciesDto is not null) + { + return _dependenciesDto; + } + + var deserializer = new DeserializerBuilder() + .WithNamingConvention(UnderscoredNamingConvention.Instance) + .Build(); + + using var sr = new StreamReader("dependencies.yaml"); + _dependenciesDto = deserializer.Deserialize(sr.ReadToEnd()); + + return _dependenciesDto; + } + } + + public IEnumerable Read(string stackName) + { + return DependenciesDto.Stacks + .Single(stack => stack.Name == stackName) + .Conventions + .Select(convention => + { + var brand = new Brand(convention.Name, convention.Icon, convention.Color); + return new Dependency(convention.Version, brand); + }); + } +} \ No newline at end of file diff --git a/src/TUI/Providers/Dependencies/HubDto.cs b/src/TUI/Providers/Dependencies/HubDto.cs new file mode 100644 index 0000000..ebb225f --- /dev/null +++ b/src/TUI/Providers/Dependencies/HubDto.cs @@ -0,0 +1,15 @@ +using System.Runtime.Serialization; +using YamlDotNet.Serialization; + +namespace TUI.Providers.Dependencies; + +[DataContract] +[YamlSerializable] +public class HubDto +{ + [YamlMember] [DataMember] public string Origin { get; set; } + + [YamlMember] [DataMember] public string Type { get; set; } + + [YamlMember] [DataMember] public IEnumerable Projects { get; set; } +} \ No newline at end of file diff --git a/src/TUI/Domain/Package.cs b/src/TUI/Providers/Dependencies/Package.cs similarity index 95% rename from src/TUI/Domain/Package.cs rename to src/TUI/Providers/Dependencies/Package.cs index b9d5519..2fb82a9 100644 --- a/src/TUI/Domain/Package.cs +++ b/src/TUI/Providers/Dependencies/Package.cs @@ -2,8 +2,7 @@ using System.Text.Json.Nodes; using System.Text.Json.Serialization; using TUI.Engine; - -namespace TUI.Domain; +namespace TUI.Providers.Dependencies; public class Package { diff --git a/src/TUI/Providers/Dependencies/ProjectDto.cs b/src/TUI/Providers/Dependencies/ProjectDto.cs new file mode 100644 index 0000000..72066e5 --- /dev/null +++ b/src/TUI/Providers/Dependencies/ProjectDto.cs @@ -0,0 +1,16 @@ +using System.Runtime.Serialization; +using YamlDotNet.Serialization; + +namespace TUI.Providers.Dependencies; + +[YamlSerializable] +public class ProjectDto +{ + [DataMember] [YamlMember] public int Id { get; set; } + + [DataMember] [YamlMember] public string Name { get; set; } + + [DataMember] [YamlMember] public string Deps { get; set; } + + [DataMember] [YamlMember] public IEnumerable Tags { get; set; } +} \ No newline at end of file diff --git a/src/TUI/Providers/Dependencies/StackDto.cs b/src/TUI/Providers/Dependencies/StackDto.cs new file mode 100644 index 0000000..9c10cc6 --- /dev/null +++ b/src/TUI/Providers/Dependencies/StackDto.cs @@ -0,0 +1,17 @@ +using System.Runtime.Serialization; +using YamlDotNet.Serialization; + +namespace TUI.Providers.Dependencies; + +[DataContract] +[YamlSerializable] +public class StackDto +{ + [YamlMember] [DataMember] public string Name { get; set; } + + [YamlMember] [DataMember] public string Icon { get; set; } + + [YamlMember] [DataMember] public DependencyDto[] Conventions { get; set; } + + [YamlMember] [DataMember] public IEnumerable Hubs { get; set; } +} \ No newline at end of file diff --git a/src/TUI/Settings/SourceDto.cs b/src/TUI/Settings/SourceDto.cs deleted file mode 100644 index 100db53..0000000 --- a/src/TUI/Settings/SourceDto.cs +++ /dev/null @@ -1,20 +0,0 @@ -using YamlDotNet.Serialization; - - -namespace TUI.Settings; - -[YamlSerializable] -public class SourceDto -{ - [YamlMember] - public string[] Tags { get; set; } - - [YamlMember] - public string Name { get; set; } - - [YamlMember] - public int ProjectId { get; set; } = 0; - - [YamlMember] - public string Repo { get; set; } -} \ No newline at end of file diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index 82eb923..d7f4388 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,7 +1,5 @@ using System.Text.Json; -using TUI.Domain; -using TUI.Engine; -using TUI.Settings; +using TUI.Providers.Dependencies; namespace TUI.Store; @@ -9,9 +7,10 @@ public static class DependenciesStore { private readonly static Dictionary Packages = new(); - private static Package DownloadPackage(SourceDto sourceDto) + private static Package DownloadPackage(ProjectDto projectDto) { - var endpoint = sourceDto.Tags.Have("gitlab") ? GetGitlabEndpoint(sourceDto) : sourceDto.Repo; + // var endpoint = projectDto.Tags.Have("gitlab") ? GetGitlabEndpoint(projectDto) : projectDto.Repo; + var endpoint = ""; if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; using HttpClient client = new(); @@ -21,10 +20,11 @@ public static class DependenciesStore return package; } - private static string GetGitlabEndpoint(SourceDto sourceDto) + private static string GetGitlabEndpoint(ProjectDto projectDto) { var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); - return $"{sourceDto.Repo}/api/v4/projects/{sourceDto.ProjectId}/repository/files/package.json/raw?" + - $"private_token={token}&ref=dev"; + // return $"{projectDto.Repo}/api/v4/projects/{projectDto.ProjectId}/repository/files/package.json/raw?" + + // $"private_token={token}&ref=dev"; + return ""; } } \ No newline at end of file diff --git a/src/TUI/TUI.csproj b/src/TUI/TUI.csproj index 1250cb0..f38e70b 100644 --- a/src/TUI/TUI.csproj +++ b/src/TUI/TUI.csproj @@ -14,7 +14,7 @@ - + Always @@ -30,5 +30,8 @@ + + + diff --git a/src/TUI/UserInterface/Icons.cs b/src/TUI/UserInterface/Icons.cs index 63ceaea..e904383 100644 --- a/src/TUI/UserInterface/Icons.cs +++ b/src/TUI/UserInterface/Icons.cs @@ -1,3 +1,4 @@ +using Pastel; using TUI.Engine; @@ -7,9 +8,9 @@ public static class Icons { public static readonly Dictionary Applications = new() { - { Symbols.NpmPackage, "package" }, - { Symbols.DockerImage, "image" }, - { Symbols.Site, "site" }, + { Symbols.NpmPackage.Colorized(), "package" }, + { Symbols.DockerImage.Colorized(), "image" }, + { Symbols.Site.Pastel("666666"), "site" }, { Symbols.Api, "api" } }; } \ No newline at end of file diff --git a/src/TUI/UserInterface/Panel.cs b/src/TUI/UserInterface/Panel.cs index 157062e..0054752 100644 --- a/src/TUI/UserInterface/Panel.cs +++ b/src/TUI/UserInterface/Panel.cs @@ -1,5 +1,5 @@ using TUI.Engine.Theme; -using TUI.Settings; +using TUI.Providers.Dependencies; namespace TUI.UserInterface; @@ -15,7 +15,7 @@ public static class Panel private static int _marginTop; - public static void RenderRows(SourceDto[] sources, int selectedRowNumber) + public static void RenderRows(ProjectDto[] sources, int selectedRowNumber) { for (var index = 0; index < sources.Length; index++) { diff --git a/tests/TUI.Controls.Tests/VersionComponentTests.cs b/tests/TUI.Controls.Tests/VersionComponentTests.cs index 5822173..66111a5 100644 --- a/tests/TUI.Controls.Tests/VersionComponentTests.cs +++ b/tests/TUI.Controls.Tests/VersionComponentTests.cs @@ -16,7 +16,8 @@ namespace TUI.Engine.Tests [InlineData(VersionType.TooOld, "\u001b[38;2;236;151;6m10.12.33\u001b[0m")] public void DrawSketchVersionTypes(VersionType versionType, string expected) { - var version = new VersionComponent(versionType, "10.12.33"); + var brand = new Brand("Docker", "󰡨", "#1d63ed"); + var version = new VersionComponent(versionType, "10.12.33", brand); var sketch = (version as IComponent).MakeSketch(new Size(10, 2)); From f80a78f8cb32f10abc5912a61884a411bd7b3753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Mon, 1 Apr 2024 18:37:40 +0500 Subject: [PATCH 16/23] =?UTF-8?q?=E2=9C=A8=20Add=20title=20for=20project?= =?UTF-8?q?=20dependency?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Domain/NewFile1.txt => docs/Features.txt | 66 +++++++++++++------ src/TUI.Engine/Components/Sketch.cs | 3 + src/TUI.Engine/SymbolExtensions.cs | 2 +- src/TUI.Engine/Symbols.cs | 2 +- src/TUI/Controls/Components/ProjectTitle.cs | 47 +++++++++++++ src/TUI/Controls/Components/Tag.cs | 61 ----------------- .../Controls/Containers/DashboardContainer.cs | 3 +- .../Containers/DependenciesContainer.cs | 3 +- src/TUI/Controls/Statics/Hints/TagHints.cs | 2 +- src/TUI/Domain/Hub.cs | 6 ++ src/TUI/Domain/Project.cs | 12 ++++ src/TUI/Pages/DependenciesPage.cs | 22 +++++-- .../Dependencies/DependencyRepository.cs | 20 +++++- src/TUI/Store/DependenciesStore.cs | 51 ++++++++------ src/TUI/TUI.csproj | 3 - src/TUI/UserInterface/Icons.cs | 2 +- 16 files changed, 186 insertions(+), 119 deletions(-) rename src/TUI/Domain/NewFile1.txt => docs/Features.txt (63%) create mode 100644 src/TUI/Controls/Components/ProjectTitle.cs delete mode 100644 src/TUI/Controls/Components/Tag.cs create mode 100644 src/TUI/Domain/Hub.cs create mode 100644 src/TUI/Domain/Project.cs diff --git a/src/TUI/Domain/NewFile1.txt b/docs/Features.txt similarity index 63% rename from src/TUI/Domain/NewFile1.txt rename to docs/Features.txt index e9fb9e2..49b2b06 100644 --- a/src/TUI/Domain/NewFile1.txt +++ b/docs/Features.txt @@ -9,35 +9,52 @@  be nice 󰚩 SEO  site 󰬟 too old  VCS  api - 󰦖 wait 󰲽 build 󱓞 release - 󱔢 reopen 󱞈 testing 󰶯 hotfix - 󱞇 in progress 󰦕 done  publish - 󱞇 review 󱄊 cancel - -   releases 󱓟  Fact  2023 -   releases 󱓟  Fact -   releases 󱓟  Planned -   releases 󱓟  Planned  2024-12-31 xfirm -   competencies 󰧑 -   growth zone 󰶼 -   dependencies  +   󱓟 releases  Fact  2023 +   󱓟 releases  Fact +   󱓟 releases  Planned +   󱓟 releases  Planned  2024-12-31 xfirm +   󰧑 competencies +   󰶼 growth zone +    dependencies +   󱁤 tools + + + +󰦖 wait 󰲽 build +󱔢 reopen 󱞈 testing +󱞇 in progress 󰦕 done +󱞇 review 󱄊 cancel ┌──────────────────────────────────────────────────────────────────────── Planned release ─────────────────────────────────────────────────────────────────┐ -│ 2024-12-31 4/11 xfirm [############# ] //green - done, blue - test, pink review/build, orange WIP -│ 4/11 xfirm [###############.......] //green - done, blue - test, pink review/build -│ 2024-12-31 4/11 xfirm [###############.......] //green - done, blue - test, pink review/build -│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build -│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build -│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build -│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build -│ 2024-12-31 xfirm 4/11 [############..........] //green - done, blue - test, pink review/build +│ 󱓟 Planned 󱜜 󰲌 application  Tasks +│ 2024-12-31 1d elk-site 4/11 󰦕 󰦕 󰦕 󰦕 󱞇 󱞇 󱞇 󱞈 󱞈 󱔢 󰦖 󰦖 󰦖 +│ elk-site 2/5 󰦕 󰦕 󰦖 󰦖 󰦖 +│ elk-site 22/22 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󰦕 󱞇 󱞇 󱞇 󱞈 󱞈 󱞈 󱔢 󰦖 󰦖 󰦖 +│ 2024-12-31 12d xfirm 4/12 󰦕 󰦕 󰦕 󰦕 󱞇 󱞇 󱞇 󱞈 󱞈 󱞈 󱔢 󰦖 󰦖 󰦖 └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + + +󰨑 show stopper 󰦖 wait 󰲽 build  feature +󰨑 first of all 󱔢 reopen 󱞈 testing  bug +󰨑 just do it 󱞇 in progress 󰦕 done +󰨑 doesn't rush 󱞇 review 󱄊 cancel + ┌──────────────────────────────────────────────────────────────────────── checkperson-site ────────────────────────────────────────────────────────────────┐ │ 󰨑 󰦖  ELK-3628 Create new menu.  Anna P. 󰵮 Petrov A. 󰙨 Ivanov I. │ 󰨑 󰦕  XF-12 Change input hover.  Alex K. 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. │ 󰨑 󱞇  ELK-3628 Crete new project with menu, profile, issues and #  Anna P. 󰵮 Ivanov I. 󰙨 Petrov A., Petrov B. └──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ + + + + publish +󱓞 release +󰶯 hotfix +󱓞 release candidate + ┌─────────────────────────────────────────────────────────────────────────── Actual releases 2023 ─────────────────────────────────────────────────────────┐ │ Jan Feb Mar Apl May Jun Jul Aug Sep Oct Nov Dec │ ├─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┼─────────┤ @@ -48,5 +65,12 @@ + GA4  Jaeger 󰡾 Fallback  Screenshots  Connected  Auth +Я YM  Prometheus 󰉼 Renovate  End2End  Disconnected 󰖟 WWW +󰩃 Husky 󱎴 Sentry 󱉕 Lighthouse  Unit  Not implemented 󰚩 SEO + Probs  Grafana 󱂅 Kibana  Coverage  No need - +┌─────────────────────────────────────────────────────────────────────────── Tools ──────────────────────────────────┐ +│   Я  󰉼 󰩃 󱎴 󱉕   󱂅     󰖟 󰚩  󰡾 +│ elk-site                    +└────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ diff --git a/src/TUI.Engine/Components/Sketch.cs b/src/TUI.Engine/Components/Sketch.cs index 6cd7da4..ed96902 100644 --- a/src/TUI.Engine/Components/Sketch.cs +++ b/src/TUI.Engine/Components/Sketch.cs @@ -1,3 +1,4 @@ +using System.Text; using TUI.Engine.Attributes; namespace TUI.Engine.Components; @@ -8,6 +9,8 @@ public sealed class Sketch : IEnumerable public Sketch(string content) => ContentRows = content.Split(Symbols.LineBreak); + public Sketch(StringBuilder builder) => ContentRows = builder.ToString().Split(Symbols.LineBreak); + public IEnumerator GetEnumerator() => ContentRows.GetEnumerator(); public IEnumerable Crop(Size maxSize) => ContentRows diff --git a/src/TUI.Engine/SymbolExtensions.cs b/src/TUI.Engine/SymbolExtensions.cs index 86e6a65..9454063 100644 --- a/src/TUI.Engine/SymbolExtensions.cs +++ b/src/TUI.Engine/SymbolExtensions.cs @@ -18,7 +18,7 @@ public static class SymbolExtensions { Symbols.Api, "7F52FF" }, { Symbols.DockerImage, "086DD7" }, { Symbols.NpmPackage, "CB0000" }, - { Symbols.SEO, "4285F4" }, + { Symbols.Seo, "4285F4" }, { Symbols.Auth, "FFD700" }, }; } \ No newline at end of file diff --git a/src/TUI.Engine/Symbols.cs b/src/TUI.Engine/Symbols.cs index a96a98f..b88094e 100644 --- a/src/TUI.Engine/Symbols.cs +++ b/src/TUI.Engine/Symbols.cs @@ -15,7 +15,7 @@ public static class Symbols public const string Api = ""; public const string DockerImage = ""; public const string NpmPackage = ""; - public const string SEO = "󰚩"; + public const string Seo = "󰚩"; public const string Auth = ""; public const string NotFound = ""; diff --git a/src/TUI/Controls/Components/ProjectTitle.cs b/src/TUI/Controls/Components/ProjectTitle.cs new file mode 100644 index 0000000..2a75355 --- /dev/null +++ b/src/TUI/Controls/Components/ProjectTitle.cs @@ -0,0 +1,47 @@ +using System.Text; +using TUI.Domain; +using TUI.Engine; +using TUI.Engine.Attributes; +using TUI.Engine.Components; +using TUI.Engine.Theme; +using TUI.UserInterface; +using static TUI.Engine.Symbols; + +namespace TUI.Controls.Components; + +public class ProjectTitle : ComponentBase +{ + private readonly Project _project; + + public ProjectTitle(Project project) + { + _project = project; + } + + protected override Sketch DrawComponent(Size minSize) + { + var builder = new StringBuilder(); + builder.Append(GetHub().Colorized()); + builder.Append(Space); + builder.Append((_project.IsPublicNetwork ? NetworkPublic : NetworkPrivate).Colorized()); + builder.Append(Space); + builder.Append(_project.SeoDependent ? Seo.Colorized() : Seo.Disable()); + builder.Append(Space); + builder.Append(_project.HasAuth ? Auth.Colorized() : Auth.Disable()); + builder.Append(Space); + builder.Append(GetApplicationType().Colorized()); + builder.Append(Space); + builder.Append(_project.Name.Disable()); + return new Sketch(builder); + } + + private string GetHub() => _project.Hub == "gitlab" ? GitLab : GitHub; + + private string GetApplicationType() + { + foreach (var application in Icons.Applications.Where(application => _project.Tags.Have(application.Value))) + return application.Key; + + return Undefined.Hint(); + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Components/Tag.cs b/src/TUI/Controls/Components/Tag.cs deleted file mode 100644 index 392064c..0000000 --- a/src/TUI/Controls/Components/Tag.cs +++ /dev/null @@ -1,61 +0,0 @@ -using System.Text; -using TUI.Engine; -using TUI.Engine.Attributes; -using TUI.Engine.Attributes.Alignments; -using TUI.Engine.Components; -using TUI.Engine.Theme; -using TUI.UserInterface; - -namespace TUI.Controls.Components; - -public class Tag : ComponentBase -{ - private IEnumerable _tags; - private string _gitType; - - public void Bind(IEnumerable tags, string gitType) - { - _tags = tags; - _gitType = gitType; - } - - public void Render(Horizontal horizontal, Size size) - { - var tagBuilder = new StringBuilder(); - - tagBuilder.Append(GetGitTypeImage(_gitType)); - tagBuilder.Append(Symbols.Space); - tagBuilder.Append(_tags.Have("public") ? Symbols.NetworkPublic : Symbols.NetworkPrivate); - tagBuilder.Append(Symbols.Space); - tagBuilder.Append(_tags.Have("seo") ? Symbols.SEO : Symbols.SEO.Disable()); - tagBuilder.Append(Symbols.Space); - tagBuilder.Append(_tags.Have("auth") ? Symbols.Auth : Symbols.Auth.Disable()); - tagBuilder.Append(Symbols.Space); - tagBuilder.Append(GetApplicationType()); - tagBuilder.Append(Symbols.Space); - - // base.Render(tagBuilder, position, size); - } - - private string GetApplicationType() - { - foreach (var application in Icons.Applications) - if (_tags.Have(application.Value)) - return application.Key; - - return Symbols.Undefined; - } - - private static string GetGitTypeImage(string gitType) => - gitType switch - { - "gitlab" => Symbols.GitLab, - "github" => Symbols.GitHub, - _ => Symbols.Git - }; - - protected override Sketch DrawComponent(Size minSize) - { - throw new NotImplementedException(); - } -} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DashboardContainer.cs b/src/TUI/Controls/Containers/DashboardContainer.cs index e083c49..d2ab1d0 100644 --- a/src/TUI/Controls/Containers/DashboardContainer.cs +++ b/src/TUI/Controls/Containers/DashboardContainer.cs @@ -13,8 +13,7 @@ public class DashboardContainer : ContainerBase public DashboardContainer() { - // var panel = new PanelComponent("Dependencies ".Info() + Symbols.Node.Colorized()); - var panel = new PanelComponent("Dependencies".Info()); + var panel = new PanelComponent(" ".Info() + "Dependencies".Main()); _content = new ContentContainer(); _content.SetOrientationVertical(); SetOrientationVertical(); diff --git a/src/TUI/Controls/Containers/DependenciesContainer.cs b/src/TUI/Controls/Containers/DependenciesContainer.cs index 37b9c8f..a6be9db 100644 --- a/src/TUI/Controls/Containers/DependenciesContainer.cs +++ b/src/TUI/Controls/Containers/DependenciesContainer.cs @@ -14,7 +14,7 @@ namespace TUI.Controls.Containers; public class DependenciesContainer : ContainerBase { private const int VersionColumnWidth = 10; - private const int TitleColumnWidth = 20; + private const int TitleColumnWidth = 25; private readonly Nodes _dependencies = new(); @@ -31,6 +31,7 @@ public class DependenciesContainer : ContainerBase { title.SetPadding(Level.Normal); title.SetFixed(Orientation.Horizontal, TitleColumnWidth); + title.SetAlignment(Horizontal.Left); _dependencies.Add(title); } diff --git a/src/TUI/Controls/Statics/Hints/TagHints.cs b/src/TUI/Controls/Statics/Hints/TagHints.cs index 912c605..8ee1a95 100644 --- a/src/TUI/Controls/Statics/Hints/TagHints.cs +++ b/src/TUI/Controls/Statics/Hints/TagHints.cs @@ -11,7 +11,7 @@ public class TagHints : StaticComponentBase { { Symbols.Auth, "Auth" }, { Symbols.NetworkPublic, "WWW" }, - { Symbols.SEO, "SEO" }, + { Symbols.Seo, "SEO" }, { Symbols.Git, "VCS" } }; diff --git a/src/TUI/Domain/Hub.cs b/src/TUI/Domain/Hub.cs new file mode 100644 index 0000000..ff0a924 --- /dev/null +++ b/src/TUI/Domain/Hub.cs @@ -0,0 +1,6 @@ +namespace TUI.Domain; + +public record Hub +{ + +} \ No newline at end of file diff --git a/src/TUI/Domain/Project.cs b/src/TUI/Domain/Project.cs new file mode 100644 index 0000000..1764c0b --- /dev/null +++ b/src/TUI/Domain/Project.cs @@ -0,0 +1,12 @@ +namespace TUI.Domain; + +public record Project(int Id, string Name, IEnumerable Tags, string Hub) +{ + private IEnumerable Dependencies => new List(); + + public bool IsPublicNetwork => Tags.Contains("public"); + + public bool HasAuth => Tags.Contains("auth"); + + public bool SeoDependent => Tags.Contains("seo"); +} \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index bd1862a..aa2ecd1 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -1,10 +1,12 @@ using System.Diagnostics; +using TUI.Controls.Components; using TUI.Controls.Containers; using TUI.Controls.Layouts; using TUI.Controls.Statics; using TUI.Domain; using TUI.Engine.Rendering.Canvas; using TUI.Providers.Dependencies; +using TUI.Store; namespace TUI.Pages; @@ -31,7 +33,7 @@ public abstract class PageBase : IPage public class DependenciesPage : PageBase { - private IEnumerable ConventionDependencies; + private DependenciesStore _store; public override void Render() { @@ -43,23 +45,31 @@ public class DependenciesPage : PageBase var dependenciesHeader = new DependenciesContainer(); dependenciesHeader.AddTitleStub(); - foreach (var conventionDependency in ConventionDependencies) + foreach (var conventionDependency in _store.ConventionDependencies) { dependenciesHeader.AddDependency(conventionDependency); } dashboard.AddChildren(dependenciesHeader); - // CommandLine = new CommandLine(); - // DependenciesView = new DependenciesView(); + + foreach (var project in _store.Projects) + { + var projectDependencies = new DependenciesContainer(); + projectDependencies.AddTitle(new ProjectTitle(project)); + dashboard.AddChildren(projectDependencies); + } var layout = new DashboardLayout(header, dashboard, copyright); canvas.Draw(layout); + + // CommandLine = new CommandLine(); + // DependenciesView = new DependenciesView(); } public override void Bind() { - var repo = new DependencyRepository(); - ConventionDependencies = repo.Read("javascript"); + _store = new DependenciesStore(); + _store.Bind(); } // private bool _commandLineInDisplay; diff --git a/src/TUI/Providers/Dependencies/DependencyRepository.cs b/src/TUI/Providers/Dependencies/DependencyRepository.cs index 9b2845d..80d5c91 100644 --- a/src/TUI/Providers/Dependencies/DependencyRepository.cs +++ b/src/TUI/Providers/Dependencies/DependencyRepository.cs @@ -29,7 +29,7 @@ public class DependencyRepository } } - public IEnumerable Read(string stackName) + public IEnumerable ReadConventions(string stackName) { return DependenciesDto.Stacks .Single(stack => stack.Name == stackName) @@ -40,4 +40,22 @@ public class DependencyRepository return new Dependency(convention.Version, brand); }); } + + public IEnumerable ReadProjects(string stackName) + { + var projects = new List(); + + var hubs = DependenciesDto.Stacks + .Single(stack => stack.Name == stackName) + .Hubs; + + foreach (var hub in hubs) + { + projects.AddRange(hub + .Projects + .Select(proj => new Project(proj.Id, proj.Name, proj.Tags, hub.Type))); + } + + return projects; + } } \ No newline at end of file diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index d7f4388..e32d540 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,30 +1,41 @@ -using System.Text.Json; +using TUI.Domain; using TUI.Providers.Dependencies; namespace TUI.Store; -public static class DependenciesStore +public class DependenciesStore { - private readonly static Dictionary Packages = new(); + public IEnumerable ConventionDependencies; - private static Package DownloadPackage(ProjectDto projectDto) + public IEnumerable Projects; + + public void Bind() { - // var endpoint = projectDto.Tags.Have("gitlab") ? GetGitlabEndpoint(projectDto) : projectDto.Repo; - var endpoint = ""; - if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; - - using HttpClient client = new(); - var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); - var package = JsonSerializer.Deserialize(json); - Packages.Add(endpoint, package); - return package; + var repo = new DependencyRepository(); + ConventionDependencies = repo.ReadConventions("javascript"); + Projects = repo.ReadProjects("javascript"); } - private static string GetGitlabEndpoint(ProjectDto projectDto) - { - var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); - // return $"{projectDto.Repo}/api/v4/projects/{projectDto.ProjectId}/repository/files/package.json/raw?" + - // $"private_token={token}&ref=dev"; - return ""; - } + // private readonly static Dictionary Packages = new(); + // + // private static Package DownloadPackage(ProjectDto projectDto) + // { + // // var endpoint = projectDto.Tags.Have("gitlab") ? GetGitlabEndpoint(projectDto) : projectDto.Repo; + // var endpoint = ""; + // if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; + // + // using HttpClient client = new(); + // var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); + // var package = JsonSerializer.Deserialize(json); + // Packages.Add(endpoint, package); + // return package; + // } + // + // private static string GetGitlabEndpoint(ProjectDto projectDto) + // { + // var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); + // // return $"{projectDto.Repo}/api/v4/projects/{projectDto.ProjectId}/repository/files/package.json/raw?" + + // // $"private_token={token}&ref=dev"; + // return ""; + // } } \ No newline at end of file diff --git a/src/TUI/TUI.csproj b/src/TUI/TUI.csproj index f38e70b..8cf2073 100644 --- a/src/TUI/TUI.csproj +++ b/src/TUI/TUI.csproj @@ -30,8 +30,5 @@ - - - diff --git a/src/TUI/UserInterface/Icons.cs b/src/TUI/UserInterface/Icons.cs index e904383..1819575 100644 --- a/src/TUI/UserInterface/Icons.cs +++ b/src/TUI/UserInterface/Icons.cs @@ -10,7 +10,7 @@ public static class Icons { { Symbols.NpmPackage.Colorized(), "package" }, { Symbols.DockerImage.Colorized(), "image" }, - { Symbols.Site.Pastel("666666"), "site" }, + { Symbols.Site.Colorized(), "site" }, { Symbols.Api, "api" } }; } \ No newline at end of file From 00e5eadab101ba96b4cc82bc9fb7b971e6784aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Mon, 1 Apr 2024 19:16:15 +0500 Subject: [PATCH 17/23] =?UTF-8?q?=E2=9C=A8=20Add=20breadcrumbs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Components/BreadCrumbsComponent.cs | 20 +++++++++++++ .../Controls/Containers/FooterContainer.cs | 28 +++++++++++++++++++ src/TUI/Controls/Layouts/DashboardLayout.cs | 6 +--- src/TUI/Pages/DependenciesPage.cs | 6 ++-- 4 files changed, 53 insertions(+), 7 deletions(-) create mode 100644 src/TUI/Controls/Components/BreadCrumbsComponent.cs create mode 100644 src/TUI/Controls/Containers/FooterContainer.cs diff --git a/src/TUI/Controls/Components/BreadCrumbsComponent.cs b/src/TUI/Controls/Components/BreadCrumbsComponent.cs new file mode 100644 index 0000000..0d230a5 --- /dev/null +++ b/src/TUI/Controls/Components/BreadCrumbsComponent.cs @@ -0,0 +1,20 @@ +using TUI.Engine.Attributes; +using TUI.Engine.Components; +using TUI.Engine.Theme; + +namespace TUI.Controls.Components; + +public class BreadCrumbsComponent : ComponentBase +{ + private readonly List _crumbs = new() { " " }; + + public BreadCrumbsComponent(params string[] crumbs) + { + _crumbs.AddRange(crumbs); + } + + protected override Sketch DrawComponent(Size minSize) + { + return new Sketch(string.Join("  ".Hint(), _crumbs).Hint()); + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/FooterContainer.cs b/src/TUI/Controls/Containers/FooterContainer.cs new file mode 100644 index 0000000..90c98d5 --- /dev/null +++ b/src/TUI/Controls/Containers/FooterContainer.cs @@ -0,0 +1,28 @@ +using TUI.Controls.Statics; +using TUI.Engine.Attributes.Alignments; +using TUI.Engine.Components; +using TUI.Engine.Containers; +using TUI.Engine.Nodes; +using TUI.Engine.Theme; + +namespace TUI.Controls.Containers; + +public class FooterContainer : ContainerBase +{ + private readonly INode _breadcrumbs; + + public FooterContainer(IComponent breadcrumbs) + { + breadcrumbs.SetAlignment(Horizontal.Left); + breadcrumbs.SetPaddingLeft(Level.Normal); + _breadcrumbs = breadcrumbs; + } + + public override Nodes GetNodes() + { + var copyright = new CopyrightComponent(); + copyright.SetAlignment(Horizontal.Right); + copyright.SetPaddingRight(Level.Normal); + return new Nodes { _breadcrumbs, copyright }; + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Layouts/DashboardLayout.cs b/src/TUI/Controls/Layouts/DashboardLayout.cs index 9efb3a7..f8e75e6 100644 --- a/src/TUI/Controls/Layouts/DashboardLayout.cs +++ b/src/TUI/Controls/Layouts/DashboardLayout.cs @@ -3,7 +3,6 @@ using TUI.Engine.Attributes.Orientations; using TUI.Engine.Components; using TUI.Engine.Containers; using TUI.Engine.Nodes; -using TUI.Engine.Theme; namespace TUI.Controls.Layouts; @@ -13,7 +12,7 @@ public class DashboardLayout : ContainerBase, IContainer private readonly INode _footer; private readonly INode _dashboard; - public DashboardLayout(INode header, INode dashboard, IComponent footer) + public DashboardLayout(INode header, INode dashboard, INode footer) { SetOrientationVertical(); SetAdaptive(Orientation.Horizontal); @@ -21,9 +20,6 @@ public class DashboardLayout : ContainerBase, IContainer header.SetFixed(Orientation.Vertical, 6); footer.SetFixed(Orientation.Vertical, 1); - footer.SetPaddingRight(Level.Normal); - footer.SetAlignment(Horizontal.Right); - footer.SetAlignment(Vertical.Bottom); _header = header; _footer = footer; diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index aa2ecd1..985f2b9 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -4,6 +4,7 @@ using TUI.Controls.Containers; using TUI.Controls.Layouts; using TUI.Controls.Statics; using TUI.Domain; +using TUI.Engine; using TUI.Engine.Rendering.Canvas; using TUI.Providers.Dependencies; using TUI.Store; @@ -40,7 +41,6 @@ public class DependenciesPage : PageBase ICanvas canvas = new ConsoleCanvas(); var header = new HeaderContainer(); - var copyright = new CopyrightComponent(); var dashboard = new DashboardContainer(); var dependenciesHeader = new DependenciesContainer(); dependenciesHeader.AddTitleStub(); @@ -59,7 +59,9 @@ public class DependenciesPage : PageBase dashboard.AddChildren(projectDependencies); } - var layout = new DashboardLayout(header, dashboard, copyright); + var breadCrumbs = new BreadCrumbsComponent(" dependencies", "JavaScript"); + var footer = new FooterContainer(breadCrumbs); + var layout = new DashboardLayout(header, dashboard, footer); canvas.Draw(layout); // CommandLine = new CommandLine(); From 3a85bfbdd335e81704bd035b6868fe1b9fa36ec6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Tue, 16 Apr 2024 17:58:51 +0500 Subject: [PATCH 18/23] =?UTF-8?q?=E2=9C=A8=20Add=20speaker=20component.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI.Engine/Nodes/INode.cs | 7 ++- src/TUI.Engine/Nodes/NodeBase.cs | 2 + .../Rendering/ComponentCraftsman.cs | 2 + .../Controls/Components/SpeakerComponent.cs | 50 +++++++++++++++++++ .../Controls/Components/VersionComponent.cs | 1 - .../Controls/Containers/FooterContainer.cs | 8 ++- src/TUI/Controls/Layouts/DashboardLayout.cs | 2 - src/TUI/Pages/DependenciesPage.cs | 26 ---------- src/TUI/Pages/IPage.cs | 8 +++ src/TUI/Pages/PageBase.cs | 17 +++++++ src/TUI/Pages/WelcomePage.cs | 33 ++++++++++++ src/TUI/Program.cs | 5 +- src/TUI/Store/DependenciesStore.cs | 5 ++ src/TUI/UserInterface/Icons.cs | 1 - 14 files changed, 133 insertions(+), 34 deletions(-) create mode 100644 src/TUI/Controls/Components/SpeakerComponent.cs create mode 100644 src/TUI/Pages/IPage.cs create mode 100644 src/TUI/Pages/PageBase.cs create mode 100644 src/TUI/Pages/WelcomePage.cs diff --git a/src/TUI.Engine/Nodes/INode.cs b/src/TUI.Engine/Nodes/INode.cs index 6bdfb87..97e3966 100644 --- a/src/TUI.Engine/Nodes/INode.cs +++ b/src/TUI.Engine/Nodes/INode.cs @@ -1,7 +1,12 @@ +using TUI.Engine.Attributes; using TUI.Engine.Attributes.Resizings; +using TUI.Engine.Rendering.Canvas; namespace TUI.Engine.Nodes; public interface INode : IResizable { -} \ No newline at end of file + DrawContext DrawContext { get; set; } +} + +public record DrawContext(ICanvas Canvas, Position Pencil, Size MaxSize); \ No newline at end of file diff --git a/src/TUI.Engine/Nodes/NodeBase.cs b/src/TUI.Engine/Nodes/NodeBase.cs index bb28979..79a4182 100644 --- a/src/TUI.Engine/Nodes/NodeBase.cs +++ b/src/TUI.Engine/Nodes/NodeBase.cs @@ -55,4 +55,6 @@ public abstract class NodeBase : INode } #endregion Resizing + + public DrawContext? DrawContext { get; set; } } \ No newline at end of file diff --git a/src/TUI.Engine/Rendering/ComponentCraftsman.cs b/src/TUI.Engine/Rendering/ComponentCraftsman.cs index 70f4044..cfb7e4a 100644 --- a/src/TUI.Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI.Engine/Rendering/ComponentCraftsman.cs @@ -25,6 +25,8 @@ internal sealed class ComponentCraftsman : CraftsmanBase, IDrawable foreach (var line in sketch.Crop(maxSize)) { + component.DrawContext = new DrawContext(_canvas, pencil, maxSize); + _canvas.SetPencil(correctedPencil); _canvas.Paint(line); diff --git a/src/TUI/Controls/Components/SpeakerComponent.cs b/src/TUI/Controls/Components/SpeakerComponent.cs new file mode 100644 index 0000000..1066978 --- /dev/null +++ b/src/TUI/Controls/Components/SpeakerComponent.cs @@ -0,0 +1,50 @@ +using TUI.Engine; +using TUI.Engine.Attributes; +using TUI.Engine.Components; +using TUI.Engine.Nodes; + +namespace TUI.Controls.Components; + +public class SpeakerComponent : ComponentBase +{ + private string _message = ""; + + private Position? _pencil; + + private SpeakerComponent() + { + } + + public static SpeakerComponent Instance { get; } = new(); + + protected override Sketch DrawComponent(Size minSize) + { + return new Sketch(_message); + } + + private void Clear() + { + _message = new string(' ', DrawContext.MaxSize.Width); + DrawContext.Canvas.Draw(Instance, _pencil, DrawContext.MaxSize); + } + + public void Shout(string emoji, string message) + { + if (DrawContext is null) + { + return; + } + + _pencil ??= DrawContext.Pencil with { }; + + Clear(); + _message = emoji + Symbols.Space + message; + DrawContext.Canvas.Draw(Instance, _pencil, DrawContext.MaxSize); + + Task.Delay(2000).ContinueWith(_ => + { + Clear(); + return Task.CompletedTask; + }); + } +} \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionComponent.cs b/src/TUI/Controls/Components/VersionComponent.cs index bd1bd78..23d6e70 100644 --- a/src/TUI/Controls/Components/VersionComponent.cs +++ b/src/TUI/Controls/Components/VersionComponent.cs @@ -1,5 +1,4 @@ using System.Text; -using TUI.Engine; using TUI.Engine.Attributes; using TUI.Engine.Components; diff --git a/src/TUI/Controls/Containers/FooterContainer.cs b/src/TUI/Controls/Containers/FooterContainer.cs index 90c98d5..132e7fb 100644 --- a/src/TUI/Controls/Containers/FooterContainer.cs +++ b/src/TUI/Controls/Containers/FooterContainer.cs @@ -1,3 +1,4 @@ +using TUI.Controls.Components; using TUI.Controls.Statics; using TUI.Engine.Attributes.Alignments; using TUI.Engine.Components; @@ -10,12 +11,15 @@ namespace TUI.Controls.Containers; public class FooterContainer : ContainerBase { private readonly INode _breadcrumbs; + private readonly INode _speaker; - public FooterContainer(IComponent breadcrumbs) + public FooterContainer(IComponent? breadcrumbs) { breadcrumbs.SetAlignment(Horizontal.Left); breadcrumbs.SetPaddingLeft(Level.Normal); _breadcrumbs = breadcrumbs; + + _speaker = SpeakerComponent.Instance; } public override Nodes GetNodes() @@ -23,6 +27,6 @@ public class FooterContainer : ContainerBase var copyright = new CopyrightComponent(); copyright.SetAlignment(Horizontal.Right); copyright.SetPaddingRight(Level.Normal); - return new Nodes { _breadcrumbs, copyright }; + return new Nodes { _breadcrumbs, _speaker, copyright }; } } \ No newline at end of file diff --git a/src/TUI/Controls/Layouts/DashboardLayout.cs b/src/TUI/Controls/Layouts/DashboardLayout.cs index f8e75e6..20124f1 100644 --- a/src/TUI/Controls/Layouts/DashboardLayout.cs +++ b/src/TUI/Controls/Layouts/DashboardLayout.cs @@ -1,6 +1,4 @@ -using TUI.Engine.Attributes.Alignments; using TUI.Engine.Attributes.Orientations; -using TUI.Engine.Components; using TUI.Engine.Containers; using TUI.Engine.Nodes; diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 985f2b9..0977680 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -1,37 +1,11 @@ -using System.Diagnostics; using TUI.Controls.Components; using TUI.Controls.Containers; using TUI.Controls.Layouts; -using TUI.Controls.Statics; -using TUI.Domain; -using TUI.Engine; using TUI.Engine.Rendering.Canvas; -using TUI.Providers.Dependencies; using TUI.Store; namespace TUI.Pages; -interface IPage -{ - void Open(); - void Render(); - void Bind(); -} - -public abstract class PageBase : IPage -{ - public void Open() - { - Debugger.Log(0, "Event", $"Open page ${GetType().UnderlyingSystemType.Name}\n"); - Bind(); - Render(); - } - - public abstract void Render(); - - public abstract void Bind(); -} - public class DependenciesPage : PageBase { private DependenciesStore _store; diff --git a/src/TUI/Pages/IPage.cs b/src/TUI/Pages/IPage.cs new file mode 100644 index 0000000..3a9b32a --- /dev/null +++ b/src/TUI/Pages/IPage.cs @@ -0,0 +1,8 @@ +namespace TUI.Pages; + +interface IPage +{ + void Open(); + void Render(); + void Bind(); +} \ No newline at end of file diff --git a/src/TUI/Pages/PageBase.cs b/src/TUI/Pages/PageBase.cs new file mode 100644 index 0000000..2dbce48 --- /dev/null +++ b/src/TUI/Pages/PageBase.cs @@ -0,0 +1,17 @@ +using System.Diagnostics; + +namespace TUI.Pages; + +public abstract class PageBase : IPage +{ + public void Open() + { + Debugger.Log(0, "Event", $"Open page ${GetType().UnderlyingSystemType.Name}\n"); + Bind(); + Render(); + } + + public abstract void Render(); + + public abstract void Bind(); +} \ No newline at end of file diff --git a/src/TUI/Pages/WelcomePage.cs b/src/TUI/Pages/WelcomePage.cs new file mode 100644 index 0000000..169c276 --- /dev/null +++ b/src/TUI/Pages/WelcomePage.cs @@ -0,0 +1,33 @@ +using TUI.Controls.Common; +using TUI.Controls.Components; +using TUI.Controls.Containers; +using TUI.Controls.Layouts; +using TUI.Controls.Statics; +using TUI.Engine.Attributes; +using TUI.Engine.Rendering.Canvas; + +namespace TUI.Pages; + +public class WelcomePage : PageBase +{ + public override void Render() + { + ICanvas canvas = new ConsoleCanvas(); + + var header = new StubComponent(new Size(1, 1)); + + var logo = new LogoComponent(); + + var breadCrumbs = new BreadCrumbsComponent(); + + var footer = new FooterContainer(breadCrumbs); + + var layout = new DashboardLayout(header, logo, footer); + + canvas.Draw(layout); + } + + public override void Bind() + { + } +} \ No newline at end of file diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index 775f06f..8852137 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -6,9 +6,12 @@ Console.CursorVisible = false; // var settings = Settings.Init(); +var welcomePage = new WelcomePage(); +welcomePage.Open(); +Thread.Sleep(2000); + var dependenciesPage = new DependenciesPage(); dependenciesPage.Open(); - // display.OpenDeps(settings.Projects[0]); var key = new ConsoleKeyInfo('1', ConsoleKey.NoName, false, false, false); diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index e32d540..166f638 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,3 +1,4 @@ +using TUI.Controls.Components; using TUI.Domain; using TUI.Providers.Dependencies; @@ -12,8 +13,12 @@ public class DependenciesStore public void Bind() { var repo = new DependencyRepository(); + ConventionDependencies = repo.ReadConventions("javascript"); + SpeakerComponent.Instance.Shout("🤔", "Prepare javascript conventions"); + Projects = repo.ReadProjects("javascript"); + SpeakerComponent.Instance.Shout("🤩", "Prepare javascript projects"); } // private readonly static Dictionary Packages = new(); diff --git a/src/TUI/UserInterface/Icons.cs b/src/TUI/UserInterface/Icons.cs index 1819575..07e7509 100644 --- a/src/TUI/UserInterface/Icons.cs +++ b/src/TUI/UserInterface/Icons.cs @@ -1,4 +1,3 @@ -using Pastel; using TUI.Engine; From a06f5c541e2b7f40cf0a7dd857fc98f86f730c0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Thu, 13 Jun 2024 14:07:45 +0500 Subject: [PATCH 19/23] =?UTF-8?q?=F0=9F=90=9B=20Fix=20bug=20in=20render=20?= =?UTF-8?q?top=20level.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI/Controls/Components/PanelComponent.cs | 20 +++++++++---------- .../Controls/Containers/DashboardContainer.cs | 10 +++++----- src/TUI/Pages/DependenciesPage.cs | 2 +- src/TUI/Program.cs | 3 +-- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/TUI/Controls/Components/PanelComponent.cs b/src/TUI/Controls/Components/PanelComponent.cs index a3536b5..9bb9d5c 100644 --- a/src/TUI/Controls/Components/PanelComponent.cs +++ b/src/TUI/Controls/Components/PanelComponent.cs @@ -10,13 +10,13 @@ namespace TUI.Controls.Components; public class PanelComponent : ComponentBase, IComponent { private readonly string _title; - + public PanelComponent(string title) { _title = title; SetAbsolute(); } - + private static void RenderTopLine(StringBuilder builder, Size size, string title) { var halfWidth = (size.Width - title.GetWidth() - (int)Indentation.BorderWidth * 2 - @@ -24,15 +24,15 @@ public class PanelComponent : ComponentBase, IComponent builder.Append(Angles.LeftTop); builder.Append(Lines.Horizontal.Repeat(halfWidth)); builder.AppendFormat("{0}{1}{0}", Space.Repeat(Convert.ToInt32(Indentation.Default)), title); - builder.Append(Lines.Horizontal.Repeat(halfWidth)); + builder.Append(Lines.Horizontal.Repeat(halfWidth + halfWidth % 2)); builder.Append(Angles.RightTop); builder.Append(LineBreak); } - + private static void RenderMiddleLine(StringBuilder builder, Size size) { var dashboardHeight = size.Height - (int)Indentation.BorderWidth * 2; - + while (dashboardHeight > 0) { var bodyWidth = size.Width - (int)Indentation.BorderWidth * 2; @@ -40,11 +40,11 @@ public class PanelComponent : ComponentBase, IComponent builder.Append(Space.Repeat(bodyWidth)); builder.Append(Lines.Vertical); builder.Append(LineBreak); - + dashboardHeight--; } } - + private static void RenderBottomLine(StringBuilder builder, Size size) { var width = size.Width - (int)Indentation.BorderWidth * 2; @@ -53,15 +53,15 @@ public class PanelComponent : ComponentBase, IComponent builder.Append(Angles.RightBottom); builder.Append(LineBreak); } - + protected override Sketch DrawComponent(Size minSize) { var builder = new StringBuilder(); - + RenderTopLine(builder, minSize, _title); RenderMiddleLine(builder, minSize); RenderBottomLine(builder, minSize); - + return new Sketch(builder.ToString().Main()); } } \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DashboardContainer.cs b/src/TUI/Controls/Containers/DashboardContainer.cs index d2ab1d0..a556a5c 100644 --- a/src/TUI/Controls/Containers/DashboardContainer.cs +++ b/src/TUI/Controls/Containers/DashboardContainer.cs @@ -10,23 +10,23 @@ public class DashboardContainer : ContainerBase { private readonly Nodes _children = new(); private readonly ContentContainer _content; - + public DashboardContainer() { - var panel = new PanelComponent(" ".Info() + "Dependencies".Main()); + var panel = new PanelComponent(" ".Info() + " Dependencies".Main()); _content = new ContentContainer(); _content.SetOrientationVertical(); SetOrientationVertical(); - + _children.Add(panel); _children.Add(_content); } - + public void AddChildren(IContainer node) { node.SetFixed(Orientation.Vertical, 1); _content.AddChildren(node); } - + public override Nodes GetNodes() => _children; } \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 0977680..4820dc8 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -33,7 +33,7 @@ public class DependenciesPage : PageBase dashboard.AddChildren(projectDependencies); } - var breadCrumbs = new BreadCrumbsComponent(" dependencies", "JavaScript"); + var breadCrumbs = new BreadCrumbsComponent(" Dependencies", "JavaScript"); var footer = new FooterContainer(breadCrumbs); var layout = new DashboardLayout(header, dashboard, footer); canvas.Draw(layout); diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index 8852137..14e60b8 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -8,11 +8,10 @@ Console.CursorVisible = false; var welcomePage = new WelcomePage(); welcomePage.Open(); -Thread.Sleep(2000); +Thread.Sleep(500); var dependenciesPage = new DependenciesPage(); dependenciesPage.Open(); -// display.OpenDeps(settings.Projects[0]); var key = new ConsoleKeyInfo('1', ConsoleKey.NoName, false, false, false); var waitCommand = true; From 92e3e37bd19798283a0517f1dd5103f122642eea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 14 Jun 2024 16:02:21 +0500 Subject: [PATCH 20/23] =?UTF-8?q?=E2=9C=A8=20Add=20render=20for=20legacy?= =?UTF-8?q?=20project.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI.Engine/Nodes/INode.cs | 5 +- src/TUI.Engine/Nodes/NodeBase.cs | 2 + .../Rendering/ComponentCraftsman.cs | 22 +++-- src/TUI.Engine/Theme/Palette.cs | 31 +++---- src/TUI/Controls/Common/StubComponent.cs | 19 ++-- src/TUI/Controls/Components/ProjectTitle.cs | 12 +-- .../Controls/Components/VersionComponent.cs | 22 +++-- src/TUI/Controls/Components/VersionStatus.cs | 10 +++ src/TUI/Controls/Components/VersionType.cs | 10 ++- .../Components/VersionTypeExtensions.cs | 13 ++- .../Controls/Containers/DashboardContainer.cs | 2 + .../Containers/DependenciesContainer.cs | 59 ++++++++++--- .../Controls/Statics/Hints/VersionHints.cs | 8 +- src/TUI/Domain/Brand.cs | 6 +- src/TUI/Domain/Dependency.cs | 64 +++++++++++++- src/TUI/Domain/Hub.cs | 5 +- src/TUI/Domain/Project.cs | 10 ++- src/TUI/Domain/Version.cs | 32 +++++++ src/TUI/Pages/DependenciesPage.cs | 82 ++++++++++++----- src/TUI/Pages/IPage.cs | 1 + src/TUI/Pages/PageBase.cs | 7 +- src/TUI/Pages/WelcomePage.cs | 4 + src/TUI/Program.cs | 23 +++-- .../Dependencies/DependencyRepository.cs | 88 ++++++++++++++++--- .../{Package.cs => PackageJson.cs} | 14 +-- src/TUI/Store/DependenciesStore.cs | 52 +++++------ .../VersionComponentTests.cs | 45 ++++++++-- 27 files changed, 479 insertions(+), 169 deletions(-) create mode 100644 src/TUI/Controls/Components/VersionStatus.cs create mode 100644 src/TUI/Domain/Version.cs rename src/TUI/Providers/Dependencies/{Package.cs => PackageJson.cs} (92%) diff --git a/src/TUI.Engine/Nodes/INode.cs b/src/TUI.Engine/Nodes/INode.cs index 97e3966..02e87ed 100644 --- a/src/TUI.Engine/Nodes/INode.cs +++ b/src/TUI.Engine/Nodes/INode.cs @@ -7,6 +7,9 @@ namespace TUI.Engine.Nodes; public interface INode : IResizable { DrawContext DrawContext { get; set; } + StyleContext StyleContext { get; set; } } -public record DrawContext(ICanvas Canvas, Position Pencil, Size MaxSize); \ No newline at end of file +public record DrawContext(ICanvas Canvas, Position Pencil, Size MaxSize); + +public record StyleContext(string? Foreground, string? Background = null); \ No newline at end of file diff --git a/src/TUI.Engine/Nodes/NodeBase.cs b/src/TUI.Engine/Nodes/NodeBase.cs index 79a4182..30e88cd 100644 --- a/src/TUI.Engine/Nodes/NodeBase.cs +++ b/src/TUI.Engine/Nodes/NodeBase.cs @@ -57,4 +57,6 @@ public abstract class NodeBase : INode #endregion Resizing public DrawContext? DrawContext { get; set; } + + public StyleContext? StyleContext { get; set; } } \ No newline at end of file diff --git a/src/TUI.Engine/Rendering/ComponentCraftsman.cs b/src/TUI.Engine/Rendering/ComponentCraftsman.cs index cfb7e4a..a24cba9 100644 --- a/src/TUI.Engine/Rendering/ComponentCraftsman.cs +++ b/src/TUI.Engine/Rendering/ComponentCraftsman.cs @@ -1,3 +1,4 @@ +using Pastel; using TUI.Engine.Attributes; using TUI.Engine.Components; using TUI.Engine.Nodes; @@ -8,31 +9,34 @@ namespace TUI.Engine.Rendering; internal sealed class ComponentCraftsman : CraftsmanBase, IDrawable { private readonly ICanvas _canvas; - + public ComponentCraftsman(ICanvas canvas) { _canvas = canvas; } - + public Size Draw(IComponent component, Position pencil, Size maxSize) { var sketch = component.MakeSketch(maxSize); var sketchSize = sketch.GetSize(); - + var correctedPencil = component.CorrectContentPosition(pencil, maxSize, sketchSize); - + Debug(pencil, maxSize); - + foreach (var line in sketch.Crop(maxSize)) { component.DrawContext = new DrawContext(_canvas, pencil, maxSize); - + _canvas.SetPencil(correctedPencil); - _canvas.Paint(line); - + _canvas.Paint(component.StyleContext is not null + ? line.RemoveColors().Pastel(component.StyleContext.Foreground) + : line); + + correctedPencil = correctedPencil with { Top = correctedPencil.Top + 1 }; } - + return sketchSize; } } \ No newline at end of file diff --git a/src/TUI.Engine/Theme/Palette.cs b/src/TUI.Engine/Theme/Palette.cs index 5ab1765..8f9b7ea 100644 --- a/src/TUI.Engine/Theme/Palette.cs +++ b/src/TUI.Engine/Theme/Palette.cs @@ -4,31 +4,32 @@ namespace TUI.Engine.Theme; public static class Palette { - private const string HoverColor = "292928"; - private const string PrimaryColor = "84BA64"; - private const string HintColor = "71797E"; - private const string ErrorColor = "CA3433"; - private const string WarningColor = "EC9706"; - private const string InfoColor = "25799F"; - + public const string HoverColor = "292928"; + public const string PrimaryColor = "84BA64"; + public const string HintColor = "71797E"; + public const string DisableColor = "303030"; + public const string ErrorColor = "CA3433"; + public const string WarningColor = "EC9706"; + public const string InfoColor = "25799F"; + public static string Main(this string currentText, bool isFocused = true) => isFocused ? currentText.Pastel(PrimaryColor) : Hint(currentText); - + public static string Hint(this string currentText) => currentText.Pastel(HintColor); - + public static string Hint(this char currentText) => currentText.ToString().Pastel(HintColor); - + public static string Disable(this string currentText) => currentText.RemoveColors().Pastel(HintColor); - + public static string Warning(this string currentText) => currentText.Pastel(WarningColor); - + public static string Error(this string currentText) => currentText.Pastel(ErrorColor); - + public static string Info(this string currentText) => currentText.Pastel(InfoColor); - + public static string Info(this char currentText) => currentText.ToString().Pastel(InfoColor); - + public static string Info(this int currentText) => currentText.ToString().Pastel(InfoColor); } \ No newline at end of file diff --git a/src/TUI/Controls/Common/StubComponent.cs b/src/TUI/Controls/Common/StubComponent.cs index 8a498ee..a3c39e9 100644 --- a/src/TUI/Controls/Common/StubComponent.cs +++ b/src/TUI/Controls/Common/StubComponent.cs @@ -9,25 +9,32 @@ namespace TUI.Controls.Common; public class StubComponent : ComponentBase { private readonly Size _size; - - public StubComponent(Size size) + private readonly string? _text; + + public StubComponent(Size size, string? text = null) { _size = size; + _text = text; SetFixed(Orientation.Horizontal, size.Width); SetFixed(Orientation.Vertical, size.Height); } - + protected override Sketch DrawComponent(Size minSize) { var builder = new StringBuilder(); var height = 0; - + + while (_size.Height > height) { - builder.Append(Symbols.Space.Repeat(_size.Width)); + builder.Append(Symbols.Space.Repeat(_size.Width - (_text?.GetWidth() ?? 0))); height++; } - + + if (_text is not null) + { + builder.Append(_text); + } return new Sketch(builder.ToString()); } } \ No newline at end of file diff --git a/src/TUI/Controls/Components/ProjectTitle.cs b/src/TUI/Controls/Components/ProjectTitle.cs index 2a75355..a5f9559 100644 --- a/src/TUI/Controls/Components/ProjectTitle.cs +++ b/src/TUI/Controls/Components/ProjectTitle.cs @@ -12,12 +12,12 @@ namespace TUI.Controls.Components; public class ProjectTitle : ComponentBase { private readonly Project _project; - + public ProjectTitle(Project project) { _project = project; } - + protected override Sketch DrawComponent(Size minSize) { var builder = new StringBuilder(); @@ -34,14 +34,14 @@ public class ProjectTitle : ComponentBase builder.Append(_project.Name.Disable()); return new Sketch(builder); } - - private string GetHub() => _project.Hub == "gitlab" ? GitLab : GitHub; - + + private string GetHub() => _project.Hub.Type == "gitlab" ? GitLab : GitHub; + private string GetApplicationType() { foreach (var application in Icons.Applications.Where(application => _project.Tags.Have(application.Value))) return application.Key; - + return Undefined.Hint(); } } \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionComponent.cs b/src/TUI/Controls/Components/VersionComponent.cs index 23d6e70..0f4408b 100644 --- a/src/TUI/Controls/Components/VersionComponent.cs +++ b/src/TUI/Controls/Components/VersionComponent.cs @@ -1,4 +1,5 @@ using System.Text; +using TUI.Domain; using TUI.Engine.Attributes; using TUI.Engine.Components; @@ -9,26 +10,31 @@ public class VersionComponent : ComponentBase private readonly VersionType _type; private readonly string _version; private readonly Brand? _brand; - - public VersionComponent(VersionType type, string version, Brand? brand) + private readonly VersionStatus _status; + + public VersionComponent(string version, Brand brand, VersionStatus status = VersionStatus.SoGood, + VersionType type = VersionType.Release) { - _type = type; _version = version; _brand = brand; + _status = status; + _type = type; } - + protected override Sketch DrawComponent(Size minSize) { var builder = new StringBuilder(); - + + // builder.Append(_type.ToString()); + if (_brand is not null) { builder.Append(_brand.ColorLogo()); } - + builder.Append(_version); var sketch = builder.ToString(); - - return new Sketch(_type.Colorize(sketch)); + + return new Sketch(_status.Colorize(sketch)); } } \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionStatus.cs b/src/TUI/Controls/Components/VersionStatus.cs new file mode 100644 index 0000000..0974abe --- /dev/null +++ b/src/TUI/Controls/Components/VersionStatus.cs @@ -0,0 +1,10 @@ +namespace TUI.Controls.Components; + +public enum VersionStatus +{ + NotFound, + ToNew, + SoGood, + BeNice, + TooOld, +} \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionType.cs b/src/TUI/Controls/Components/VersionType.cs index 108dc0a..786c668 100644 --- a/src/TUI/Controls/Components/VersionType.cs +++ b/src/TUI/Controls/Components/VersionType.cs @@ -3,8 +3,10 @@ namespace TUI.Controls.Components; public enum VersionType { Convention, - ToNew, - SoGood, - BeNice, - TooOld, + Release, + Candidate, + Canary, + Alpha, + Beta, + Next, } \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionTypeExtensions.cs b/src/TUI/Controls/Components/VersionTypeExtensions.cs index 3178ca7..519815b 100644 --- a/src/TUI/Controls/Components/VersionTypeExtensions.cs +++ b/src/TUI/Controls/Components/VersionTypeExtensions.cs @@ -4,14 +4,13 @@ namespace TUI.Controls.Components; public static class VersionTypeExtensions { - public static string Colorize(this VersionType versionType, string value) => - versionType switch + public static string Colorize(this VersionStatus versionStatus, string value) => + versionStatus switch { - VersionType.TooOld => value.Warning(), - VersionType.ToNew => value.Info(), - VersionType.SoGood => value.Hint(), - VersionType.BeNice => value.Main(), - VersionType.Convention => value.Main(), + VersionStatus.TooOld => value.Warning(), + VersionStatus.ToNew => value.Info(), + VersionStatus.SoGood => value.Hint(), + VersionStatus.BeNice => value.Main(), _ => value }; } \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DashboardContainer.cs b/src/TUI/Controls/Containers/DashboardContainer.cs index a556a5c..d775396 100644 --- a/src/TUI/Controls/Containers/DashboardContainer.cs +++ b/src/TUI/Controls/Containers/DashboardContainer.cs @@ -29,4 +29,6 @@ public class DashboardContainer : ContainerBase } public override Nodes GetNodes() => _children; + + public Nodes GetContent() => _content.GetNodes(); } \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DependenciesContainer.cs b/src/TUI/Controls/Containers/DependenciesContainer.cs index a6be9db..23393c9 100644 --- a/src/TUI/Controls/Containers/DependenciesContainer.cs +++ b/src/TUI/Controls/Containers/DependenciesContainer.cs @@ -1,6 +1,7 @@ using TUI.Controls.Common; using TUI.Controls.Components; using TUI.Domain; +using TUI.Engine; using TUI.Engine.Attributes; using TUI.Engine.Attributes.Alignments; using TUI.Engine.Attributes.Orientations; @@ -13,38 +14,76 @@ namespace TUI.Controls.Containers; public class DependenciesContainer : ContainerBase { + public readonly Project? Project; + private const int VersionColumnWidth = 10; + private const int TitleColumnWidth = 25; - + private readonly Nodes _dependencies = new(); - + + public DependenciesContainer() + { + } + + public DependenciesContainer(Project project) + { + Project = project; + } + public void AddTitleStub() { var size = new Size(TitleColumnWidth, 1); var title = new StubComponent(size); title.SetPadding(Level.Normal); - + _dependencies.Add(title); } - + public void AddTitle(IComponent title) { title.SetPadding(Level.Normal); title.SetFixed(Orientation.Horizontal, TitleColumnWidth); title.SetAlignment(Horizontal.Left); - + + if (Project is not null && Project.Legacy) + { + title.StyleContext = new StyleContext(Palette.DisableColor); + } + _dependencies.Add(title); } - - public void AddDependency(Dependency dependency) + + public void AddDependencyStub() { - var version = new VersionComponent(VersionType.Convention, dependency.Version, dependency.Brand); + var size = new Size(VersionColumnWidth, 1); + var stub = new StubComponent(size, Symbols.NotFound.Hint()); + stub.SetPadding(Level.Normal); + stub.SetAlignment(Horizontal.Right); + stub.SetFixed(Orientation.Horizontal, VersionColumnWidth); + + if (Project is not null && Project.Legacy) + { + stub.StyleContext = new StyleContext(Palette.DisableColor); + } + + _dependencies.Add(stub); + } + + public void AddDependency(Dependency dependency, VersionStatus status = VersionStatus.BeNice) + { + var version = new VersionComponent(dependency.Version, dependency.Brand, status, dependency.Type); version.SetPadding(Level.Normal); version.SetAlignment(Horizontal.Right); version.SetFixed(Orientation.Horizontal, VersionColumnWidth); - + + if (Project is not null && Project.Legacy) + { + version.StyleContext = new StyleContext(Palette.DisableColor); + } + _dependencies.Add(version); } - + public override Nodes GetNodes() => _dependencies; } \ No newline at end of file diff --git a/src/TUI/Controls/Statics/Hints/VersionHints.cs b/src/TUI/Controls/Statics/Hints/VersionHints.cs index 1a41614..b271bb2 100644 --- a/src/TUI/Controls/Statics/Hints/VersionHints.cs +++ b/src/TUI/Controls/Statics/Hints/VersionHints.cs @@ -10,10 +10,10 @@ public class VersionHints : StaticComponentBase { private readonly Dictionary _hints = new() { - { "󰎔", VersionType.ToNew.Colorize("too new") }, - { "", VersionType.SoGood.Colorize("so good") }, - { "", VersionType.BeNice.Colorize("be nice") }, - { "󰬟", VersionType.TooOld.Colorize("too old") } + { "󰎔", VersionStatus.ToNew.Colorize("too new") }, + { "", VersionStatus.SoGood.Colorize("so good") }, + { "", VersionStatus.BeNice.Colorize("be nice") }, + { "󰬟", VersionStatus.TooOld.Colorize("too old") } }; protected override void RenderWithCache(StringBuilder builder) diff --git a/src/TUI/Domain/Brand.cs b/src/TUI/Domain/Brand.cs index 0530a0b..f3422a6 100644 --- a/src/TUI/Domain/Brand.cs +++ b/src/TUI/Domain/Brand.cs @@ -1,8 +1,8 @@ using Pastel; -namespace TUI.Controls.Components; +namespace TUI.Domain; -public record Brand(string Name, string Logo, string Color) +public record Brand(string Name, string? Logo = null, string? Color = null) { - public string ColorLogo() => Logo.Pastel(Color); + public string ColorLogo() => Logo?.Pastel(Color) ?? string.Empty; }; \ No newline at end of file diff --git a/src/TUI/Domain/Dependency.cs b/src/TUI/Domain/Dependency.cs index 38ff60d..b29419a 100644 --- a/src/TUI/Domain/Dependency.cs +++ b/src/TUI/Domain/Dependency.cs @@ -2,4 +2,66 @@ using TUI.Controls.Components; namespace TUI.Domain; -public record Dependency(string Version, Brand Brand); \ No newline at end of file +public record Dependency() +{ + private readonly Version _current; + public readonly Brand Brand; + public VersionType Type { get; private set; } + + public string Version => $"{_current.Major}.{_current.Minor}.{_current.Patch}"; + + public Dependency(string version, Brand brand) : this() + { + _current = new Version(version); + Brand = brand; + } + + public VersionStatus Comparison(Dependency outerDependency) + { + // if (string.IsNullOrEmpty(Version) || string.IsNullOrEmpty(outerDependency.Version)) + // { + // return VersionStatus.NotFound; + // } + + var outer = outerDependency._current; + + Type = _current.Type; + + if (_current.Major < outer.Major) + { + return VersionStatus.TooOld; + } + + if (_current.Major > outer.Major) + { + return VersionStatus.ToNew; + } + + if (_current.Minor < outer.Minor) + { + return VersionStatus.BeNice; + } + + if (_current.Minor > outer.Minor) + { + return VersionStatus.ToNew; + } + + if (_current.Patch < outer.Patch) + { + return VersionStatus.BeNice; + } + + if (_current.Patch > outer.Patch) + { + return VersionStatus.ToNew; + } + + if (outer.Type != VersionType.Release) + { + return VersionStatus.ToNew; + } + + return VersionStatus.SoGood; + } +}; \ No newline at end of file diff --git a/src/TUI/Domain/Hub.cs b/src/TUI/Domain/Hub.cs index ff0a924..403d320 100644 --- a/src/TUI/Domain/Hub.cs +++ b/src/TUI/Domain/Hub.cs @@ -1,6 +1,3 @@ namespace TUI.Domain; -public record Hub -{ - -} \ No newline at end of file +public record Hub(string Origin, string Type); \ No newline at end of file diff --git a/src/TUI/Domain/Project.cs b/src/TUI/Domain/Project.cs index 1764c0b..c75be9f 100644 --- a/src/TUI/Domain/Project.cs +++ b/src/TUI/Domain/Project.cs @@ -1,12 +1,14 @@ namespace TUI.Domain; -public record Project(int Id, string Name, IEnumerable Tags, string Hub) +public record Project(int Id, string Name, IEnumerable Tags, Hub Hub) { private IEnumerable Dependencies => new List(); - + public bool IsPublicNetwork => Tags.Contains("public"); - + public bool HasAuth => Tags.Contains("auth"); - + public bool SeoDependent => Tags.Contains("seo"); + + public bool Legacy => Tags.Contains("legacy"); } \ No newline at end of file diff --git a/src/TUI/Domain/Version.cs b/src/TUI/Domain/Version.cs new file mode 100644 index 0000000..ed61736 --- /dev/null +++ b/src/TUI/Domain/Version.cs @@ -0,0 +1,32 @@ +using TUI.Controls.Components; + +namespace TUI.Domain; + +public class Version +{ + public readonly int Major; + public readonly int Minor; + public readonly int Patch; + public readonly VersionType Type; + + public Version(string version) + { + var parts = version.Split('.'); + + Major = Convert.ToInt32(parts[0].Replace("^", "").Replace("~", "")); + Minor = Convert.ToInt32(parts[1]); + Patch = Convert.ToInt32(string.Join("", parts[2].TakeWhile(char.IsDigit))); + + var extension = parts[2].Replace(Patch.ToString(), ""); + + Type = extension switch + { + not null when extension.Contains("rc") => VersionType.Candidate, + not null when extension.Contains("beta") => VersionType.Beta, + not null when extension.Contains("alpha") => VersionType.Alpha, + not null when extension.Contains("canary") => VersionType.Canary, + not null when extension.Contains("next") => VersionType.Next, + _ => VersionType.Release + }; + } +} \ No newline at end of file diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index 4820dc8..f2b7f5e 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -6,57 +6,97 @@ using TUI.Store; namespace TUI.Pages; +public record DependenciesState(HeaderContainer Header, DashboardContainer Dashboard, FooterContainer Footer); + public class DependenciesPage : PageBase { private DependenciesStore _store; - - public override void Render() + + private DependenciesState _state; + + public override void Initial() { - ICanvas canvas = new ConsoleCanvas(); - var header = new HeaderContainer(); var dashboard = new DashboardContainer(); var dependenciesHeader = new DependenciesContainer(); dependenciesHeader.AddTitleStub(); - + foreach (var conventionDependency in _store.ConventionDependencies) { dependenciesHeader.AddDependency(conventionDependency); } - + dashboard.AddChildren(dependenciesHeader); - + foreach (var project in _store.Projects) { - var projectDependencies = new DependenciesContainer(); + var projectDependencies = new DependenciesContainer(project); projectDependencies.AddTitle(new ProjectTitle(project)); dashboard.AddChildren(projectDependencies); } - + var breadCrumbs = new BreadCrumbsComponent(" Dependencies", "JavaScript"); var footer = new FooterContainer(breadCrumbs); - var layout = new DashboardLayout(header, dashboard, footer); - canvas.Draw(layout); - - // CommandLine = new CommandLine(); - // DependenciesView = new DependenciesView(); + + _state = new DependenciesState(header, dashboard, footer); } - + + public override void Render() + { + ICanvas canvas = new ConsoleCanvas(); + var layout = new DashboardLayout(_state.Header, _state.Dashboard, _state.Footer); + canvas.Draw(layout); + } + + public void LoadDependencies() + { + Initial(); + var projects = _state.Dashboard.GetContent(); + foreach (var projectDependencies in projects.Cast().Skip(1)) + { + if (projectDependencies is null) + { + continue; + } + + var project = projectDependencies.Project; + var actualDependencies = _store.ActualDependencies(project).ToArray(); + + foreach (var conventionDependency in _store.ConventionDependencies) + { + var actualDependency = actualDependencies.SingleOrDefault( + dependency => string.Equals(dependency.Brand.Name, conventionDependency.Brand.Name, + StringComparison.CurrentCultureIgnoreCase)); + + if (actualDependency is null) + { + projectDependencies.AddDependencyStub(); + continue; + } + + var versionType = actualDependency.Comparison(conventionDependency); + projectDependencies.AddDependency(actualDependency, versionType); + } + + Render(); + } + } + public override void Bind() { _store = new DependenciesStore(); _store.Bind(); } - + // private bool _commandLineInDisplay; - + // private ProjectDto _currentProjectDto; - + // private bool _headerInDisplay = true; - - + + // public string FocusedElement { get; set; } = ""; - + // public void OpenDeps(ProjectDto projectDto) // { // _currentProjectDto = projectDto; diff --git a/src/TUI/Pages/IPage.cs b/src/TUI/Pages/IPage.cs index 3a9b32a..13894e8 100644 --- a/src/TUI/Pages/IPage.cs +++ b/src/TUI/Pages/IPage.cs @@ -3,6 +3,7 @@ namespace TUI.Pages; interface IPage { void Open(); + void Initial(); void Render(); void Bind(); } \ No newline at end of file diff --git a/src/TUI/Pages/PageBase.cs b/src/TUI/Pages/PageBase.cs index 2dbce48..2c9e357 100644 --- a/src/TUI/Pages/PageBase.cs +++ b/src/TUI/Pages/PageBase.cs @@ -8,10 +8,13 @@ public abstract class PageBase : IPage { Debugger.Log(0, "Event", $"Open page ${GetType().UnderlyingSystemType.Name}\n"); Bind(); + Initial(); Render(); } - + + public abstract void Initial(); + public abstract void Render(); - + public abstract void Bind(); } \ No newline at end of file diff --git a/src/TUI/Pages/WelcomePage.cs b/src/TUI/Pages/WelcomePage.cs index 169c276..0c651d2 100644 --- a/src/TUI/Pages/WelcomePage.cs +++ b/src/TUI/Pages/WelcomePage.cs @@ -10,6 +10,10 @@ namespace TUI.Pages; public class WelcomePage : PageBase { + public override void Initial() + { + } + public override void Render() { ICanvas canvas = new ConsoleCanvas(); diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index 14e60b8..0f91ded 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -13,15 +13,24 @@ Thread.Sleep(500); var dependenciesPage = new DependenciesPage(); dependenciesPage.Open(); -var key = new ConsoleKeyInfo('1', ConsoleKey.NoName, false, false, false); + +ConsoleKeyInfo? key = null; + var waitCommand = true; do { - // if (key.Key == ConsoleKey.Q && !display.CommandLine.IsFocused) - // { - // waitCommand = false; - // continue; - // } + if (key?.Key == ConsoleKey.Q) + { + waitCommand = false; + continue; + } + + if (key?.Key == ConsoleKey.R) + { + dependenciesPage.LoadDependencies(); + key = null; + continue; + } // // if (display.CommandLine.IsFocused) // { @@ -58,7 +67,7 @@ do // break; // } // } - + key = Console.ReadKey(true); } while (waitCommand); diff --git a/src/TUI/Providers/Dependencies/DependencyRepository.cs b/src/TUI/Providers/Dependencies/DependencyRepository.cs index 80d5c91..d13627e 100644 --- a/src/TUI/Providers/Dependencies/DependencyRepository.cs +++ b/src/TUI/Providers/Dependencies/DependencyRepository.cs @@ -1,3 +1,5 @@ +using System.Text.Json; +using System.Text.Json.Nodes; using TUI.Controls.Components; using TUI.Domain; using YamlDotNet.Serialization; @@ -8,7 +10,7 @@ namespace TUI.Providers.Dependencies; public class DependencyRepository { private DependenciesDto? _dependenciesDto; - + private DependenciesDto DependenciesDto { get @@ -17,18 +19,18 @@ public class DependencyRepository { return _dependenciesDto; } - + var deserializer = new DeserializerBuilder() .WithNamingConvention(UnderscoredNamingConvention.Instance) .Build(); - + using var sr = new StreamReader("dependencies.yaml"); _dependenciesDto = deserializer.Deserialize(sr.ReadToEnd()); - + return _dependenciesDto; } } - + public IEnumerable ReadConventions(string stackName) { return DependenciesDto.Stacks @@ -40,22 +42,86 @@ public class DependencyRepository return new Dependency(convention.Version, brand); }); } - + public IEnumerable ReadProjects(string stackName) { var projects = new List(); - + var hubs = DependenciesDto.Stacks .Single(stack => stack.Name == stackName) .Hubs; - + foreach (var hub in hubs) { projects.AddRange(hub .Projects - .Select(proj => new Project(proj.Id, proj.Name, proj.Tags, hub.Type))); + .Select(proj => new Project(proj.Id, proj.Name, proj.Tags, new Hub(hub.Origin, hub.Type)))); } - + return projects; } -} \ No newline at end of file + + + public IEnumerable ReadActual(Project project) + { + var dependencies = new List(); + + if (project.Hub.Type == "gitlab") + { + var endpoint = GetGitlabEndpoint(project.Hub.Origin, project.Id); + using HttpClient client = new(); + var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); + + var packageJson = JsonSerializer.Deserialize(json); + + dependencies.AddRange(Map(packageJson?.Dependencies)); + dependencies.AddRange(Map(packageJson?.DevDependencies)); + dependencies.AddRange(Map(packageJson?.Engines)); + } + + return dependencies; + } + + private static string GetGitlabEndpoint(string origin, int projectId) + { + var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); + return $"{origin}/api/v4/projects/{projectId}/repository/files/package.json/raw?" + + $"private_token={token}&ref=dev"; + } + + private static IEnumerable Map(JsonObject? dependencies) + { + if (dependencies is null) + { + yield break; + } + + foreach (var dependency in dependencies) + { + var actualVersion = dependency.Value?.ToString(); + var brand = new Brand(dependency.Key); + + if (actualVersion is null) + { + continue; + } + + yield return new Dependency(actualVersion, brand); + } + } +} + + +// private static Package DownloadPackage(ProjectDto project) +// { +// // var endpoint = projectDto.Tags.Have("gitlab") ? GetGitlabEndpoint(projectDto) : projectDto.Repo; +// var endpoint = ""; +// if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; +// +// using HttpClient client = new(); +// var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); +// +// Packages.Add(endpoint, package); +// return package; +// } +// \ No newline at end of file diff --git a/src/TUI/Providers/Dependencies/Package.cs b/src/TUI/Providers/Dependencies/PackageJson.cs similarity index 92% rename from src/TUI/Providers/Dependencies/Package.cs rename to src/TUI/Providers/Dependencies/PackageJson.cs index 2fb82a9..30387aa 100644 --- a/src/TUI/Providers/Dependencies/Package.cs +++ b/src/TUI/Providers/Dependencies/PackageJson.cs @@ -4,7 +4,7 @@ using TUI.Engine; namespace TUI.Providers.Dependencies; -public class Package +public class PackageJson { [JsonPropertyName("dependencies")] public JsonObject? Dependencies { get; set; } @@ -14,20 +14,20 @@ public class Package [JsonPropertyName("engines")] public JsonObject? Engines { get; set; } - + public Version? ParseVersion(string? dependencyName) { if (dependencyName == null) return null; - + JsonNode? version = null; - + var lowerDependencyName = dependencyName.ToLower(); Dependencies?.TryGetPropertyValue(lowerDependencyName, out version); - + if (version == null) Engines?.TryGetPropertyValue(lowerDependencyName, out version); - + if (version == null) DevDependencies?.TryGetPropertyValue(lowerDependencyName, out version); - + return version?.GetValue().ToVersion(); } } \ No newline at end of file diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index 166f638..6c0c431 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,5 +1,6 @@ using TUI.Controls.Components; using TUI.Domain; +using TUI.Engine.Theme; using TUI.Providers.Dependencies; namespace TUI.Store; @@ -7,40 +8,31 @@ namespace TUI.Store; public class DependenciesStore { public IEnumerable ConventionDependencies; - + public IEnumerable Projects; - + + private DependencyRepository Repository = new(); + + public IEnumerable ActualDependencies(Project project) + { + SpeakerComponent.Instance.Shout("", $"Fetch actual dependencies for project {project.Name.Main()}"); + try + { + return Repository.ReadActual(project); + } + catch + { + SpeakerComponent.Instance.Shout("", $"Fetch failed for project{project.Name}"); + return new List(); + } + } + public void Bind() { - var repo = new DependencyRepository(); - - ConventionDependencies = repo.ReadConventions("javascript"); SpeakerComponent.Instance.Shout("🤔", "Prepare javascript conventions"); - - Projects = repo.ReadProjects("javascript"); + ConventionDependencies = Repository.ReadConventions("javascript"); + SpeakerComponent.Instance.Shout("🤩", "Prepare javascript projects"); + Projects = Repository.ReadProjects("javascript"); } - - // private readonly static Dictionary Packages = new(); - // - // private static Package DownloadPackage(ProjectDto projectDto) - // { - // // var endpoint = projectDto.Tags.Have("gitlab") ? GetGitlabEndpoint(projectDto) : projectDto.Repo; - // var endpoint = ""; - // if (Packages.TryGetValue(endpoint, out var downloadPackage)) return downloadPackage; - // - // using HttpClient client = new(); - // var json = client.GetStringAsync(endpoint).GetAwaiter().GetResult(); - // var package = JsonSerializer.Deserialize(json); - // Packages.Add(endpoint, package); - // return package; - // } - // - // private static string GetGitlabEndpoint(ProjectDto projectDto) - // { - // var token = Environment.GetEnvironmentVariable("TLD_GITLAB_PAT"); - // // return $"{projectDto.Repo}/api/v4/projects/{projectDto.ProjectId}/repository/files/package.json/raw?" + - // // $"private_token={token}&ref=dev"; - // return ""; - // } } \ No newline at end of file diff --git a/tests/TUI.Controls.Tests/VersionComponentTests.cs b/tests/TUI.Controls.Tests/VersionComponentTests.cs index 66111a5..e07d621 100644 --- a/tests/TUI.Controls.Tests/VersionComponentTests.cs +++ b/tests/TUI.Controls.Tests/VersionComponentTests.cs @@ -1,5 +1,6 @@ using FluentAssertions; using TUI.Controls.Components; +using TUI.Domain; using TUI.Engine.Attributes; using TUI.Engine.Components; @@ -9,19 +10,45 @@ namespace TUI.Engine.Tests { [Theory] [Trait("Category", nameof(Sketch))] - [InlineData(VersionType.Convention, "\u001b[38;2;132;186;100m10.12.33\u001b[0m")] - [InlineData(VersionType.BeNice, "\u001b[38;2;132;186;100m10.12.33\u001b[0m")] - [InlineData(VersionType.SoGood, "\u001b[38;2;113;121;126m10.12.33\u001b[0m")] - [InlineData(VersionType.ToNew, "\u001b[38;2;37;121;159m10.12.33\u001b[0m")] - [InlineData(VersionType.TooOld, "\u001b[38;2;236;151;6m10.12.33\u001b[0m")] - public void DrawSketchVersionTypes(VersionType versionType, string expected) + [InlineData(VersionStatus.BeNice, "\u001b[38;2;132;186;100m10.12.33\u001b[0m")] + [InlineData(VersionStatus.SoGood, "\u001b[38;2;113;121;126m10.12.33\u001b[0m")] + [InlineData(VersionStatus.ToNew, "\u001b[38;2;37;121;159m10.12.33\u001b[0m")] + [InlineData(VersionStatus.TooOld, "\u001b[38;2;236;151;6m10.12.33\u001b[0m")] + public void DrawSketchVersionTypes(VersionStatus versionStatus, string expected) { var brand = new Brand("Docker", "󰡨", "#1d63ed"); - var version = new VersionComponent(versionType, "10.12.33", brand); - + var version = new VersionComponent("10.12.33", brand, versionStatus); + var sketch = (version as IComponent).MakeSketch(new Size(10, 2)); - + sketch.ToString().Should().Be(expected); } + + [Theory] + [Trait("Category", nameof(Dependency))] + [InlineData("1.0.0", "0.0.1", VersionStatus.ToNew)] + [InlineData("1.0.0", "0.1.1", VersionStatus.ToNew)] + [InlineData("1.0.0", "0.1.0", VersionStatus.ToNew)] + [InlineData("1.2.0", "1.0.0", VersionStatus.ToNew)] + [InlineData("1.2.0", "1.0.1", VersionStatus.ToNew)] + [InlineData("1.2.0", "1.1.0", VersionStatus.ToNew)] + [InlineData("1.0.0", "1.0.0-rc", VersionStatus.ToNew)] + [InlineData("1.0.0", "1.0.0", VersionStatus.SoGood)] + [InlineData("^1.0.0", "1.0.0", VersionStatus.SoGood)] + [InlineData("1.2.0", "1.3.0", VersionStatus.BeNice)] + [InlineData("1.3.1", "1.3.3", VersionStatus.BeNice)] + [InlineData("1.2.0", "2.1.0", VersionStatus.TooOld)] + [InlineData("1.2.0", "2.0.1", VersionStatus.TooOld)] + [InlineData("1.2.0", "2.3.1", VersionStatus.TooOld)] + public void ComparisonDependencies(string actual, string convention, VersionStatus expectedType) + { + var brand = new Brand("Poker", "󱢢", "#1d63ed"); + var actualDependency = new Dependency(actual, brand); + var conventionDependency = new Dependency(convention, brand); + + var status = actualDependency.Comparison(conventionDependency); + + status.Should().Be(expectedType); + } } } \ No newline at end of file From d7d2fcd0a6e8ca25d4b94bc5fc316b0ef5de186c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 14 Jun 2024 16:45:30 +0500 Subject: [PATCH 21/23] =?UTF-8?q?=F0=9F=A5=85=20Catch=20error=20and=20rend?= =?UTF-8?q?er.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI.Engine/Symbols.cs | 2 ++ .../Controls/Components/VersionComponent.cs | 8 +++-- .../Controls/Components/VersionExtensions.cs | 28 ++++++++++++++++++ src/TUI/Controls/Components/VersionType.cs | 2 +- .../Components/VersionTypeExtensions.cs | 16 ---------- .../Containers/DependenciesContainer.cs | 18 +++++++++++- src/TUI/Pages/DependenciesPage.cs | 29 ++++++++++++------- src/TUI/Store/DependenciesStore.cs | 6 ++-- 8 files changed, 76 insertions(+), 33 deletions(-) create mode 100644 src/TUI/Controls/Components/VersionExtensions.cs delete mode 100644 src/TUI/Controls/Components/VersionTypeExtensions.cs diff --git a/src/TUI.Engine/Symbols.cs b/src/TUI.Engine/Symbols.cs index b88094e..654907f 100644 --- a/src/TUI.Engine/Symbols.cs +++ b/src/TUI.Engine/Symbols.cs @@ -18,6 +18,8 @@ public static class Symbols public const string Seo = "󰚩"; public const string Auth = ""; public const string NotFound = ""; + public const string Error = ""; + public const string Download = ""; public static class Lines { diff --git a/src/TUI/Controls/Components/VersionComponent.cs b/src/TUI/Controls/Components/VersionComponent.cs index 0f4408b..d8016d4 100644 --- a/src/TUI/Controls/Components/VersionComponent.cs +++ b/src/TUI/Controls/Components/VersionComponent.cs @@ -1,7 +1,9 @@ using System.Text; using TUI.Domain; +using TUI.Engine; using TUI.Engine.Attributes; using TUI.Engine.Components; +using TUI.Engine.Theme; namespace TUI.Controls.Components; @@ -25,16 +27,18 @@ public class VersionComponent : ComponentBase { var builder = new StringBuilder(); - // builder.Append(_type.ToString()); if (_brand is not null) { builder.Append(_brand.ColorLogo()); } + builder.Append(_type.ToImage().Warning()); + builder.Append(Symbols.Space); builder.Append(_version); var sketch = builder.ToString(); return new Sketch(_status.Colorize(sketch)); } -} \ No newline at end of file +} + diff --git a/src/TUI/Controls/Components/VersionExtensions.cs b/src/TUI/Controls/Components/VersionExtensions.cs new file mode 100644 index 0000000..5de4afa --- /dev/null +++ b/src/TUI/Controls/Components/VersionExtensions.cs @@ -0,0 +1,28 @@ +using TUI.Engine.Theme; + +namespace TUI.Controls.Components; + +public static class VersionExtensions +{ + public static string ToImage(this VersionType versionType) + => + versionType switch + { + VersionType.Alpha => "󰀫", + VersionType.Beta => "󰂡", + VersionType.Candidate => "󰑣", + VersionType.Canary => "󱗆", + VersionType.Next => "󰒭", + _ => "" + }; + + public static string Colorize(this VersionStatus versionStatus, string value) => + versionStatus switch + { + VersionStatus.TooOld => value.Warning(), + VersionStatus.ToNew => value.Info(), + VersionStatus.SoGood => value.Hint(), + VersionStatus.BeNice => value.Main(), + _ => value + }; +} \ No newline at end of file diff --git a/src/TUI/Controls/Components/VersionType.cs b/src/TUI/Controls/Components/VersionType.cs index 786c668..a7fac98 100644 --- a/src/TUI/Controls/Components/VersionType.cs +++ b/src/TUI/Controls/Components/VersionType.cs @@ -9,4 +9,4 @@ public enum VersionType Alpha, Beta, Next, -} \ No newline at end of file +} diff --git a/src/TUI/Controls/Components/VersionTypeExtensions.cs b/src/TUI/Controls/Components/VersionTypeExtensions.cs deleted file mode 100644 index 519815b..0000000 --- a/src/TUI/Controls/Components/VersionTypeExtensions.cs +++ /dev/null @@ -1,16 +0,0 @@ -using TUI.Engine.Theme; - -namespace TUI.Controls.Components; - -public static class VersionTypeExtensions -{ - public static string Colorize(this VersionStatus versionStatus, string value) => - versionStatus switch - { - VersionStatus.TooOld => value.Warning(), - VersionStatus.ToNew => value.Info(), - VersionStatus.SoGood => value.Hint(), - VersionStatus.BeNice => value.Main(), - _ => value - }; -} \ No newline at end of file diff --git a/src/TUI/Controls/Containers/DependenciesContainer.cs b/src/TUI/Controls/Containers/DependenciesContainer.cs index 23393c9..ecf373f 100644 --- a/src/TUI/Controls/Containers/DependenciesContainer.cs +++ b/src/TUI/Controls/Containers/DependenciesContainer.cs @@ -16,7 +16,7 @@ public class DependenciesContainer : ContainerBase { public readonly Project? Project; - private const int VersionColumnWidth = 10; + private const int VersionColumnWidth = 11; private const int TitleColumnWidth = 25; @@ -70,6 +70,22 @@ public class DependenciesContainer : ContainerBase _dependencies.Add(stub); } + public void AddError() + { + var size = new Size(25, 1); + var stub = new StubComponent(size, (Symbols.Error + Symbols.Space + " Something went wrong").Error()); + stub.SetPadding(Level.Normal); + stub.SetAlignment(Horizontal.Right); + stub.SetFixed(Orientation.Horizontal, 25); + + if (Project is not null && Project.Legacy) + { + stub.StyleContext = new StyleContext(Palette.DisableColor); + } + + _dependencies.Add(stub); + } + public void AddDependency(Dependency dependency, VersionStatus status = VersionStatus.BeNice) { var version = new VersionComponent(dependency.Version, dependency.Brand, status, dependency.Type); diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index f2b7f5e..c558011 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -62,20 +62,27 @@ public class DependenciesPage : PageBase var project = projectDependencies.Project; var actualDependencies = _store.ActualDependencies(project).ToArray(); - foreach (var conventionDependency in _store.ConventionDependencies) + if (!actualDependencies.Any()) { - var actualDependency = actualDependencies.SingleOrDefault( - dependency => string.Equals(dependency.Brand.Name, conventionDependency.Brand.Name, - StringComparison.CurrentCultureIgnoreCase)); - - if (actualDependency is null) + projectDependencies.AddError(); + } + else + { + foreach (var conventionDependency in _store.ConventionDependencies) { - projectDependencies.AddDependencyStub(); - continue; + var actualDependency = actualDependencies.SingleOrDefault( + dependency => string.Equals(dependency.Brand.Name, conventionDependency.Brand.Name, + StringComparison.CurrentCultureIgnoreCase)); + + if (actualDependency is null) + { + projectDependencies.AddDependencyStub(); + continue; + } + + var versionType = actualDependency.Comparison(conventionDependency); + projectDependencies.AddDependency(actualDependency, versionType); } - - var versionType = actualDependency.Comparison(conventionDependency); - projectDependencies.AddDependency(actualDependency, versionType); } Render(); diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index 6c0c431..8d4b8a9 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,5 +1,6 @@ using TUI.Controls.Components; using TUI.Domain; +using TUI.Engine; using TUI.Engine.Theme; using TUI.Providers.Dependencies; @@ -15,14 +16,15 @@ public class DependenciesStore public IEnumerable ActualDependencies(Project project) { - SpeakerComponent.Instance.Shout("", $"Fetch actual dependencies for project {project.Name.Main()}"); + SpeakerComponent.Instance.Shout(Symbols.Download.Info(), $"Fetch actual dependencies for project {project.Name.Main + ()}"); try { return Repository.ReadActual(project); } catch { - SpeakerComponent.Instance.Shout("", $"Fetch failed for project{project.Name}"); + SpeakerComponent.Instance.Shout(Symbols.Error.Error(), $"Fetch failed for project{project.Name}"); return new List(); } } From 044618e690d349b456c16b097d8114ee3bf9bbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 14 Jun 2024 17:05:05 +0500 Subject: [PATCH 22/23] =?UTF-8?q?=E2=9C=A8=20Do=20page=20singletones.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI/Pages/DependenciesPage.cs | 8 +++++- src/TUI/Pages/IPage.cs | 1 + src/TUI/Pages/PageBase.cs | 2 ++ src/TUI/Pages/WelcomePage.cs | 12 ++++++++- src/TUI/Program.cs | 43 +++++++++++++++++++------------ 5 files changed, 47 insertions(+), 19 deletions(-) diff --git a/src/TUI/Pages/DependenciesPage.cs b/src/TUI/Pages/DependenciesPage.cs index c558011..71b84f6 100644 --- a/src/TUI/Pages/DependenciesPage.cs +++ b/src/TUI/Pages/DependenciesPage.cs @@ -10,6 +10,12 @@ public record DependenciesState(HeaderContainer Header, DashboardContainer Dashb public class DependenciesPage : PageBase { + private DependenciesPage() + { + } + + public static DependenciesPage Instance { get; } = new(); + private DependenciesStore _store; private DependenciesState _state; @@ -48,7 +54,7 @@ public class DependenciesPage : PageBase canvas.Draw(layout); } - public void LoadDependencies() + public override void Load() { Initial(); var projects = _state.Dashboard.GetContent(); diff --git a/src/TUI/Pages/IPage.cs b/src/TUI/Pages/IPage.cs index 13894e8..61028ef 100644 --- a/src/TUI/Pages/IPage.cs +++ b/src/TUI/Pages/IPage.cs @@ -6,4 +6,5 @@ interface IPage void Initial(); void Render(); void Bind(); + void Load(); } \ No newline at end of file diff --git a/src/TUI/Pages/PageBase.cs b/src/TUI/Pages/PageBase.cs index 2c9e357..91aa0e7 100644 --- a/src/TUI/Pages/PageBase.cs +++ b/src/TUI/Pages/PageBase.cs @@ -12,6 +12,8 @@ public abstract class PageBase : IPage Render(); } + public abstract void Load(); + public abstract void Initial(); public abstract void Render(); diff --git a/src/TUI/Pages/WelcomePage.cs b/src/TUI/Pages/WelcomePage.cs index 0c651d2..a556b65 100644 --- a/src/TUI/Pages/WelcomePage.cs +++ b/src/TUI/Pages/WelcomePage.cs @@ -10,6 +10,12 @@ namespace TUI.Pages; public class WelcomePage : PageBase { + private WelcomePage() + { + } + + public static WelcomePage Instance { get; } = new(); + public override void Initial() { } @@ -30,7 +36,11 @@ public class WelcomePage : PageBase canvas.Draw(layout); } - + + public override void Load() + { + } + public override void Bind() { } diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index 0f91ded..682e0a6 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -4,14 +4,12 @@ Console.Clear(); Console.CursorVisible = false; -// var settings = Settings.Init(); - -var welcomePage = new WelcomePage(); +var welcomePage = WelcomePage.Instance; welcomePage.Open(); Thread.Sleep(500); -var dependenciesPage = new DependenciesPage(); -dependenciesPage.Open(); +IPage currentPage = DependenciesPage.Instance; +currentPage.Open(); ConsoleKeyInfo? key = null; @@ -19,19 +17,32 @@ ConsoleKeyInfo? key = null; var waitCommand = true; do { - if (key?.Key == ConsoleKey.Q) + switch (key?.Key) { - waitCommand = false; - continue; + case ConsoleKey.Q: + waitCommand = false; + break; + case ConsoleKey.R: + key = null; + currentPage.Load(); + break; + case ConsoleKey.D1: + key = null; + currentPage = DependenciesPage.Instance; + Console.Clear(); + currentPage.Render(); + break; + case ConsoleKey.D0: + key = null; + currentPage = WelcomePage.Instance; + Console.Clear(); + currentPage.Render(); + break; + default: + key = Console.ReadKey(true); + break; } - if (key?.Key == ConsoleKey.R) - { - dependenciesPage.LoadDependencies(); - key = null; - continue; - } - // // if (display.CommandLine.IsFocused) // { // switch (key.Key) @@ -67,8 +78,6 @@ do // break; // } // } - - key = Console.ReadKey(true); } while (waitCommand); Console.Clear(); \ No newline at end of file From a8bca447a2932dc4a2bb8dcd7bf49f3bd19daae3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BB=D0=B5=D0=BA=D1=81=D0=B0=D0=BD=D0=B4=D1=80=20?= =?UTF-8?q?=D0=9A=D0=BE=D0=BB=D0=BE=D1=81=D0=BE=D0=B2?= Date: Fri, 1 Nov 2024 17:38:32 +0500 Subject: [PATCH 23/23] =?UTF-8?q?=F0=9F=90=9B=20Fix=20bug.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/TUI/Program.cs | 39 +------------------ .../Dependencies/DependencyRepository.cs | 1 - src/TUI/Store/DependenciesStore.cs | 19 +++++---- 3 files changed, 13 insertions(+), 46 deletions(-) diff --git a/src/TUI/Program.cs b/src/TUI/Program.cs index 682e0a6..c5120cb 100644 --- a/src/TUI/Program.cs +++ b/src/TUI/Program.cs @@ -42,42 +42,7 @@ do key = Console.ReadKey(true); break; } - - // if (display.CommandLine.IsFocused) - // { - // switch (key.Key) - // { - // case ConsoleKey.Escape: - // display.CommandLine.IsFocused = false; - // break; - // default: - // Console.Write(key.KeyChar); - // - // break; - // } - // } - // else - // { - // switch (key.KeyChar) - // { - // case ':': - // display.OpenCommandLine(); - // break; - // } - // - // switch (key.Key) - // { - // case ConsoleKey.DownArrow: - // display.Next(); - // break; - // case ConsoleKey.UpArrow: - // display.Previous(); - // break; - // case ConsoleKey.E: - // display.Toggle(); - // break; - // } - // } } while (waitCommand); -Console.Clear(); \ No newline at end of file +Console.Clear(); +Console.CursorVisible = true; \ No newline at end of file diff --git a/src/TUI/Providers/Dependencies/DependencyRepository.cs b/src/TUI/Providers/Dependencies/DependencyRepository.cs index d13627e..45ac9d9 100644 --- a/src/TUI/Providers/Dependencies/DependencyRepository.cs +++ b/src/TUI/Providers/Dependencies/DependencyRepository.cs @@ -1,6 +1,5 @@ using System.Text.Json; using System.Text.Json.Nodes; -using TUI.Controls.Components; using TUI.Domain; using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; diff --git a/src/TUI/Store/DependenciesStore.cs b/src/TUI/Store/DependenciesStore.cs index 8d4b8a9..9d8c9d4 100644 --- a/src/TUI/Store/DependenciesStore.cs +++ b/src/TUI/Store/DependenciesStore.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using TUI.Controls.Components; using TUI.Domain; using TUI.Engine; @@ -9,31 +10,33 @@ namespace TUI.Store; public class DependenciesStore { public IEnumerable ConventionDependencies; - + public IEnumerable Projects; - + private DependencyRepository Repository = new(); - + public IEnumerable ActualDependencies(Project project) { - SpeakerComponent.Instance.Shout(Symbols.Download.Info(), $"Fetch actual dependencies for project {project.Name.Main - ()}"); + SpeakerComponent.Instance.Shout(Symbols.Download.Info(), + $"Fetch actual dependencies for project {project.Name.Main()}"); + try { return Repository.ReadActual(project); } - catch + catch(Exception ex) { + Debugger.Log(0, "error", ex.Message); SpeakerComponent.Instance.Shout(Symbols.Error.Error(), $"Fetch failed for project{project.Name}"); return new List(); } } - + public void Bind() { SpeakerComponent.Instance.Shout("🤔", "Prepare javascript conventions"); ConventionDependencies = Repository.ReadConventions("javascript"); - + SpeakerComponent.Instance.Shout("🤩", "Prepare javascript projects"); Projects = Repository.ReadProjects("javascript"); }