2
0

ShadowView.cs 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. #nullable enable
  2. using Microsoft.VisualBasic;
  3. using System.Diagnostics;
  4. namespace Terminal.Gui;
  5. /// <summary>
  6. /// Draws a shadow on the right or bottom of the view. Used internally by <see cref="Margin"/>.
  7. /// </summary>
  8. internal class ShadowView : View
  9. {
  10. private ShadowStyle _shadowStyle;
  11. /// <inheritdoc/>
  12. public override Attribute GetNormalColor ()
  13. {
  14. if (SuperView is Adornment adornment)
  15. {
  16. var attr = Attribute.Default;
  17. if (adornment.Parent?.SuperView is { })
  18. {
  19. attr = adornment.Parent.SuperView.GetNormalColor ();
  20. }
  21. else if (Application.Top is { })
  22. {
  23. attr = Application.Top.GetNormalColor ();
  24. }
  25. return new (
  26. new Attribute (
  27. ShadowStyle == ShadowStyle.Opaque ? Color.Black : attr.Foreground.GetDarkerColor (),
  28. ShadowStyle == ShadowStyle.Opaque ? attr.Background : attr.Background.GetDarkerColor ()));
  29. }
  30. return base.GetNormalColor ();
  31. }
  32. /// <inheritdoc />
  33. protected override bool OnClearingViewport (Rectangle viewport)
  34. {
  35. // Prevent clearing (so we can have transparency)
  36. return true;
  37. }
  38. /// <inheritdoc/>
  39. protected override bool OnDrawingContent (Rectangle viewport)
  40. {
  41. switch (ShadowStyle)
  42. {
  43. case ShadowStyle.Opaque:
  44. if (Orientation == Orientation.Vertical)
  45. {
  46. DrawVerticalShadowOpaque (viewport);
  47. }
  48. else
  49. {
  50. DrawHorizontalShadowOpaque (viewport);
  51. }
  52. break;
  53. case ShadowStyle.Transparent:
  54. //Attribute prevAttr = Driver.GetAttribute ();
  55. //var attr = new Attribute (prevAttr.Foreground, prevAttr.Background);
  56. //SetAttribute (attr);
  57. if (Orientation == Orientation.Vertical)
  58. {
  59. DrawVerticalShadowTransparent (viewport);
  60. }
  61. else
  62. {
  63. DrawHorizontalShadowTransparent (viewport);
  64. }
  65. //SetAttribute (prevAttr);
  66. break;
  67. }
  68. return true;
  69. }
  70. /// <summary>
  71. /// Gets or sets the orientation of the shadow.
  72. /// </summary>
  73. public Orientation Orientation { get; set; }
  74. public override ShadowStyle ShadowStyle
  75. {
  76. get => _shadowStyle;
  77. set
  78. {
  79. Visible = value != ShadowStyle.None;
  80. _shadowStyle = value;
  81. }
  82. }
  83. private void DrawHorizontalShadowOpaque (Rectangle rectangle)
  84. {
  85. // Draw the start glyph
  86. AddRune (0, 0, Glyphs.ShadowHorizontalStart);
  87. // Fill the rest of the rectangle with the glyph - note we skip the last since vertical will draw it
  88. for (var i = 1; i < rectangle.Width - 1; i++)
  89. {
  90. AddRune (i, 0, Glyphs.ShadowHorizontal);
  91. }
  92. // Last is special
  93. AddRune (rectangle.Width - 1, 0, Glyphs.ShadowHorizontalEnd);
  94. }
  95. private void DrawHorizontalShadowTransparent (Rectangle viewport)
  96. {
  97. Rectangle screen = ViewportToScreen (viewport);
  98. // Fill the rest of the rectangle - note we skip the last since vertical will draw it
  99. for (int i = Math.Max(0, screen.X + 1); i < screen.X + screen.Width - 1; i++)
  100. {
  101. Driver?.Move (i, screen.Y);
  102. if (i < Driver?.Contents!.GetLength (1) && screen.Y < Driver?.Contents?.GetLength (0))
  103. {
  104. Driver.AddRune (Driver.Contents [screen.Y, i].Rune);
  105. }
  106. }
  107. }
  108. private void DrawVerticalShadowOpaque (Rectangle viewport)
  109. {
  110. // Draw the start glyph
  111. AddRune (0, 0, Glyphs.ShadowVerticalStart);
  112. // Fill the rest of the rectangle with the glyph
  113. for (var i = 1; i < viewport.Height; i++)
  114. {
  115. AddRune (0, i, Glyphs.ShadowVertical);
  116. }
  117. }
  118. private void DrawVerticalShadowTransparent (Rectangle viewport)
  119. {
  120. Rectangle screen = ViewportToScreen (viewport);
  121. // Fill the rest of the rectangle
  122. for (int i = Math.Max (0, screen.Y); i < screen.Y + viewport.Height; i++)
  123. {
  124. Driver?.Move (screen.X, i);
  125. if (Driver?.Contents is { } && screen.X < Driver.Contents.GetLength (1) && i < Driver.Contents.GetLength (0))
  126. {
  127. Driver.AddRune (Driver.Contents [i, screen.X].Rune);
  128. }
  129. }
  130. }
  131. }