Does SharpConsoleUI have a control or feature similar to a Spinner? #25
-
|
Does SharpConsoleUI have a control or feature similar to a Spinner? |
Beta Was this translation helpful? Give feedback.
Replies: 9 comments
-
|
My temporary solution is: class Demo
{
static void Run()
{
var window = new WindowBuilder(windowSystem)
.WithAsyncWindowThread(RuninWindowThread)
.Build();
var statusBar = Controls.StatusBar()
.StickyBottom()
.Build();
CurrentSpinner = new DefaultSpinner();
CurrentSpinner.IsVisible = true;
RefreshSpinner = (frame) =>
{
statusBar.LeftItems[0].Label = $"[yellow]{frame.EscapeMarkup()}[/]";
};
statusBar.AddLeft(new StatusBarItem() { Label = " ".PadLeft(CurrentSpinner.CharsWidth) });
window.AddControl(statusBar);
windowSystem.AddWindow(window);
windowSystem.Run();
}
private static Action<string>? RefreshSpinner = null;
private static Spinner? CurrentSpinner = null;
private static async Task RuninWindowThread(Window window, CancellationToken ct)
{
while (!ct.IsCancellationRequested)
{
if(CurrentSpinner != null && CurrentSpinner.IsVisible)
{
await Task.Delay(CurrentSpinner.IntervalMs, ct);
RefreshSpinner?.Invoke(CurrentSpinner.NextFrame);
}
}
}
}
public class Spinner
{
public bool IsVisible { get; set; }
public virtual int IntervalMs => 100;
public virtual bool IsUnicode => true;
public virtual int CharsWidth => 1;
public virtual IReadOnlyList<string> Frames =>
[
"⣷",
"⣯",
"⣟",
"⡿",
"⢿",
"⣻",
"⣽",
"⣾",
];
protected int CurrentFrameIndex = 0;
public virtual string NextFrame
{
get
{
CurrentFrameIndex = (CurrentFrameIndex + 1) % Frames.Count;
return Frames[CurrentFrameIndex];
}
}
}
public sealed class DotsBarSpinner : Spinner
{
public override int IntervalMs => 360;
public override bool IsUnicode => false;
public override int CharsWidth => 3;
public override IReadOnlyList<string> Frames =>
[
". ",
".. ",
"...",
];
}@nickprotop Hopefully the official will include a new Spinner control. |
Beta Was this translation helpful? Give feedback.
-
|
Hi @changlv — thanks for the detailed request and the reference implementation, it was a great starting point! Spinner support is now built into SharpConsoleUI as of v2.4.65 (on NuGet now), so you can drop the manual 1. A standalone
|
Beta Was this translation helpful? Give feedback.
-
|
@nickprotop Awesome! That's exactly what I need! I've given you all sorts of Spinner variants that I've already implemented – hoping they can serve as a reference for you. If you think they're suitable, you can just build them in. public class Spinner
{
public bool IsVisible { get; set; }
public virtual int IntervalMs => 100;
public virtual bool IsUnicode => true;
public virtual int CharsWidth => 1;
public virtual IReadOnlyList<string> Frames =>
[
"⣷",
"⣯",
"⣟",
"⡿",
"⢿",
"⣻",
"⣽",
"⣾",
];
protected int CurrentFrameIndex = 0;
public virtual string NextFrame
{
get
{
CurrentFrameIndex = (CurrentFrameIndex + 1) % Frames.Count;
return Frames[CurrentFrameIndex];
}
}
}
public sealed class DefaultSpinner : Spinner { }
public sealed class DotsSpinner : Spinner
{
public override int IntervalMs => 80;
public override bool IsUnicode => true;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"⠋",
"⠙",
"⠹",
"⠸",
"⠼",
"⠴",
"⠦",
"⠧",
"⠇",
"⠏",
];
}
public sealed class LineSpinner : Spinner
{
public override int IntervalMs => 120;
public override bool IsUnicode => false;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"-",
"\\",
"|",
"/",
];
}
public sealed class DotsBarSpinner : Spinner
{
public override int IntervalMs => 360;
public override bool IsUnicode => false;
public override int CharsWidth => 3;
public override IReadOnlyList<string> Frames =>
[
". ",
".. ",
"...",
];
}
public sealed class DotsBar2Spinner : Spinner
{
public override int IntervalMs => 200;
public override bool IsUnicode => false;
public override int CharsWidth => 3;
public override IReadOnlyList<string> Frames =>
[
". ",
".. ",
"...",
" ..",
" .",
" ",
];
}
public sealed class StarSpinner : Spinner
{
public override int IntervalMs => 70;
public override bool IsUnicode => true;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"✶",
"✸",
"✹",
"✺",
"✹",
"✷",
];
}
public sealed class GrowVerticalSpinner : Spinner
{
public override int IntervalMs => 120;
public override bool IsUnicode => true;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"▁",
"▃",
"▄",
"▅",
"▆",
"▇",
"▆",
"▅",
"▄",
"▃",
];
}
public sealed class GrowHorizontalSpinner : Spinner
{
public override int IntervalMs => 120;
public override bool IsUnicode => true;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"▏",
"▎",
"▍",
"▌",
"▋",
"▊",
"▉",
"▊",
"▋",
"▌",
"▍",
"▎",
];
}
public sealed class ToggleSpinner : Spinner
{
public override int IntervalMs => 240;
public override bool IsUnicode => true;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"□",
"■",
];
}
public sealed class ArrowSpinner : Spinner
{
public override int IntervalMs => 120;
public override bool IsUnicode => true;
public override int CharsWidth => 1;
public override IReadOnlyList<string> Frames =>
[
"←",
"↖",
"↑",
"↗",
"→",
"↘",
"↓",
"↙",
];
}
public sealed class BouncingBarSpinner : Spinner
{
public override int IntervalMs => 80;
public override bool IsUnicode => false;
public override int CharsWidth => 6;
public override IReadOnlyList<string> Frames =>
[
"[ ]",
"[= ]",
"[== ]",
"[=== ]",
"[====]",
"[ ===]",
"[ ==]",
"[ =]",
"[ ]",
"[ =]",
"[ ==]",
"[ ===]",
"[====]",
"[=== ]",
"[== ]",
"[= ]",
];
}
public sealed class AestheticBarSpinner : Spinner
{
public override int IntervalMs => 80;
public override bool IsUnicode => true;
public override int CharsWidth => 6;
public override IReadOnlyList<string> Frames =>
[
"▰▱▱▱▱▱",
"▰▰▱▱▱▱",
"▰▰▰▱▱▱",
"▰▰▰▰▱▱",
"▰▰▰▰▰▱",
"▰▰▰▰▰▰",
"▰▱▱▱▱▱",
];
} |
Beta Was this translation helpful? Give feedback.
-
|
@changlv — these are great, thank you! I've added the distinct ones as built-in presets. As of v2.4.67 (on NuGet now) the full set of new
They work three ways, same as the original presets: // 1. Standalone control
Controls.Spinner().WithStyle(SpinnerStyle.Arrow).Build();
// 2. Drive a label (your original status-bar use case)
new SpinnerTextAnimator(ws, SpinnerStyle.AestheticBar,
frame => statusBar.LeftItems[0].Label = frame).Start();
// 3. Inline markup tag — anywhere markup renders
"Working [spinner star] / [spinner brailledots] / [spinner aestheticbar]"On your original status-bar question specifically: statusBar.AddLeft(null, "[green]Building [spinner][/]");
statusBar.AddCenterText("Connecting [cyan1][spinner circle][/]");
// any style: [spinner arrow], [spinner aestheticbar], …No background thread, no manual frame index, and it respects the global animations-enabled setting. See it live: the DemoApp's Spinner window (Controls → Spinner) now shows every preset, the inline-tag examples, and a status bar pinned to the bottom that uses both an inline A couple of implementation notes in case they're useful for your own copies:
You're credited in the source and docs. Thanks again for the catalog — genuinely nice additions! |
Beta Was this translation helpful? Give feedback.
-
|
@nickprotop Wow, you're really efficient! |
Beta Was this translation helpful? Give feedback.
-
|
Good call on the timing — fixed in v2.4.68. Two things landed: 1. Per-style default speeds. Each style now has a sensible default interval instead of the flat 100 ms, so To override on a control, use the fluent Controls.Spinner().WithStyle(SpinnerStyle.Dots).Build(); // 360ms default
Controls.Spinner().WithStyle(SpinnerStyle.Dots).WithInterval(80).Build(); // explicit 80ms2. Inline interval override. You can also set the speed right in the markup tag: A trailing millisecond value wins; an invalid/missing one falls back to the style default, and the interval never affects the reserved width (so no reflow). The DemoApp's Spinner window shows all three side by side. Precedence everywhere is explicit → per-style default → 100 ms. Thanks again — the library's spinners are in much better shape thanks to your input! |
Beta Was this translation helpful? Give feedback.
-
|
@nickprotop The Spinner control is working well now. Just a small suggestion: perhaps the default interval value could be a bit larger (too fast might make users feel anxious). SpinnerStyle.Star interval: 180 |
Beta Was this translation helpful? Give feedback.
-
|
Thanks @changlv — applied your tested values in v2.4.71 (on NuGet now). The unset per-style defaults are now:
They read much calmer — agreed the old speeds felt a bit anxious. |
Beta Was this translation helpful? Give feedback.
-
|
@nickprotop Thank you for adopting it! Fast work! Awesome! |
Beta Was this translation helpful? Give feedback.
@changlv — these are great, thank you! I've added the distinct ones as built-in presets. As of v2.4.67 (on NuGet now) the full set of new
SpinnerStylevalues is:Star,GrowVertical,GrowHorizontal,Toggle,Arrow,BouncingBar,AestheticBar,BrailleDots,DotsBounceThey work three ways, same…