Add support for different spinners

This commit is contained in:
Patrik Svensson
2020-12-05 10:52:51 +01:00
committed by Patrik Svensson
parent 3c504155bc
commit cbed41e637
20 changed files with 3618 additions and 45 deletions

View File

@ -1,4 +1,6 @@
using System;
using System.Linq;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console
@ -11,8 +13,8 @@ namespace Spectre.Console
private const string ACCUMULATED = "SPINNER_ACCUMULATED";
private const string INDEX = "SPINNER_INDEX";
private readonly string _ansiSequence = "⣷⣯⣟⡿⢿⣻⣽⣾";
private readonly string _asciiSequence = "-\\|/-\\|/";
private readonly ProgressSpinner _spinner;
private int? _maxLength;
/// <inheritdoc/>
protected internal override int? ColumnWidth => 1;
@ -25,26 +27,48 @@ namespace Spectre.Console
/// </summary>
public Style Style { get; set; } = new Style(foreground: Color.Yellow);
/// <summary>
/// Initializes a new instance of the <see cref="SpinnerColumn"/> class.
/// </summary>
public SpinnerColumn()
: this(ProgressSpinner.Known.Default)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="SpinnerColumn"/> class.
/// </summary>
/// <param name="spinner">The spinner to use.</param>
public SpinnerColumn(ProgressSpinner spinner)
{
_spinner = spinner ?? throw new ArgumentNullException(nameof(spinner));
}
/// <inheritdoc/>
public override IRenderable Render(RenderContext context, ProgressTask task, TimeSpan deltaTime)
{
var useAscii = (context.LegacyConsole || !context.Unicode) && _spinner.IsUnicode;
var spinner = useAscii ? ProgressSpinner.Known.Ascii : _spinner;
if (!task.IsStarted || task.IsFinished)
{
return new Markup(" ");
if (_maxLength == null)
{
_maxLength = _spinner.Frames.Max(frame => Cell.GetCellLength(context, frame));
}
return new Markup(new string(' ', _maxLength.Value));
}
var accumulated = task.State.Update<double>(ACCUMULATED, acc => acc + deltaTime.TotalMilliseconds);
if (accumulated >= 100)
if (accumulated >= _spinner.Interval.TotalMilliseconds)
{
task.State.Update<double>(ACCUMULATED, _ => 0);
task.State.Update<int>(INDEX, index => index + 1);
}
var useAscii = context.LegacyConsole || !context.Unicode;
var sequence = useAscii ? _asciiSequence : _ansiSequence;
var index = task.State.Get<int>(INDEX);
return new Markup(sequence[index % sequence.Length].ToString(), Style ?? Style.Plain);
return new Markup(spinner.Frames[index % spinner.Frames.Count], Style ?? Style.Plain);
}
}
}

View File

@ -26,6 +26,12 @@ namespace Spectre.Console
/// </summary>
public bool AutoClear { get; set; }
/// <summary>
/// Gets or sets the refresh rate if <c>AutoRefresh</c> is enabled.
/// Defaults to 10 times/second.
/// </summary>
public TimeSpan RefreshRate { get; set; } = TimeSpan.FromMilliseconds(100);
internal List<ProgressColumn> Columns { get; }
/// <summary>
@ -110,7 +116,7 @@ namespace Spectre.Console
if (interactive)
{
var columns = new List<ProgressColumn>(Columns);
return new InteractiveProgressRenderer(_console, columns);
return new InteractiveProgressRenderer(_console, columns, RefreshRate);
}
else
{

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,27 @@
using System;
using System.Collections.Generic;
namespace Spectre.Console
{
/// <summary>
/// Represents a spinner used in a <see cref="SpinnerColumn"/>.
/// </summary>
public abstract partial class ProgressSpinner
{
/// <summary>
/// Gets the update interval for the spinner.
/// </summary>
public abstract TimeSpan Interval { get; }
/// <summary>
/// Gets a value indicating whether or not the spinner
/// uses Unicode characters.
/// </summary>
public abstract bool IsUnicode { get; }
/// <summary>
/// Gets the spinner frames.
/// </summary>
public abstract IReadOnlyList<string> Frames { get; }
}
}

View File

@ -15,9 +15,9 @@ namespace Spectre.Console.Internal
private readonly Stopwatch _stopwatch;
private TimeSpan _lastUpdate;
public override TimeSpan RefreshRate => TimeSpan.FromMilliseconds(100);
public override TimeSpan RefreshRate { get; }
public InteractiveProgressRenderer(IAnsiConsole console, List<ProgressColumn> columns)
public InteractiveProgressRenderer(IAnsiConsole console, List<ProgressColumn> columns, TimeSpan refreshRate)
{
_console = console ?? throw new ArgumentNullException(nameof(console));
_columns = columns ?? throw new ArgumentNullException(nameof(columns));
@ -25,6 +25,8 @@ namespace Spectre.Console.Internal
_lock = new object();
_stopwatch = new Stopwatch();
_lastUpdate = TimeSpan.Zero;
RefreshRate = refreshRate;
}
public override void Started()

View File

@ -1,7 +1,6 @@
using System.Collections.Generic;
using System.Linq;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console.Rendering
{