LegendAnnotation.cs 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. namespace Terminal.Gui.Views;
  2. /// <summary>
  3. /// Used by <see cref="GraphView"/> to render smbol definitions in a graph, e.g. colors and their meanings
  4. /// </summary>
  5. public class LegendAnnotation : View, IAnnotation
  6. {
  7. /// <summary>Ordered collection of entries that are rendered in the legend.</summary>
  8. private readonly List<Tuple<GraphCellToRender, string>> _entries = new ();
  9. /// <summary>Creates a new empty legend at the empty screen coordinates.</summary>
  10. public LegendAnnotation () : this (Rectangle.Empty) { }
  11. /// <summary>Creates a new empty legend at the given screen coordinates.</summary>
  12. /// <param name="legendBounds">
  13. /// Defines the area available for the legend to render in (within the graph). This is in
  14. /// screen units (i.e. not graph space)
  15. /// </param>
  16. public LegendAnnotation (Rectangle legendBounds)
  17. {
  18. X = legendBounds.X;
  19. Y = legendBounds.Y;
  20. Width = legendBounds.Width;
  21. Height = legendBounds.Height;
  22. BorderStyle = LineStyle.Single;
  23. }
  24. /// <summary>Returns false i.e. Legends render after series</summary>
  25. public bool BeforeSeries => false;
  26. // BUGBUG: Legend annotations are subviews. But for some reason the are rendered directly in OnDrawContent
  27. // BUGBUG: instead of just being normal subviews. They get rendered as blank rects and thus we disable subview drawing.
  28. /// <inheritdoc/>
  29. protected override bool OnDrawingText () { return true; }
  30. // BUGBUG: Legend annotations are subviews. But for some reason the are rendered directly in OnDrawContent
  31. // BUGBUG: instead of just being normal subviews. They get rendered as blank rects and thus we disable subview drawing.
  32. /// <inheritdoc/>
  33. protected override bool OnClearingViewport () { return true; }
  34. /// <summary>Draws the Legend and all entries into the area within <see cref="View.Viewport"/></summary>
  35. /// <param name="graph"></param>
  36. public void Render (GraphView graph)
  37. {
  38. if (!IsInitialized)
  39. {
  40. // BUGBUG: We should be getting a visual role here?
  41. SetScheme (new() { Normal = Application.Driver?.GetAttribute () ?? Attribute.Default });
  42. graph.Add (this);
  43. }
  44. if (BorderStyle != LineStyle.None)
  45. {
  46. DrawAdornments ();
  47. RenderLineCanvas ();
  48. }
  49. var linesDrawn = 0;
  50. foreach (Tuple<GraphCellToRender, string> entry in _entries)
  51. {
  52. if (entry.Item1.Color.HasValue)
  53. {
  54. SetAttribute (entry.Item1.Color.Value);
  55. }
  56. else
  57. {
  58. graph.SetDriverColorToGraphColor ();
  59. }
  60. // add the symbol
  61. AddRune (0, linesDrawn, entry.Item1.Rune);
  62. // switch to normal coloring (for the text)
  63. graph.SetDriverColorToGraphColor ();
  64. // add the text
  65. Move (1, linesDrawn);
  66. string str = TextFormatter.ClipOrPad (entry.Item2, Viewport.Width - 1);
  67. Application.Driver?.AddStr (str);
  68. linesDrawn++;
  69. // Legend has run out of space
  70. if (linesDrawn >= Viewport.Height)
  71. {
  72. break;
  73. }
  74. }
  75. }
  76. /// <summary>Adds an entry into the legend. Duplicate entries are permissible</summary>
  77. /// <param name="graphCellToRender">The symbol appearing on the graph that should appear in the legend</param>
  78. /// <param name="text">
  79. /// Text to render on this line of the legend. Will be truncated if outside of Legend
  80. /// <see cref="View.Viewport"/>
  81. /// </param>
  82. public void AddEntry (GraphCellToRender graphCellToRender, string text) { _entries.Add (Tuple.Create (graphCellToRender, text)); }
  83. }