mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-10-31 17:15:28 +08:00 
			
		
		
		
	 Patrik Svensson
					Patrik Svensson
				
			
				
					committed by
					
						 Patrik Svensson
						Patrik Svensson
					
				
			
			
				
	
			
			
			 Patrik Svensson
						Patrik Svensson
					
				
			
						parent
						
							effdecb1d4
						
					
				
				
					commit
					8a01b93aca
				
			| @@ -1,4 +1,3 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace GridExample | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace PanelExample | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| using System; | ||||
| using Spectre.Console; | ||||
|  | ||||
| namespace TableExample | ||||
| @@ -12,6 +11,42 @@ namespace TableExample | ||||
|  | ||||
|             // A big table | ||||
|             RenderBigTable(); | ||||
|  | ||||
|             // A complex table | ||||
|             RenderComplexTable(); | ||||
|         } | ||||
|  | ||||
|         private static void RenderComplexTable() | ||||
|         { | ||||
|             // Create simple table. | ||||
|             var simple = new Table { Border = BorderKind.Rounded }; | ||||
|             simple.AddColumn(new TableColumn("[u]Foo[/]").Centered()); | ||||
|             simple.AddColumn(new TableColumn("[u]Bar[/]")); | ||||
|             simple.AddColumn(new TableColumn("[u]Baz[/]")); | ||||
|             simple.AddRow("Hello", "[red]World![/]", ""); | ||||
|             simple.AddRow("[blue]Bounjour[/]", "[white]le[/]", "[red]monde![/]"); | ||||
|             simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); | ||||
|  | ||||
|             // Create other table. | ||||
|             var second = new Table { Border = BorderKind.Square }; | ||||
|             second.AddColumn(new TableColumn("[u]Foo[/]")); | ||||
|             second.AddColumn(new TableColumn("[u]Bar[/]")); | ||||
|             second.AddColumn(new TableColumn("[u]Baz[/]")); | ||||
|             second.AddRow("Hello", "[red]World![/]", ""); | ||||
|             second.AddRow(simple, new Text("Whaaat"), new Text("Lolz")); | ||||
|             second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", ""); | ||||
|  | ||||
|             var table = new Table { Border = BorderKind.Rounded }; | ||||
|             table.AddColumn(new TableColumn(new Panel("[u]Foo[/]"))); | ||||
|             table.AddColumn(new TableColumn(new Panel("[u]Bar[/]"))); | ||||
|             table.AddColumn(new TableColumn(new Panel("[u]Baz[/]"))); | ||||
|  | ||||
|             // Add some rows | ||||
|             table.AddRow(new Text("Hello").Centered(), new Markup("[red]World![/] 🌍"), Text.Empty); | ||||
|             table.AddRow(second, new Text("Whaaat"), new Text("Lol")); | ||||
|             table.AddRow(new Markup("[blue]Hej[/]").Centered(), new Markup("[yellow]Världen![/]"), Text.Empty); | ||||
|  | ||||
|             AnsiConsole.Render(table); | ||||
|         } | ||||
|  | ||||
|         private static void RenderSimpleTable() | ||||
|   | ||||
| @@ -81,3 +81,6 @@ dotnet_diagnostic.RCS1079.severity = warning | ||||
|  | ||||
| # RCS1057: Add empty line between declarations. | ||||
| dotnet_diagnostic.RCS1057.severity = none | ||||
|  | ||||
| # IDE0004: Remove Unnecessary Cast | ||||
| dotnet_diagnostic.IDE0004.severity = warning | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| using Shouldly; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Rendering; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
|   | ||||
| @@ -125,8 +125,7 @@ namespace Spectre.Console.Tests.Unit | ||||
|  | ||||
|             // When | ||||
|             console.Render( | ||||
|                 new Panel( | ||||
|                     new Text("Hello World").WithAlignment(Justify.Right)) | ||||
|                 new Panel(new Text("Hello World").RightAligned()) | ||||
|                 { | ||||
|                     Expand = true, | ||||
|                 }); | ||||
| @@ -146,8 +145,7 @@ namespace Spectre.Console.Tests.Unit | ||||
|  | ||||
|             // When | ||||
|             console.Render( | ||||
|                 new Panel( | ||||
|                     new Text("Hello World").WithAlignment(Justify.Center)) | ||||
|                 new Panel(new Text("Hello World").Centered()) | ||||
|                 { | ||||
|                     Expand = true, | ||||
|                 }); | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| using Shouldly; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Rendering; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
|   | ||||
| @@ -59,7 +59,21 @@ namespace Spectre.Console.Tests.Unit | ||||
|         public sealed class TheAddRowMethod | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Rows_Are_Null() | ||||
|             public void Should_Throw_If_String_Rows_Are_Null() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|  | ||||
|                 // When | ||||
|                 var result = Record.Exception(() => table.AddRow((string[])null)); | ||||
|  | ||||
|                 // Then | ||||
|                 result.ShouldBeOfType<ArgumentNullException>() | ||||
|                     .ParamName.ShouldBe("columns"); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Throw_If_Renderable_Rows_Are_Null() | ||||
|             { | ||||
|                 // Given | ||||
|                 var table = new Table(); | ||||
|   | ||||
| @@ -1,87 +1,81 @@ | ||||
| using System.Text; | ||||
| using Shouldly; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Rendering; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     public sealed class TextTests | ||||
|     { | ||||
|         public sealed class Measuring | ||||
|         [Fact] | ||||
|         public void Should_Consider_The_Longest_Word_As_Minimum_Width() | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Return_The_Longest_Word_As_Minimum_Width() | ||||
|             { | ||||
|                 var text = new Text("Foo Bar Baz\nQux\nLol mobile"); | ||||
|             var text = new Text("Foo Bar Baz\nQux\nLol mobile"); | ||||
|  | ||||
|                 var result = text.Measure(new RenderContext(Encoding.Unicode, false), 80); | ||||
|             var result = ((IRenderable)text).Measure(new RenderContext(Encoding.Unicode, false), 80); | ||||
|  | ||||
|                 result.Min.ShouldBe(6); | ||||
|             } | ||||
|  | ||||
|             [Fact] | ||||
|             public void Should_Return_The_Longest_Line_As_Maximum_Width() | ||||
|             { | ||||
|                 var text = new Text("Foo Bar Baz\nQux\nLol mobile"); | ||||
|  | ||||
|                 var result = text.Measure(new RenderContext(Encoding.Unicode, false), 80); | ||||
|  | ||||
|                 result.Max.ShouldBe(11); | ||||
|             } | ||||
|             result.Min.ShouldBe(6); | ||||
|         } | ||||
|  | ||||
|         public sealed class Rendering | ||||
|         [Fact] | ||||
|         public void Should_Consider_The_Longest_Line_As_Maximum_Width() | ||||
|         { | ||||
|             [Fact] | ||||
|             public void Should_Render_Unstyled_Text_As_Expected() | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new PlainConsole(width: 80); | ||||
|                 var text = new Text("Hello World"); | ||||
|             var text = new Text("Foo Bar Baz\nQux\nLol mobile"); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Render(text); | ||||
|             var result = ((IRenderable)text).Measure(new RenderContext(Encoding.Unicode, false), 80); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output | ||||
|                     .NormalizeLineEndings() | ||||
|                     .ShouldBe("Hello World"); | ||||
|             } | ||||
|             result.Max.ShouldBe(11); | ||||
|         } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData("Hello\n\nWorld\n\n")] | ||||
|             [InlineData("Hello\r\n\r\nWorld\r\n\r\n")] | ||||
|             public void Should_Write_Line_Breaks(string input) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new PlainConsole(width: 5); | ||||
|                 var text = new Text(input); | ||||
|         [Fact] | ||||
|         public void Should_Render_Unstyled_Text_As_Expected() | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new PlainConsole(width: 80); | ||||
|             var text = new Text("Hello World"); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Render(text); | ||||
|             // When | ||||
|             fixture.Render(text); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.RawOutput.ShouldBe("Hello\n\nWorld\n\n"); | ||||
|             } | ||||
|             // Then | ||||
|             fixture.Output | ||||
|                 .NormalizeLineEndings() | ||||
|                 .ShouldBe("Hello World"); | ||||
|         } | ||||
|  | ||||
|             [Theory] | ||||
|             [InlineData(5, "Hello World", "Hello\nWorld")] | ||||
|             [InlineData(10, "Hello Sweet Nice World", "Hello \nSweet Nice\nWorld")] | ||||
|             public void Should_Split_Unstyled_Text_To_New_Lines_If_Width_Exceeds_Console_Width( | ||||
|                 int width, string input, string expected) | ||||
|             { | ||||
|                 // Given | ||||
|                 var fixture = new PlainConsole(width); | ||||
|                 var text = new Text(input); | ||||
|         [Theory] | ||||
|         [InlineData("Hello\n\nWorld\n\n")] | ||||
|         [InlineData("Hello\r\n\r\nWorld\r\n\r\n")] | ||||
|         public void Should_Write_Line_Breaks(string input) | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new PlainConsole(width: 5); | ||||
|             var text = new Text(input); | ||||
|  | ||||
|                 // When | ||||
|                 fixture.Render(text); | ||||
|             // When | ||||
|             fixture.Render(text); | ||||
|  | ||||
|                 // Then | ||||
|                 fixture.Output | ||||
|                     .NormalizeLineEndings() | ||||
|                     .ShouldBe(expected); | ||||
|             } | ||||
|             // Then | ||||
|             fixture.RawOutput.ShouldBe("Hello\n\nWorld\n\n"); | ||||
|         } | ||||
|  | ||||
|         [Theory] | ||||
|         [InlineData(5, "Hello World", "Hello\nWorld")] | ||||
|         [InlineData(10, "Hello Sweet Nice World", "Hello \nSweet Nice\nWorld")] | ||||
|         public void Should_Split_Unstyled_Text_To_New_Lines_If_Width_Exceeds_Console_Width( | ||||
|             int width, string input, string expected) | ||||
|         { | ||||
|             // Given | ||||
|             var fixture = new PlainConsole(width); | ||||
|             var text = new Text(input); | ||||
|  | ||||
|             // When | ||||
|             fixture.Render(text); | ||||
|  | ||||
|             // Then | ||||
|             fixture.Output | ||||
|                 .NormalizeLineEndings() | ||||
|                 .ShouldBe(expected); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|   | ||||
| @@ -1,27 +0,0 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="Text"/>. | ||||
|     /// </summary> | ||||
|     public static class TextExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets the text alignment. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The <see cref="Text"/> instance.</param> | ||||
|         /// <param name="alignment">The text alignment.</param> | ||||
|         /// <returns>The same <see cref="Text"/> instance.</returns> | ||||
|         public static Text WithAlignment(this Text text, Justify alignment) | ||||
|         { | ||||
|             if (text is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(text)); | ||||
|             } | ||||
|  | ||||
|             text.Alignment = alignment; | ||||
|             return text; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|   | ||||
							
								
								
									
										61
									
								
								src/Spectre.Console/Rendering/AlignableExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/Spectre.Console/Rendering/AlignableExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,61 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="IAlignable"/>. | ||||
|     /// </summary> | ||||
|     public static class AlignableExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Sets the alignment for an <see cref="IAlignable"/> object. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The alignable type.</typeparam> | ||||
|         /// <param name="alignable">The alignable object.</param> | ||||
|         /// <param name="alignment">The alignment.</param> | ||||
|         /// <returns>The same alignable object.</returns> | ||||
|         public static T WithAlignment<T>(this T alignable, Justify alignment) | ||||
|             where T : IAlignable | ||||
|         { | ||||
|             alignable.Alignment = alignment; | ||||
|             return alignable; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the <see cref="IAlignable"/> object to be left aligned. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The alignable type.</typeparam> | ||||
|         /// <param name="alignable">The alignable object.</param> | ||||
|         /// <returns>The same alignable object.</returns> | ||||
|         public static T LeftAligned<T>(this T alignable) | ||||
|             where T : IAlignable | ||||
|         { | ||||
|             alignable.Alignment = Justify.Left; | ||||
|             return alignable; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the <see cref="IAlignable"/> object to be centered. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The alignable type.</typeparam> | ||||
|         /// <param name="alignable">The alignable object.</param> | ||||
|         /// <returns>The same alignable object.</returns> | ||||
|         public static T Centered<T>(this T alignable) | ||||
|             where T : IAlignable | ||||
|         { | ||||
|             alignable.Alignment = Justify.Center; | ||||
|             return alignable; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the <see cref="IAlignable"/> object to be right aligned. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">The alignable type.</typeparam> | ||||
|         /// <param name="alignable">The alignable object.</param> | ||||
|         /// <returns>The same alignable object.</returns> | ||||
|         public static T RightAligned<T>(this T alignable) | ||||
|             where T : IAlignable | ||||
|         { | ||||
|             alignable.Alignment = Justify.Right; | ||||
|             return alignable; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -3,7 +3,7 @@ using System.Collections.Generic; | ||||
| using System.Globalization; | ||||
| using System.Linq; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a border used by tables. | ||||
| @@ -1,4 +1,4 @@ | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents the different border parts. | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents an old school ASCII border. | ||||
| @@ -1,4 +1,4 @@ | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents an invisible border. | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a rounded border. | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a square border. | ||||
| @@ -1,15 +1,15 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
| using Spectre.Console.Rendering; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a grid. | ||||
|     /// A renderable grid. | ||||
|     /// </summary> | ||||
|     public sealed class Grid : IRenderable | ||||
|     public sealed class Grid : Renderable | ||||
|     { | ||||
|         private readonly Table _table; | ||||
| 
 | ||||
| @@ -28,13 +28,13 @@ namespace Spectre.Console | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         public Measurement Measure(RenderContext context, int maxWidth) | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return ((IRenderable)_table).Measure(context, maxWidth); | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         public IEnumerable<Segment> Render(RenderContext context, int width) | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int width) | ||||
|         { | ||||
|             return ((IRenderable)_table).Render(context, width); | ||||
|         } | ||||
| @@ -109,8 +109,8 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         public void AddEmptyRow() | ||||
|         { | ||||
|             var columns = new string[_table.ColumnCount]; | ||||
|             Enumerable.Range(0, _table.ColumnCount).ForEach(index => columns[index] = string.Empty); | ||||
|             var columns = new IRenderable[_table.ColumnCount]; | ||||
|             Enumerable.Range(0, _table.ColumnCount).ForEach(index => columns[index] = Text.Empty); | ||||
|             AddRow(columns); | ||||
|         } | ||||
| 
 | ||||
| @@ -118,7 +118,7 @@ namespace Spectre.Console | ||||
|         /// Adds a new row to the grid. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public void AddRow(params string[] columns) | ||||
|         public void AddRow(params IRenderable[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
| @@ -3,7 +3,7 @@ namespace Spectre.Console | ||||
|     /// <summary> | ||||
|     /// Represents a grid column. | ||||
|     /// </summary> | ||||
|     public sealed class GridColumn | ||||
|     public sealed class GridColumn : IAlignable | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the column. | ||||
							
								
								
									
										31
									
								
								src/Spectre.Console/Rendering/GridExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								src/Spectre.Console/Rendering/GridExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="Grid"/>. | ||||
|     /// </summary> | ||||
|     public static class GridExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Adds a new row to the grid. | ||||
|         /// </summary> | ||||
|         /// <param name="grid">The grid to add the row to.</param> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public static void AddRow(this Grid grid, params string[] columns) | ||||
|         { | ||||
|             if (grid is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(grid)); | ||||
|             } | ||||
|  | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             grid.AddRow(columns.Select(column => new Markup(column)).ToArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/Spectre.Console/Rendering/IAlignable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/Spectre.Console/Rendering/IAlignable.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents something that is alignable. | ||||
|     /// </summary> | ||||
|     public interface IAlignable | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets or sets the alignment. | ||||
|         /// </summary> | ||||
|         Justify? Alignment { get; set; } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents something that can be rendered to the console. | ||||
							
								
								
									
										43
									
								
								src/Spectre.Console/Rendering/Markup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/Spectre.Console/Rendering/Markup.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| using System.Collections.Generic; | ||||
| using Spectre.Console.Internal; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A renderable piece of markup text. | ||||
|     /// </summary> | ||||
|     public sealed class Markup : Renderable, IAlignable | ||||
|     { | ||||
|         private readonly Text _text; | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         public Justify? Alignment | ||||
|         { | ||||
|             get => _text.Alignment; | ||||
|             set => _text.Alignment = value; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Markup"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The markup text.</param> | ||||
|         /// <param name="style">The style of the text.</param> | ||||
|         public Markup(string text, Style? style = null) | ||||
|         { | ||||
|             _text = MarkupParser.Parse(text, style); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return ((IRenderable)_text).Measure(context, maxWidth); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return ((IRenderable)_text).Render(context, maxWidth); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a measurement. | ||||
| @@ -1,13 +1,14 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Rendering; | ||||
| using SpectreBorder = Spectre.Console.Rendering.Border; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a panel which contains another renderable item. | ||||
|     /// A renderable panel. | ||||
|     /// </summary> | ||||
|     public sealed class Panel : IRenderable | ||||
|     public sealed class Panel : Renderable | ||||
|     { | ||||
|         private const int EdgeWidth = 2; | ||||
| 
 | ||||
| @@ -42,6 +43,15 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         public Padding Padding { get; set; } = new Padding(1, 1); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Panel"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="text">The panel content.</param> | ||||
|         public Panel(string text) | ||||
|             : this(new Markup(text)) | ||||
|         { | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Panel"/> class. | ||||
|         /// </summary> | ||||
| @@ -52,23 +62,25 @@ namespace Spectre.Console | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         Measurement IRenderable.Measure(RenderContext context, int maxWidth) | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             var childWidth = _child.Measure(context, maxWidth); | ||||
|             return new Measurement(childWidth.Min + 2 + Padding.GetHorizontalPadding(), childWidth.Max + 2 + Padding.GetHorizontalPadding()); | ||||
|             return new Measurement( | ||||
|                 childWidth.Min + 2 + Padding.GetHorizontalPadding(), | ||||
|                 childWidth.Max + 2 + Padding.GetHorizontalPadding()); | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         IEnumerable<Segment> IRenderable.Render(RenderContext context, int width) | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             var border = Composition.Border.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder); | ||||
|             var border = SpectreBorder.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder); | ||||
| 
 | ||||
|             var paddingWidth = Padding.GetHorizontalPadding(); | ||||
|             var childWidth = width - EdgeWidth - paddingWidth; | ||||
|             var childWidth = maxWidth - EdgeWidth - paddingWidth; | ||||
| 
 | ||||
|             if (!Expand) | ||||
|             { | ||||
|                 var measurement = _child.Measure(context, width - EdgeWidth - paddingWidth); | ||||
|                 var measurement = _child.Measure(context, maxWidth - EdgeWidth - paddingWidth); | ||||
|                 childWidth = measurement.Max; | ||||
|             } | ||||
| 
 | ||||
| @@ -1,6 +1,6 @@ | ||||
| using System.Text; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a render context. | ||||
							
								
								
									
										41
									
								
								src/Spectre.Console/Rendering/Renderable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/Spectre.Console/Rendering/Renderable.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Base class for a renderable object implementing <see cref="IRenderable"/>. | ||||
|     /// </summary> | ||||
|     public abstract class Renderable : IRenderable | ||||
|     { | ||||
|         /// <inheritdoc/> | ||||
|         Measurement IRenderable.Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return Measure(context, maxWidth); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         IEnumerable<Segment> IRenderable.Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return Render(context, maxWidth); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Measures the renderable object. | ||||
|         /// </summary> | ||||
|         /// <param name="context">The render context.</param> | ||||
|         /// <param name="maxWidth">The maximum allowed width.</param> | ||||
|         /// <returns>The minimum and maximum width of the object.</returns> | ||||
|         protected virtual Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return new Measurement(maxWidth, maxWidth); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Renders the object. | ||||
|         /// </summary> | ||||
|         /// <param name="context">The render context.</param> | ||||
|         /// <param name="maxWidth">The maximum allowed width.</param> | ||||
|         /// <returns>A collection of segments.</returns> | ||||
|         protected abstract IEnumerable<Segment> Render(RenderContext context, int maxWidth); | ||||
|     } | ||||
| } | ||||
| @@ -5,7 +5,7 @@ using System.Linq; | ||||
| using System.Text; | ||||
| using Spectre.Console.Internal; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a renderable segment. | ||||
| @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a collection of segments. | ||||
| @@ -1,7 +1,7 @@ | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     internal sealed class SegmentLineEnumerator : IEnumerable<Segment> | ||||
|     { | ||||
| @@ -1,7 +1,7 @@ | ||||
| using System.Collections; | ||||
| using System.Collections.Generic; | ||||
| 
 | ||||
| namespace Spectre.Console.Composition | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
|     internal sealed class SegmentLineIterator : IEnumerator<Segment> | ||||
|     { | ||||
| @@ -1,8 +1,8 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
| using Spectre.Console.Rendering; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
| @@ -100,13 +100,13 @@ namespace Spectre.Console | ||||
|             var maxWidths = new List<int>(); | ||||
| 
 | ||||
|             // Include columns in measurement | ||||
|             var measure = ((IRenderable)column.Text).Measure(options, maxWidth); | ||||
|             var measure = column.Text.Measure(options, maxWidth); | ||||
|             minWidths.Add(measure.Min); | ||||
|             maxWidths.Add(measure.Max); | ||||
| 
 | ||||
|             foreach (var row in rows) | ||||
|             { | ||||
|                 measure = ((IRenderable)row).Measure(options, maxWidth); | ||||
|                 measure = row.Measure(options, maxWidth); | ||||
|                 minWidths.Add(measure.Min); | ||||
|                 maxWidths.Add(measure.Max); | ||||
|             } | ||||
| @@ -1,18 +1,19 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
| using Spectre.Console.Rendering; | ||||
| using SpectreBorder = Spectre.Console.Rendering.Border; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a table. | ||||
|     /// A renderable table. | ||||
|     /// </summary> | ||||
|     public sealed partial class Table : IRenderable | ||||
|     public sealed partial class Table : Renderable | ||||
|     { | ||||
|         private readonly List<TableColumn> _columns; | ||||
|         private readonly List<List<Text>> _rows; | ||||
|         private readonly List<List<IRenderable>> _rows; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets the number of columns in the table. | ||||
| @@ -67,21 +68,7 @@ namespace Spectre.Console | ||||
|         public Table() | ||||
|         { | ||||
|             _columns = new List<TableColumn>(); | ||||
|             _rows = new List<List<Text>>(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Adds a column to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="column">The column to add.</param> | ||||
|         public void AddColumn(string column) | ||||
|         { | ||||
|             if (column is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(column)); | ||||
|             } | ||||
| 
 | ||||
|             AddColumn(new TableColumn(column)); | ||||
|             _rows = new List<List<IRenderable>>(); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
| @@ -103,23 +90,6 @@ namespace Spectre.Console | ||||
|             _columns.Add(column); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Adds multiple columns to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public void AddColumns(params string[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
| 
 | ||||
|             foreach (var column in columns) | ||||
|             { | ||||
|                 AddColumn(column); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Adds multiple columns to the table. | ||||
|         /// </summary> | ||||
| @@ -142,8 +112,8 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         public void AddEmptyRow() | ||||
|         { | ||||
|             var columns = new string[ColumnCount]; | ||||
|             Enumerable.Range(0, ColumnCount).ForEach(index => columns[index] = string.Empty); | ||||
|             var columns = new IRenderable[ColumnCount]; | ||||
|             Enumerable.Range(0, ColumnCount).ForEach(index => columns[index] = Text.Empty); | ||||
|             AddRow(columns); | ||||
|         } | ||||
| 
 | ||||
| @@ -151,7 +121,7 @@ namespace Spectre.Console | ||||
|         /// Adds a row to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="columns">The row columns to add.</param> | ||||
|         public void AddRow(params string[] columns) | ||||
|         public void AddRow(params IRenderable[] columns) | ||||
|         { | ||||
|             if (columns is null) | ||||
|             { | ||||
| @@ -168,11 +138,11 @@ namespace Spectre.Console | ||||
|                 throw new InvalidOperationException("The number of row columns are greater than the number of table columns."); | ||||
|             } | ||||
| 
 | ||||
|             _rows.Add(columns.Select(column => Text.Markup(column)).ToList()); | ||||
|             _rows.Add(columns.ToList()); | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         Measurement IRenderable.Measure(RenderContext context, int maxWidth) | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (context is null) | ||||
|             { | ||||
| @@ -194,20 +164,20 @@ namespace Spectre.Console | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         IEnumerable<Segment> IRenderable.Render(RenderContext context, int width) | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (context is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(context)); | ||||
|             } | ||||
| 
 | ||||
|             var border = Composition.Border.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder); | ||||
|             var border = SpectreBorder.GetBorder(Border, (context.LegacyConsole || !context.Unicode) && SafeBorder); | ||||
|             var tableWidth = maxWidth; | ||||
| 
 | ||||
|             var showBorder = Border != BorderKind.None; | ||||
|             var hideBorder = Border == BorderKind.None; | ||||
|             var hasRows = _rows.Count > 0; | ||||
| 
 | ||||
|             var maxWidth = width; | ||||
|             if (Width != null) | ||||
|             { | ||||
|                 maxWidth = Math.Min(Width.Value, maxWidth); | ||||
| @@ -219,13 +189,13 @@ namespace Spectre.Console | ||||
|             var columnWidths = CalculateColumnWidths(context, maxWidth); | ||||
| 
 | ||||
|             // Update the table width. | ||||
|             width = columnWidths.Sum() + GetExtraWidth(includePadding: true); | ||||
|             tableWidth = columnWidths.Sum() + GetExtraWidth(includePadding: true); | ||||
| 
 | ||||
|             var rows = new List<List<Text>>(); | ||||
|             var rows = new List<List<IRenderable>>(); | ||||
|             if (ShowHeaders) | ||||
|             { | ||||
|                 // Add columns to top of rows | ||||
|                 rows.Add(new List<Text>(_columns.Select(c => c.Text))); | ||||
|                 rows.Add(new List<IRenderable>(_columns.Select(c => c.Text))); | ||||
|             } | ||||
| 
 | ||||
|             // Add rows. | ||||
| @@ -244,7 +214,7 @@ namespace Spectre.Console | ||||
|                     var justification = _columns[columnIndex].Alignment; | ||||
|                     var childContext = context.WithJustification(justification); | ||||
| 
 | ||||
|                     var lines = Segment.SplitLines(((IRenderable)cell).Render(childContext, rowWidth)); | ||||
|                     var lines = Segment.SplitLines(cell.Render(childContext, rowWidth)); | ||||
|                     cellHeight = Math.Max(cellHeight, lines.Count); | ||||
|                     cells.Add(lines); | ||||
|                 } | ||||
| @@ -1,16 +1,17 @@ | ||||
| using System; | ||||
| using Spectre.Console.Rendering; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a table column. | ||||
|     /// </summary> | ||||
|     public sealed class TableColumn | ||||
|     public sealed class TableColumn : IAlignable | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the text associated with the column. | ||||
|         /// </summary> | ||||
|         public Text Text { get; } | ||||
|         public IRenderable Text { get; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the column. | ||||
| @@ -39,8 +40,17 @@ namespace Spectre.Console | ||||
|         /// </summary> | ||||
|         /// <param name="text">The table column text.</param> | ||||
|         public TableColumn(string text) | ||||
|             : this(new Markup(text)) | ||||
|         { | ||||
|             Text = Text.Markup(text ?? throw new ArgumentNullException(nameof(text))); | ||||
|         } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="TableColumn"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="renderable">The <see cref="IRenderable"/> instance to use as the table column.</param> | ||||
|         public TableColumn(IRenderable renderable) | ||||
|         { | ||||
|             Text = renderable ?? throw new ArgumentNullException(nameof(renderable)); | ||||
|             Width = null; | ||||
|             Padding = new Padding(1, 1); | ||||
|             NoWrap = false; | ||||
							
								
								
									
										78
									
								
								src/Spectre.Console/Rendering/TableExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/Spectre.Console/Rendering/TableExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| using System; | ||||
| using System.Linq; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="Table"/>. | ||||
|     /// </summary> | ||||
|     public static class TableExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Adds a column to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="table">The table to add the column to.</param> | ||||
|         /// <param name="column">The column to add.</param> | ||||
|         /// <returns>The added <see cref="TableColumn"/> instance.</returns> | ||||
|         public static TableColumn AddColumn(this Table table, string column) | ||||
|         { | ||||
|             if (table is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(table)); | ||||
|             } | ||||
|  | ||||
|             if (column is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(column)); | ||||
|             } | ||||
|  | ||||
|             var tableColumn = new TableColumn(column); | ||||
|             table.AddColumn(tableColumn); | ||||
|  | ||||
|             return tableColumn; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds multiple columns to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="table">The table to add the columns to.</param> | ||||
|         /// <param name="columns">The columns to add.</param> | ||||
|         public static void AddColumns(this Table table, params string[] columns) | ||||
|         { | ||||
|             if (table is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(table)); | ||||
|             } | ||||
|  | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             foreach (var column in columns) | ||||
|             { | ||||
|                 AddColumn(table, column); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds a row to the table. | ||||
|         /// </summary> | ||||
|         /// <param name="table">The table to add the row to.</param> | ||||
|         /// <param name="columns">The row columns to add.</param> | ||||
|         public static void AddRow(this Table table, params string[] columns) | ||||
|         { | ||||
|             if (table is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(table)); | ||||
|             } | ||||
|  | ||||
|             if (columns is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(columns)); | ||||
|             } | ||||
|  | ||||
|             table.AddRow(columns.Select(column => new Markup(column)).ToArray()); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -3,24 +3,29 @@ using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
| using System.Diagnostics.CodeAnalysis; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Composition; | ||||
| using Spectre.Console.Internal; | ||||
| using Spectre.Console.Rendering; | ||||
| 
 | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a piece of text. | ||||
|     /// A renderable piece of text. | ||||
|     /// </summary> | ||||
|     [DebuggerDisplay("{_text,nq}")] | ||||
|     [SuppressMessage("Naming", "CA1724:Type names should not match namespaces")] | ||||
|     public sealed class Text : IRenderable | ||||
|     public sealed class Text : Renderable, IAlignable | ||||
|     { | ||||
|         private readonly List<SegmentLine> _lines; | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets an empty <see cref="Text"/> instance. | ||||
|         /// </summary> | ||||
|         public static Text Empty { get; } = new Text(string.Empty); | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Gets or sets the text alignment. | ||||
|         /// </summary> | ||||
|         public Justify Alignment { get; set; } = Justify.Left; | ||||
|         public Justify? Alignment { get; set; } | ||||
| 
 | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Text"/> class. | ||||
| @@ -60,7 +65,7 @@ namespace Spectre.Console | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         public Measurement Measure(RenderContext context, int maxWidth) | ||||
|         protected override Measurement Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (_lines.Count == 0) | ||||
|             { | ||||
| @@ -74,7 +79,7 @@ namespace Spectre.Console | ||||
|         } | ||||
| 
 | ||||
|         /// <inheritdoc/> | ||||
|         public IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             if (context is null) | ||||
|             { | ||||
| @@ -89,7 +94,7 @@ namespace Spectre.Console | ||||
|             var lines = SplitLines(context, maxWidth); | ||||
| 
 | ||||
|             // Justify lines | ||||
|             var justification = context.Justification ?? Alignment; | ||||
|             var justification = context.Justification ?? Alignment ?? Justify.Left; | ||||
|             foreach (var (_, _, last, line) in lines.Enumerate()) | ||||
|             { | ||||
|                 var length = line.Sum(l => l.StripLineEndings().CellLength(context.Encoding)); | ||||
		Reference in New Issue
	
	Block a user