#nullable enable using Microsoft.VisualBasic; using System.Diagnostics; namespace Terminal.Gui; /// /// Draws a shadow on the right or bottom of the view. Used internally by . /// internal class ShadowView : View { private ShadowStyle _shadowStyle; /// public override Attribute GetNormalColor () { if (SuperView is Adornment adornment) { var attr = Attribute.Default; if (adornment.Parent?.SuperView is { }) { attr = adornment.Parent.SuperView.GetNormalColor (); } else if (Application.Top is { }) { attr = Application.Top.GetNormalColor (); } return new ( new Attribute ( ShadowStyle == ShadowStyle.Opaque ? Color.Black : attr.Foreground.GetDarkerColor (), ShadowStyle == ShadowStyle.Opaque ? attr.Background : attr.Background.GetDarkerColor ())); } return base.GetNormalColor (); } /// public override void OnDrawContent (Rectangle viewport) { //base.OnDrawContent (viewport); switch (ShadowStyle) { case ShadowStyle.Opaque: if (Orientation == Orientation.Vertical) { DrawVerticalShadowOpaque (viewport); } else { DrawHorizontalShadowOpaque (viewport); } break; case ShadowStyle.Transparent: //Attribute prevAttr = Driver.GetAttribute (); //var attr = new Attribute (prevAttr.Foreground, prevAttr.Background); //Driver.SetAttribute (attr); if (Orientation == Orientation.Vertical) { DrawVerticalShadowTransparent (viewport); } else { DrawHorizontalShadowTransparent (viewport); } //Driver.SetAttribute (prevAttr); break; } } /// /// Gets or sets the orientation of the shadow. /// public Orientation Orientation { get; set; } public override ShadowStyle ShadowStyle { get => _shadowStyle; set { Visible = value != ShadowStyle.None; _shadowStyle = value; } } private void DrawHorizontalShadowOpaque (Rectangle rectangle) { // Draw the start glyph AddRune (0, 0, Glyphs.ShadowHorizontalStart); // Fill the rest of the rectangle with the glyph - note we skip the last since vertical will draw it for (var i = 1; i < rectangle.Width - 1; i++) { AddRune (i, 0, Glyphs.ShadowHorizontal); } // Last is special AddRune (rectangle.Width - 1, 0, Glyphs.ShadowHorizontalEnd); } private void DrawHorizontalShadowTransparent (Rectangle viewport) { Rectangle screen = ViewportToScreen (viewport); // Fill the rest of the rectangle - note we skip the last since vertical will draw it for (int i = screen.X; i < screen.X + screen.Width - 1; i++) { Driver.Move (i, screen.Y); if (i < Driver.Contents!.GetLength (1) && screen.Y < Driver.Contents.GetLength (0)) { Driver.AddRune (Driver.Contents [screen.Y, i].Rune); } } } private void DrawVerticalShadowOpaque (Rectangle viewport) { // Draw the start glyph AddRune (0, 0, Glyphs.ShadowVerticalStart); // Fill the rest of the rectangle with the glyph for (var i = 1; i < viewport.Height; i++) { AddRune (0, i, Glyphs.ShadowVertical); } } private void DrawVerticalShadowTransparent (Rectangle viewport) { Rectangle screen = ViewportToScreen (viewport); // Fill the rest of the rectangle for (int i = screen.Y; i < screen.Y + viewport.Height; i++) { Driver.Move (screen.X, i); if (Driver.Contents is { } && screen.X < Driver.Contents.GetLength (1) && i < Driver.Contents.GetLength (0)) { Driver.AddRune (Driver.Contents [i, screen.X].Rune); } } } }