mirror of
				https://github.com/nsnail/spectre.console.git
				synced 2025-11-01 01:25:27 +08:00 
			
		
		
		
	 Patrik Svensson
					Patrik Svensson
				
			
				
					committed by
					
						 Patrik Svensson
						Patrik Svensson
					
				
			
			
				
	
			
			
			 Patrik Svensson
						Patrik Svensson
					
				
			
						parent
						
							1cf30f62fc
						
					
				
				
					commit
					7dccb310f3
				
			| @@ -0,0 +1,4 @@ | ||||
|                           Number of fruits                   | ||||
|  Apple  ████████ 12                                          | ||||
| Orange  █████████████████████████████████████████████████ 54 | ||||
| Banana  ████████████████████████████ 33                      | ||||
							
								
								
									
										28
									
								
								src/Spectre.Console.Tests/Unit/BarChartTests.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Spectre.Console.Tests/Unit/BarChartTests.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| using System.Threading.Tasks; | ||||
| using VerifyXunit; | ||||
| using Xunit; | ||||
|  | ||||
| namespace Spectre.Console.Tests.Unit | ||||
| { | ||||
|     [UsesVerify] | ||||
|     public sealed class BarChartTests | ||||
|     { | ||||
|         [Fact] | ||||
|         public async Task Should_Render_Correctly() | ||||
|         { | ||||
|             // Given | ||||
|             var console = new PlainConsole(width: 80); | ||||
|  | ||||
|             // When | ||||
|             console.Render(new BarChart() | ||||
|                 .Width(60) | ||||
|                 .Label("Number of fruits") | ||||
|                 .AddItem("Apple", 12) | ||||
|                 .AddItem("Orange", 54) | ||||
|                 .AddItem("Banana", 33)); | ||||
|  | ||||
|             // Then | ||||
|             await Verifier.Verify(console.Output); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -62,6 +62,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Progress", "..\examples\Pro | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Status", "..\examples\Status\Status.csproj", "{3716AFDF-0904-4635-8422-86E6B9356840}" | ||||
| EndProject | ||||
| Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Charts", "..\examples\Charts\Charts.csproj", "{0A1AFD26-86A0-4060-B277-D380172C7070}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| @@ -324,6 +326,18 @@ Global | ||||
| 		{3716AFDF-0904-4635-8422-86E6B9356840}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{3716AFDF-0904-4635-8422-86E6B9356840}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{3716AFDF-0904-4635-8422-86E6B9356840}.Release|x86.Build.0 = Release|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Debug|x64.Build.0 = Debug|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Debug|x86.ActiveCfg = Debug|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Debug|x86.Build.0 = Debug|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Release|x64.Build.0 = Release|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Release|x86.ActiveCfg = Release|Any CPU | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070}.Release|x86.Build.0 = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
| @@ -348,6 +362,7 @@ Global | ||||
| 		{5693761A-754A-40A8-9144-36510D6A4D69} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 		{2B712A52-40F1-4C1C-833E-7C869ACA91F3} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 		{3716AFDF-0904-4635-8422-86E6B9356840} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 		{0A1AFD26-86A0-4060-B277-D380172C7070} = {F0575243-121F-4DEE-9F6B-246E26DC0844} | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(ExtensibilityGlobals) = postSolution | ||||
| 		SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C} | ||||
|   | ||||
							
								
								
									
										234
									
								
								src/Spectre.Console/Extensions/BarGraphExtensions.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										234
									
								
								src/Spectre.Console/Extensions/BarGraphExtensions.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,234 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Contains extension methods for <see cref="BarChart"/>. | ||||
|     /// </summary> | ||||
|     public static class BarGraphExtensions | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Adds an item to the bar chart. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="label">The item label.</param> | ||||
|         /// <param name="value">The item value.</param> | ||||
|         /// <param name="color">The item color.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart AddItem(this BarChart chart, string label, double value, Color? color = null) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.Data.Add(new BarChartItem(label, value, color)); | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds an item to the bar chart. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">A type that implements <see cref="IBarChartItem"/>.</typeparam> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="item">The item.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart AddItem<T>(this BarChart chart, T item) | ||||
|             where T : IBarChartItem | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.Data.Add(new BarChartItem( | ||||
|                     item.Label, | ||||
|                     item.Value, | ||||
|                     item.Color)); | ||||
|  | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds multiple items to the bar chart. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">A type that implements <see cref="IBarChartItem"/>.</typeparam> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="items">The items.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart AddItems<T>(this BarChart chart, IEnumerable<T> items) | ||||
|             where T : IBarChartItem | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             if (items is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(items)); | ||||
|             } | ||||
|  | ||||
|             foreach (var item in items) | ||||
|             { | ||||
|                 AddItem<T>(chart, item); | ||||
|             } | ||||
|  | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Adds multiple items to the bar chart. | ||||
|         /// </summary> | ||||
|         /// <typeparam name="T">A type that implements <see cref="IBarChartItem"/>.</typeparam> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="items">The items.</param> | ||||
|         /// <param name="converter">The converter that converts instances of <c>T</c> to <see cref="BarChartItem"/>.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart AddItems<T>(this BarChart chart, IEnumerable<T> items, Func<T, BarChartItem> converter) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             if (items is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(items)); | ||||
|             } | ||||
|  | ||||
|             if (converter is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(converter)); | ||||
|             } | ||||
|  | ||||
|             foreach (var item in items) | ||||
|             { | ||||
|                 chart.Data.Add(converter(item)); | ||||
|             } | ||||
|  | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the width of the bar chart. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="width">The bar chart width.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart Width(this BarChart chart, int? width) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.Width = width; | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the label of the bar chart. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="label">The bar chart label.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart Label(this BarChart chart, string? label) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.Label = label; | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Shows values next to each bar in the bar chart. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart ShowValues(this BarChart chart) | ||||
|         { | ||||
|             return ShowValues(chart, true); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Hides values next to each bar in the bar chart. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart HideValues(this BarChart chart) | ||||
|         { | ||||
|             return ShowValues(chart, false); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets whether or not values should be shown | ||||
|         /// next to each bar. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <param name="show">Whether or not values should be shown next to each bar.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart ShowValues(this BarChart chart, bool show) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.ShowValues = show; | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Aligns the label to the left. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart LeftAlignLabel(this BarChart chart) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.LabelAlignment = Justify.Left; | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Centers the label. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart CenterLabel(this BarChart chart) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.LabelAlignment = Justify.Center; | ||||
|             return chart; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Aligns the label to the right. | ||||
|         /// </summary> | ||||
|         /// <param name="chart">The bar chart.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static BarChart RightAlignLabel(this BarChart chart) | ||||
|         { | ||||
|             if (chart is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(chart)); | ||||
|             } | ||||
|  | ||||
|             chart.LabelAlignment = Justify.Right; | ||||
|             return chart; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -97,5 +97,22 @@ namespace Spectre.Console | ||||
|             grid.AddRow(columns.Select(column => new Markup(column)).ToArray()); | ||||
|             return grid; | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Sets the grid width. | ||||
|         /// </summary> | ||||
|         /// <param name="grid">The grid.</param> | ||||
|         /// <param name="width">The width.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static Grid Width(this Grid grid, int? width) | ||||
|         { | ||||
|             if (grid is null) | ||||
|             { | ||||
|                 throw new ArgumentNullException(nameof(grid)); | ||||
|             } | ||||
|  | ||||
|             grid.Width = width; | ||||
|             return grid; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -150,7 +150,7 @@ namespace Spectre.Console | ||||
|         /// <param name="table">The table.</param> | ||||
|         /// <param name="width">The width.</param> | ||||
|         /// <returns>The same instance so that multiple calls can be chained.</returns> | ||||
|         public static Table Width(this Table table, int width) | ||||
|         public static Table Width(this Table table, int? width) | ||||
|         { | ||||
|             if (table is null) | ||||
|             { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Diagnostics; | ||||
|  | ||||
| namespace Spectre.Console.Rendering | ||||
| { | ||||
| @@ -8,12 +9,14 @@ namespace Spectre.Console.Rendering | ||||
|     public abstract class Renderable : IRenderable | ||||
|     { | ||||
|         /// <inheritdoc/> | ||||
|         [DebuggerStepThrough] | ||||
|         Measurement IRenderable.Measure(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return Measure(context, maxWidth); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         [DebuggerStepThrough] | ||||
|         IEnumerable<Segment> IRenderable.Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             return Render(context, maxWidth); | ||||
|   | ||||
							
								
								
									
										82
									
								
								src/Spectre.Console/Widgets/BarChart.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								src/Spectre.Console/Widgets/BarChart.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| using System.Collections.Generic; | ||||
| using System.Linq; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// A renderable (horizontal) bar chart. | ||||
|     /// </summary> | ||||
|     public sealed class BarChart : Renderable | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the bar chart data. | ||||
|         /// </summary> | ||||
|         public List<BarChartItem> Data { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the bar chart. | ||||
|         /// </summary> | ||||
|         public int? Width { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the bar chart label. | ||||
|         /// </summary> | ||||
|         public string? Label { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the bar chart label alignment. | ||||
|         /// </summary> | ||||
|         public Justify? LabelAlignment { get; set; } = Justify.Center; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets a value indicating whether or not | ||||
|         /// values should be shown next to each bar. | ||||
|         /// </summary> | ||||
|         public bool ShowValues { get; set; } = true; | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="BarChart"/> class. | ||||
|         /// </summary> | ||||
|         public BarChart() | ||||
|         { | ||||
|             Data = new List<BarChartItem>(); | ||||
|         } | ||||
|  | ||||
|         /// <inheritdoc/> | ||||
|         protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth) | ||||
|         { | ||||
|             var maxValue = Data.Max(item => item.Value); | ||||
|  | ||||
|             var table = new Grid(); | ||||
|             table.Collapse(); | ||||
|             table.AddColumn(new GridColumn().PadRight(2).RightAligned()); | ||||
|             table.AddColumn(new GridColumn().PadLeft(0)); | ||||
|             table.Width = Width; | ||||
|  | ||||
|             if (!string.IsNullOrWhiteSpace(Label)) | ||||
|             { | ||||
|                 table.AddRow(Text.Empty, new Markup(Label).Alignment(LabelAlignment)); | ||||
|             } | ||||
|  | ||||
|             foreach (var item in Data) | ||||
|             { | ||||
|                 table.AddRow( | ||||
|                     new Markup(item.Label), | ||||
|                     new ProgressBar() | ||||
|                     { | ||||
|                         Value = item.Value, | ||||
|                         MaxValue = maxValue, | ||||
|                         ShowRemaining = false, | ||||
|                         CompletedStyle = new Style().Foreground(item.Color ?? Color.Default), | ||||
|                         FinishedStyle = new Style().Foreground(item.Color ?? Color.Default), | ||||
|                         UnicodeBar = '█', | ||||
|                         AsciiBar = '█', | ||||
|                         ShowValue = ShowValues, | ||||
|                     }); | ||||
|             } | ||||
|  | ||||
|             return ((IRenderable)table).Render(context, maxWidth); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										38
									
								
								src/Spectre.Console/Widgets/BarChartItem.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/Spectre.Console/Widgets/BarChartItem.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| using System; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// An item that's shown in a bar chart. | ||||
|     /// </summary> | ||||
|     public sealed class BarChartItem : IBarChartItem | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the item label. | ||||
|         /// </summary> | ||||
|         public string Label { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the item value. | ||||
|         /// </summary> | ||||
|         public double Value { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the item color. | ||||
|         /// </summary> | ||||
|         public Color? Color { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="BarChartItem"/> class. | ||||
|         /// </summary> | ||||
|         /// <param name="label">The item label.</param> | ||||
|         /// <param name="value">The item value.</param> | ||||
|         /// <param name="color">The item color.</param> | ||||
|         public BarChartItem(string label, double value, Color? color = null) | ||||
|         { | ||||
|             Label = label ?? throw new ArgumentNullException(nameof(label)); | ||||
|             Value = value; | ||||
|             Color = color; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -42,6 +42,11 @@ namespace Spectre.Console | ||||
|             set => MarkAsDirty(() => _alignment = value); | ||||
|         } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets or sets the width of the grid. | ||||
|         /// </summary> | ||||
|         public int? Width { get; set; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Initializes a new instance of the <see cref="Grid"/> class. | ||||
|         /// </summary> | ||||
| @@ -124,6 +129,7 @@ namespace Spectre.Console | ||||
|                 ShowHeaders = false, | ||||
|                 IsGrid = true, | ||||
|                 PadRightCell = _padRightCell, | ||||
|                 Width = Width, | ||||
|             }; | ||||
|  | ||||
|             foreach (var column in _columns) | ||||
|   | ||||
							
								
								
									
										23
									
								
								src/Spectre.Console/Widgets/IBarGraphItem.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/Spectre.Console/Widgets/IBarGraphItem.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| namespace Spectre.Console | ||||
| { | ||||
|     /// <summary> | ||||
|     /// Represents a bar chart item. | ||||
|     /// </summary> | ||||
|     public interface IBarChartItem | ||||
|     { | ||||
|         /// <summary> | ||||
|         /// Gets the item label. | ||||
|         /// </summary> | ||||
|         string Label { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the item value. | ||||
|         /// </summary> | ||||
|         double Value { get; } | ||||
|  | ||||
|         /// <summary> | ||||
|         /// Gets the item color. | ||||
|         /// </summary> | ||||
|         Color? Color { get; } | ||||
|     } | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Globalization; | ||||
| using Spectre.Console.Rendering; | ||||
|  | ||||
| namespace Spectre.Console | ||||
| @@ -10,6 +11,10 @@ namespace Spectre.Console | ||||
|         public double MaxValue { get; set; } = 100; | ||||
|  | ||||
|         public int? Width { get; set; } | ||||
|         public bool ShowRemaining { get; set; } = true; | ||||
|         public char UnicodeBar { get; set; } = '━'; | ||||
|         public char AsciiBar { get; set; } = '-'; | ||||
|         public bool ShowValue { get; set; } | ||||
|  | ||||
|         public Style CompletedStyle { get; set; } = new Style(foreground: Color.Yellow); | ||||
|         public Style FinishedStyle { get; set; } = new Style(foreground: Color.Green); | ||||
| @@ -26,15 +31,38 @@ namespace Spectre.Console | ||||
|             var width = Math.Min(Width ?? maxWidth, maxWidth); | ||||
|             var completed = Math.Min(MaxValue, Math.Max(0, Value)); | ||||
|  | ||||
|             var token = !context.Unicode || context.LegacyConsole ? '-' : '━'; | ||||
|             var token = !context.Unicode || context.LegacyConsole ? AsciiBar : UnicodeBar; | ||||
|             var style = completed >= MaxValue ? FinishedStyle : CompletedStyle; | ||||
|  | ||||
|             var bars = Math.Max(0, (int)(width * (completed / MaxValue))); | ||||
|  | ||||
|             var value = completed.ToString(CultureInfo.InvariantCulture); | ||||
|             if (ShowValue) | ||||
|             { | ||||
|                 bars = bars - value.Length - 1; | ||||
|             } | ||||
|  | ||||
|             yield return new Segment(new string(token, bars), style); | ||||
|  | ||||
|             if (ShowValue) | ||||
|             { | ||||
|                 yield return new Segment(" " + value, style); | ||||
|             } | ||||
|  | ||||
|             if (bars < width) | ||||
|             { | ||||
|                 yield return new Segment(new string(token, width - bars), RemainingStyle); | ||||
|                 var diff = width - bars; | ||||
|                 if (ShowValue) | ||||
|                 { | ||||
|                     diff = diff - value.Length - 1; | ||||
|                     if (diff <= 0) | ||||
|                     { | ||||
|                         yield break; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 var remainingToken = ShowRemaining ? token : ' '; | ||||
|                 yield return new Segment(new string(remainingToken, diff), RemainingStyle); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user