From 84c6e05c660516113f307ae2c41c9117710a734d Mon Sep 17 00:00:00 2001 From: Morgan <103436411+MorganKryze@users.noreply.github.com> Date: Tue, 12 Dec 2023 00:50:30 +0100 Subject: [PATCH] Added working Matrix class and docs --- docs/documentation/specific.md | 45 ++++- docs/documentation/started.md | 5 + docs/images/matrix.png | Bin 0 -> 83169 bytes example/Program.cs | 165 ++++++++++++----- src/ConsoleAppVisuals/Core.cs | 21 +++ src/ConsoleAppVisuals/Matrix.cs | 206 ++++++++++++++++++++++ src/ConsoleAppVisuals/Table.cs | 14 +- src/ConsoleAppVisuals/models/Placement.cs | 8 +- 8 files changed, 405 insertions(+), 59 deletions(-) create mode 100644 docs/images/matrix.png create mode 100644 src/ConsoleAppVisuals/Matrix.cs diff --git a/docs/documentation/specific.md b/docs/documentation/specific.md index 40803876..7092a4a8 100644 --- a/docs/documentation/specific.md +++ b/docs/documentation/specific.md @@ -87,7 +87,50 @@ students.UpdateLine(3, new () {"04", "Charles", "Computer Science", "55"}); You may also use the `SetRoundedCorners` method to set the rounded corners to true or false for the tables. ```csharp -Table.SetRoundedCorners(true); +students.SetRoundedCorners(true); +``` + +## Matrix display + +First, you need to create a `Matrix` object giving the data just as in the example below. + +```csharp +List firstRow = new() { 1, null, 2, 7, 9, 3 }; +List secondRow = new() { 4, 5, 6, 8, null, 2 }; +List thirdRow = new() { 7, 8, null, 3, 4, 5 }; +List fourthRow = new() { null, 2, 3, 4, 5, 6 }; +List> data = new() { firstRow, secondRow, thirdRow, fourthRow }; +Matrix matrix = new(data); +``` + +The `WriteMatrix` is a special block that allows you to display the matrix. This is only visual, you can't select any element. + +```csharp +matrix.WriteMatrix(Placement.Center); + +Console.ReadKey(); +``` + +![matrix](../images/matrix.png) + +> [!NOTE] +> Once you created the matrix, you can add, remove or update the lines using the methods provided by the `Matrix` class (`AddLine`, `RemoveLine`, `UpdateLine`) but also the elements using the `RemoveElement` and `UpdateElement` methods. + +Here is an example of a matrix of how to use them: + +```csharp + +matrix.AddLine(new () {2, 5, 7, 9, 3, 6}); +matrix.RemoveLine(3); +matrix.UpdateLine(2, new () {3, 6, 8, 9, null, 2}); +matrix.RemoveElement(new Position(2, 2)); +matrix.UpdateElement(new Position(3,1), 7); +``` + +You may also use the `SetRoundedCorners` method to set the rounded corners to true or false for the matrix. + +```csharp +matrix.SetRoundedCorners(true); ``` ## Loading bar diff --git a/docs/documentation/started.md b/docs/documentation/started.md index f739aab6..a730689f 100644 --- a/docs/documentation/started.md +++ b/docs/documentation/started.md @@ -33,6 +33,7 @@ ConsoleAppVisuals │ └───FontYamlFile.cs ├───Core.cs ├───Extensions.cs +├───Matrix.cs ├───Table.cs ├───TextStyler.cs └───Usings.cs @@ -60,6 +61,10 @@ This class is used to style the text. It contains the methods to apply a specifi This class is used to create a table. It may be useful to display data in a table on the screen. +### Matrix.cs + +This class is used to create a matrix. It may be useful to display data in a matrix on the screen. + ### Position.cs This class is used to define any position defined by an X and Y coordinate. It may be used in cases like matrix selectors for example. diff --git a/docs/images/matrix.png b/docs/images/matrix.png new file mode 100644 index 0000000000000000000000000000000000000000..4cbf2eb7714a056c817c38072363e93f52d02a44 GIT binary patch literal 83169 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 hbJxjzz^RONiBmDdB<&W{{_1ggRKAn literal 0 HcmV?d00001 diff --git a/example/Program.cs b/example/Program.cs index abe56336..7aa24644 100644 --- a/example/Program.cs +++ b/example/Program.cs @@ -9,12 +9,12 @@ static void Main() Console.Clear(); Console.CursorVisible = false; - Test(); + Debugging(); Core.SetTitle("Example"); Core.WriteTitle(); - Core.WriteHeader(true); - Core.WriteFooter(true); + Core.WriteHeader(false); + Core.WriteFooter(false); Core.ClearContent(); Core.LoadingBar("[ Some example loading... ]"); Core.UpdateScreen(); @@ -22,46 +22,22 @@ static void Main() Menu: - var index = Core.ScrollingMenuSelector("What do you want to do?", default, default, "Select a number", "Answer some prompt","Display trivia", "Display table", "Change color", "Quit the app"); - switch (index.Item1){ + var index = Core.ScrollingMenuSelector("What will be your next action?", default, default, + "Change Console color", + "Display paragraph", + "Display a styled text", + "Display a matrix", + "Answer some prompt", + "Select a number", + "Display table", + "Quit the app"); + Core.ClearContent(); + switch (index.Item1) + { case Output.Select: - switch (index.Item2){ + switch (index.Item2) + { case 0: - Core.ClearContent(); - Core.UpdateScreen(); - var answerNumber = Core.ScrollingNumberSelector("Select a number", 10, 50, 25, 5); - float number = answerNumber.Item2; - Core.ClearContent(); - break; - case 1: - Core.ClearContent(); - Core.UpdateScreen(); - var answerPrompt = Core.WritePrompt("Hey! What is your name?"); - string name = answerPrompt.Item2; - Core.ClearContent(); - break; - case 2: - Core.ClearContent(); - Core.UpdateScreen(); - Core.WriteParagraph(default, default, "C# is a general-purpose, multi-paradigm programming language encompassing strong typing,","lexically scoped, imperative, declarative, functional, generic, object-oriented (class-based),"," and component-oriented programming disciplines.", "", "Press [Enter] to continue..."); - Console.ReadKey(); - Core.ClearContent(); - break; - case 3: - Core.ClearContent(); - Core.UpdateScreen(); - List headers = new () {"id", "name", "major", "grades"}; - List student1 = new () {"01", "Theo", "Technology", "97"}; - List student2 = new () {"02", "Paul", "Mathematics", "86"}; - List student3 = new () {"03", "Maxime", "Physics", "92"}; - List student4 = new () {"04", "Charles", "Computer Science", "100"}; - Table students = new (headers, new () {student1, student2, student3, student4}); - students.SetRoundedCorners(true); - students.ScrollingTableSelector(true, false, "Add student"); - Core.ClearContent(); - break; - case 4: - Core.ClearContent(); Core.UpdateScreen(); var indexColor = Core.ScrollingMenuSelector("What color do you want to change?", default, default, "White", "Gray", "Red", "Green", "Blue", "Yellow", "Magenta", "Cyan"); switch(indexColor.Item2){ @@ -92,38 +68,133 @@ static void Main() default: break; } + Core.ClearContent(); + break; + + case 1: Core.UpdateScreen(); + + Core.WriteMultiplePositionedLines(default, default, default, "C# is a general-purpose, multi-paradigm programming language encompassing strong typing,","lexically scoped, imperative, declarative, functional, generic, object-oriented (class-based),"," and component-oriented programming disciplines.", "", "Press [Enter] to continue..."); + + Console.ReadKey(); + Core.ClearContent(); break; - default: + + case 2: + Core.UpdateScreen(); + + Core.WritePositionedStyledText(Core.StyleText("Hello World!")); + + Console.ReadKey(); + Core.ClearContent(); + + Core.WritePositionedStyledText(Core.StyleText("Welcome Aboard!")); + + Console.ReadKey(); Core.ClearContent(); + break; + + case 3: Core.UpdateScreen(); - Core.WriteParagraph(true, default, "You have selected to quit the app. Press [Enter] to continue..."); + + List firstRow = new() { 1, null, 2, 7, 9, 3 }; + List secondRow = new() { 4, 5, 6, 8, null, 2 }; + List thirdRow = new() { 7, 8, null, 3, 4, 5 }; + List fourthRow = new() { null, 2, 3, 4, 5, 6 }; + List> data = new() { firstRow, secondRow, thirdRow, fourthRow }; + Matrix matrix = new(data); + matrix.SetRoundedCorners(false); + matrix.WriteMatrix(Placement.Center); + + Console.ReadKey(); + Core.ClearContent(); + + matrix.Remove(new Position(0, 0)); + matrix.Remove(new Position(3, 5)); + matrix.WriteMatrix(Placement.Center); + + Console.ReadKey(); + Core.ClearContent(); + + matrix.UpdateElement(new Position(0, 0), 1); + matrix.UpdateElement(new Position(3, 5), 6); + matrix.WriteMatrix(Placement.Center); + Console.ReadKey(); + Core.ClearContent(); + break; + + case 4: + Core.UpdateScreen(); + + var answerPrompt = Core.WritePrompt("Hey! What is your name?", "Theo"); + string name = answerPrompt.Item2; + + Core.ClearContent(); + break; + case 5: + Core.UpdateScreen(); + + var answerNumber = Core.ScrollingNumberSelector("Select a number", 10, 50, 25, 5); + float number = answerNumber.Item2; + + Core.ClearContent(); + break; + case 6: + Core.UpdateScreen(); + + List headers = new () {"id", "name", "major", "grades"}; + List student1 = new () {"01", "Theo", "Technology", "97"}; + List student2 = new () {"02", "Paul", "Mathematics", "86"}; + List student3 = new () {"03", "Maxime", "Physics", "92"}; + List student4 = new () {"04", "Charles", "Computer Science", "100"}; + Table students = new (headers, new () {student1, student2, student3, student4}); + students.SetRoundedCorners(false); + students.ScrollingTableSelector(true, false, "Add student"); + + students.UpdateLine(0, new () {"01", "Theo", "Biology", "100"}); + students.RemoveLine(3); + students.ScrollingTableSelector(true, true); + + Core.ClearContent(); + break; + + default: + Core.ClearContent(); + Core.UpdateScreen(); + Core.ExitProgram(); break; } break; + case Output.Exit: Core.ClearContent(); Core.UpdateScreen(); - Core.WriteParagraph(true, default, "You have selected to quit the app. Press [Enter] to continue..."); + + Core.WriteMultiplePositionedLines(default, true, default, "You have selected to quit the app. Press [Enter] to continue..."); + Console.ReadKey(); Core.ExitProgram(); break; + case Output.Delete: Core.ClearContent(); Core.UpdateScreen(); - Core.WriteParagraph(true, default, "You have selected the backspace tile. Press [Enter] to continue..."); + + Core.WriteMultiplePositionedLines(default, true, default, "You have selected the backspace tile. Press [Enter] to continue..."); + Console.ReadKey(); break; + default: break; } goto Menu; } - public static void Test() + public static void Debugging() { - // Test code placeholder + // Debug code placeholder } } } \ No newline at end of file diff --git a/src/ConsoleAppVisuals/Core.cs b/src/ConsoleAppVisuals/Core.cs index 1df88d44..412ed954 100644 --- a/src/ConsoleAppVisuals/Core.cs +++ b/src/ConsoleAppVisuals/Core.cs @@ -339,6 +339,7 @@ public static void WriteFooter(bool continuous = true, (string, string, string)? /// If true, the paragraph is printed in the negative colors. /// The height of the paragraph. /// The lines of the paragraph. + [Obsolete("This method is deprecated. Use WriteParagraph with the placement attribute instead. This method will be removed in a future release.", true)] public static void WriteParagraph(bool negative = false, int? line = null, params string[] text) { line ??= ContentHeight; @@ -352,6 +353,26 @@ public static void WriteParagraph(bool negative = false, int? line = null, param } ApplyNegative(default); } + ///

