Patrik Svensson 20650f1e7e Change IAnsiConsole to render IRenderable
This makes it possible for encoders to output better representation
of the actual objects instead of working with chopped up segments.

* IAnsiConsole.Write now takes an IRenderable instead of segments
* Calculating cell width does no longer require a render context
* Removed RenderContext.LegacyConsole
* Removed RenderContext.Encoding
* Added Capabilities.Unicode
2021-03-28 09:06:06 -04:00

81 lines
2.2 KiB
C#

using System.Collections.Generic;
namespace Spectre.Console.Rendering
{
internal sealed class LiveRenderable : Renderable
{
private readonly object _lock = new object();
private IRenderable? _renderable;
private SegmentShape? _shape;
public bool HasRenderable => _renderable != null;
public void SetRenderable(IRenderable renderable)
{
lock (_lock)
{
_renderable = renderable;
}
}
public IRenderable PositionCursor()
{
lock (_lock)
{
if (_shape == null)
{
return new ControlSequence(string.Empty);
}
return new ControlSequence("\r" + "\u001b[1A".Repeat(_shape.Value.Height - 1));
}
}
public IRenderable RestoreCursor()
{
lock (_lock)
{
if (_shape == null)
{
return new ControlSequence(string.Empty);
}
return new ControlSequence("\r\u001b[2K" + "\u001b[1A\u001b[2K".Repeat(_shape.Value.Height - 1));
}
}
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
{
lock (_lock)
{
if (_renderable != null)
{
var segments = _renderable.Render(context, maxWidth);
var lines = Segment.SplitLines(segments);
var shape = SegmentShape.Calculate(context, lines);
_shape = _shape == null ? shape : _shape.Value.Inflate(shape);
_shape.Value.Apply(context, ref lines);
foreach (var (_, _, last, line) in lines.Enumerate())
{
foreach (var item in line)
{
yield return item;
}
if (!last)
{
yield return Segment.LineBreak;
}
}
yield break;
}
_shape = null;
}
}
}
}