#nullable disable
namespace Terminal.Gui.Views;
///
/// Used by to render smbol definitions in a graph, e.g. colors and their meanings
///
public class LegendAnnotation : View, IAnnotation
{
/// Ordered collection of entries that are rendered in the legend.
private readonly List> _entries = new ();
/// Creates a new empty legend at the empty screen coordinates.
public LegendAnnotation () : this (Rectangle.Empty) { }
/// Creates a new empty legend at the given screen coordinates.
///
/// Defines the area available for the legend to render in (within the graph). This is in
/// screen units (i.e. not graph space)
///
public LegendAnnotation (Rectangle legendBounds)
{
X = legendBounds.X;
Y = legendBounds.Y;
Width = legendBounds.Width;
Height = legendBounds.Height;
BorderStyle = LineStyle.Single;
}
/// Returns false i.e. Legends render after series
public bool BeforeSeries => false;
// BUGBUG: Legend annotations are subviews. But for some reason the are rendered directly in OnDrawContent
// BUGBUG: instead of just being normal subviews. They get rendered as blank rects and thus we disable subview drawing.
///
protected override bool OnDrawingText () { return true; }
// BUGBUG: Legend annotations are subviews. But for some reason the are rendered directly in OnDrawContent
// BUGBUG: instead of just being normal subviews. They get rendered as blank rects and thus we disable subview drawing.
///
protected override bool OnClearingViewport () { return true; }
/// Draws the Legend and all entries into the area within
///
public void Render (GraphView graph)
{
if (!IsInitialized)
{
// BUGBUG: We should be getting a visual role here?
SetScheme (new () { Normal = Application.Driver?.GetAttribute () ?? Attribute.Default });
graph.Add (this);
}
if (BorderStyle != LineStyle.None)
{
// BUGBUG: View code should never call Draw directly. This
// BUGBUG: needs to be refactored to decouple.
DrawAdornments ();
RenderLineCanvas (null);
}
var linesDrawn = 0;
foreach (Tuple entry in _entries)
{
if (entry.Item1.Color.HasValue)
{
SetAttribute (entry.Item1.Color.Value);
}
else
{
graph.SetDriverColorToGraphColor ();
}
// add the symbol
AddRune (0, linesDrawn, entry.Item1.Rune);
// switch to normal coloring (for the text)
graph.SetDriverColorToGraphColor ();
// add the text
Move (1, linesDrawn);
string str = TextFormatter.ClipOrPad (entry.Item2, Viewport.Width - 1);
Application.Driver?.AddStr (str);
linesDrawn++;
// Legend has run out of space
if (linesDrawn >= Viewport.Height)
{
break;
}
}
}
/// Adds an entry into the legend. Duplicate entries are permissible
/// The symbol appearing on the graph that should appear in the legend
///
/// Text to render on this line of the legend. Will be truncated if outside of Legend
///
///
public void AddEntry (GraphCellToRender graphCellToRender, string text) { _entries.Add (Tuple.Create (graphCellToRender, text)); }
}