+ /// This method prints a paragraph in the console. + /// + /// The placement of the paragraph. + /// If true, the paragraph is printed in the negative colors. + /// The height of the paragraph. + /// The lines of the paragraph. + public static void WriteMultiplePositionedLines(Placement placement = Placement.Center , bool negative = false, int? line = null, params string[] text) + { + line ??= ContentHeight; + ApplyNegative(negative); + int maxLength = text.Length > 0 ? text.Max(s => s.Length) : 0; + foreach (string str in text) + { + WritePositionedString(str.ResizeString(maxLength, placement), placement, negative, line++); + if (line >= Console.WindowHeight - 1) + break; + } + ApplyNegative(default); + } /// /// This method prints a message in the console and gets a string written by the user. /// diff --git a/src/ConsoleAppVisuals/Matrix.cs b/src/ConsoleAppVisuals/Matrix.cs new file mode 100644 index 00000000..3acf77c8 --- /dev/null +++ b/src/ConsoleAppVisuals/Matrix.cs @@ -0,0 +1,206 @@ +namespace ConsoleAppVisuals; +/// +/// A maxtrix class for the console. +/// +public class Matrix +{ + + private List> lines = new(); + private string[]? displayArray; + private bool roundedCorners = true; + /// + /// The natural constructor of the matrix. + /// + /// The matrix to be used. + /// Thrown when the matrix is empty or not compatible (lines are not of the same length). + public Matrix(List>? rawLines = null) + { + if (rawLines is not null) + { + lines = rawLines; + if (CompatibilityCheck()) + { + BuildMatrix(); + } + } + } + private bool CompatibilityCheck() + { + if (lines.Count == 0) + { + return false; + throw new ArgumentException("The matrix is empty."); + } + int firstRowLength = lines[0].Count; + for (int i = 1; i < lines.Count; i++) + { + if (lines[i].Count != firstRowLength) + { + return false; + throw new ArgumentException("The matrix is not compatible."); + } + } + return true; + } + private void BuildMatrix() + { + var stringList = new List(); + var localMax = new int[lines[0].Count]; // Assuming rawLines is a List> containing the grid data + + for (int i = 0; i < lines.Count; i++) + { + for (int j = 0; j < lines[i].Count; j++) + { + if (lines[i][j]?.ToString()?.Length > localMax[j]) + { + localMax[j] = lines[i][j]?.ToString()?.Length ?? 0; + } + } + } + + string border = Corners[0].ToString(); + for (int i = 0; i < lines[0].Count; i++) + { + border += new string('─', localMax[i] + 2); + border += (i != lines[0].Count - 1) ? "┬" : Corners[1].ToString(); + } + stringList.Add(border); + + var separator = "├"; + for (int i = 0; i < lines[0].Count; i++) + { + separator += new string('─', localMax[i] + 2); + separator += (i != lines[0].Count - 1) ? "┼" : "┤"; + } + + + for (int i = 0; i < lines.Count; i++) + { + string line = "│ "; + for (int j = 0; j < lines[i].Count; j++) + { + line += lines[i][j]?.ToString()?.PadRight(localMax[j]) ?? " ".PadRight(localMax[j]); + if (j != lines[i].Count - 1) + line += " │ "; + else + line += " │"; + } + stringList.Add(line); + if (i != lines.Count - 1) + stringList.Add(separator); + } + + border = Corners[2].ToString(); + for (int i = 0; i < lines[0].Count; i++) + { + border += new string('─', localMax[i] + 2); + border += (i != lines[0].Count - 1) ? "┴" : Corners[3].ToString(); + } + stringList.Add(border); + + displayArray = stringList.ToArray(); + } + private string Corners => roundedCorners ? "╭╮╰╯" : "┌┐└┘"; + /// + /// Toggles the rounded corners of the table. + /// + public void SetRoundedCorners(bool value = true) + { + roundedCorners = value; + BuildMatrix(); + } + + /// + /// Adds a line to the matrix. + /// + /// The line to add. + /// Thrown when the line is not of the same length as the other lines. + public void AddLine(List line) + { + if (lines.Count == 0) + { + lines.Add(line); + } + else if (line.Count != lines[0].Count) + { + throw new ArgumentException("Line has a different number of elements than the existing lines."); + } + else + { + lines.Add(line); + BuildMatrix(); + } + } + /// + /// Removes a line from the matrix. + /// + /// The index of the line to remove. + /// Thrown when the index is out of range. + public void RemoveLine(int index) + { + if (index < 0 || index >= lines.Count) + { + throw new IndexOutOfRangeException("Index is out of range."); + } + lines.RemoveAt(index); + BuildMatrix(); + } + /// + /// Updates a line in the matrix. + /// + /// The index of the line to update. + /// The new line. + /// Thrown when the index is out of range. + /// Thrown when the line is not of the same length as the other lines. + public void UpdateLine(int index, List line) + { + if (index < 0 || index >= lines.Count) + { + throw new IndexOutOfRangeException("Index is out of range."); + } + else if (line.Count != lines[0].Count) + { + throw new ArgumentException("Line has a different number of elements than the existing lines."); + } + lines[index] = line; + BuildMatrix(); + } + /// + /// Removes an element from the matrix. + /// + /// The position of the element to remove. + /// Thrown when the position is out of range. + public void Remove(Position position) + { + if (position.X >= lines.Count || position.Y >= lines[position.X].Count) + { + throw new IndexOutOfRangeException("Position is out of range."); + } + lines[position.X][position.Y] = default(T); + BuildMatrix(); + } + /// + /// Updates an element in the matrix. + /// + /// The position of the element to update. + /// The new element. + /// Thrown when the position is out of range. + public void UpdateElement(Position position, T newElement) + { + if (position.X >= lines.Count || position.Y >= lines[position.X].Count) + { + throw new IndexOutOfRangeException("Position is out of range."); + } + lines[position.X][position.Y] = newElement; + BuildMatrix(); + } + /// + /// Writes the matrix instance to the console. + /// + public void WriteMatrix(Placement placement = Placement.Center, bool negative = false, int? line = null) + { + if (displayArray is null) + throw new NullReferenceException("The matrix has not been built yet. The matrix cannot be displayed"); + Core.WriteMultiplePositionedLines(placement, negative, line, displayArray); + } +} \ No newline at end of file diff --git a/src/ConsoleAppVisuals/Table.cs b/src/ConsoleAppVisuals/Table.cs index 99bd1051..7d19bf86 100644 --- a/src/ConsoleAppVisuals/Table.cs +++ b/src/ConsoleAppVisuals/Table.cs @@ -77,8 +77,8 @@ private void BuildTable() } stringList.Add(line); } - stringList.Insert(0, corners[0].ToString().PadRight(stringList[0].Length - 1, '─') + corners[1]); - stringList.Add(corners[2].ToString().PadRight(stringList[0].Length - 1, '─') + corners[3]); + stringList.Insert(0, Corners[0].ToString().PadRight(stringList[0].Length - 1, '─') + Corners[1]); + stringList.Add(Corners[2].ToString().PadRight(stringList[0].Length - 1, '─') + Corners[3]); displayArray = stringList.ToArray(); } @@ -105,11 +105,11 @@ private void BuildTable() } stringList.Add(header); - string border = corners[0].ToString(); + string border = Corners[0].ToString(); for (int i = 0; i < rawHeaders.Count; i++) { border += new string('─', localMax[i] + 2); - border += (i != rawHeaders.Count - 1) ? "┬" : corners[1].ToString(); + border += (i != rawHeaders.Count - 1) ? "┬" : Corners[1].ToString(); } stringList.Insert(0, border); @@ -135,11 +135,11 @@ private void BuildTable() stringList.Add(line); } - border = corners[2].ToString(); + border = Corners[2].ToString(); for (int i = 0; i < rawHeaders.Count; i++) { border += new string('─', localMax[i] + 2); - border += (i != rawHeaders.Count - 1) ? "┴" : corners[3].ToString(); + border += (i != rawHeaders.Count - 1) ? "┴" : Corners[3].ToString(); } stringList.Add(border); @@ -149,7 +149,7 @@ private void BuildTable() #endregion #region Properties - private string corners => roundedCorners ? "╭╮╰╯" : "┌┐└┘"; + private string Corners => roundedCorners ? "╭╮╰╯" : "┌┐└┘"; /// /// Toggles the rounded corners of the table. /// diff --git a/src/ConsoleAppVisuals/models/Placement.cs b/src/ConsoleAppVisuals/models/Placement.cs index ee1114ef..bb3b1934 100644 --- a/src/ConsoleAppVisuals/models/Placement.cs +++ b/src/ConsoleAppVisuals/models/Placement.cs @@ -9,15 +9,15 @@ namespace ConsoleAppVisuals; /// public enum Placement { - /// - /// The string is placed at the left of the console. - /// - Left, /// /// The string is placed at the center of the console. /// Center, /// + /// The string is placed at the left of the console. + /// + Left, + /// /// The string is placed at the right of the console. /// Right