Tig 1 gadu atpakaļ
vecāks
revīzija
21c9097d52

+ 1 - 0
Terminal.Gui/Application/Application.cs

@@ -973,6 +973,7 @@ public static partial class Application
 
 
         if (state.Toplevel.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded || OverlappedChildNeedsDisplay ())
         if (state.Toplevel.NeedsDisplay || state.Toplevel.SubViewNeedsDisplay || state.Toplevel.LayoutNeeded || OverlappedChildNeedsDisplay ())
         {
         {
+            state.Toplevel.SetNeedsDisplay();
             state.Toplevel.Draw ();
             state.Toplevel.Draw ();
             Driver.UpdateScreen ();
             Driver.UpdateScreen ();
 
 

+ 21 - 0
Terminal.Gui/Drawing/Color.cs

@@ -259,6 +259,27 @@ public readonly partial record struct Color : ISpanParsable<Color>, IUtf8SpanPar
 
 
     }
     }
 
 
+    /// <summary>
+    /// Gets a color that is the same hue as the current color, but with a different lightness.
+    /// </summary>
+    /// <returns></returns>
+    public Color GetDarkerColor ()
+    {
+        // TODO: This is a temporary implementation; just enough to show how it could work. 
+        var hsl = ColorHelper.ColorConverter.RgbToHsl (new RGB (R, G, B));
+
+        var amount = .3;
+        if (hsl.L <= 5)
+        {
+            return DarkGray;
+        }
+        hsl.L = (byte)(hsl.L * amount);
+
+        var rgb = ColorHelper.ColorConverter.HslToRgb (hsl);
+        return new (rgb.R, rgb.G, rgb.B);
+
+    }
+
     #region Legacy Color Names
     #region Legacy Color Names
 
 
     /// <summary>The black color.</summary>
     /// <summary>The black color.</summary>

+ 212 - 2
Terminal.Gui/View/Adornment/Margin.cs

@@ -1,4 +1,5 @@
-namespace Terminal.Gui;
+#nullable enable
+namespace Terminal.Gui;
 
 
 /// <summary>The Margin for a <see cref="View"/>.</summary>
 /// <summary>The Margin for a <see cref="View"/>.</summary>
 /// <remarks>
 /// <remarks>
@@ -15,8 +16,64 @@ public class Margin : Adornment
     public Margin (View parent) : base (parent)
     public Margin (View parent) : base (parent)
     {
     {
         /* Do nothing; View.CreateAdornment requires a constructor that takes a parent */
         /* Do nothing; View.CreateAdornment requires a constructor that takes a parent */
+
+        HighlightStyle |= HighlightStyle.Pressed;
+        Highlight += Margin_Highlight;
+        LayoutStarted += Margin_LayoutStarted;
+    }
+
+    private void Margin_LayoutStarted (object? sender, LayoutEventArgs e)
+    {
+        // Adjust the shadow such that it is drawn aligned with the Border
+        if (_shadow && _rightShadow is {} && _bottomShadow is {})
+        {
+            _rightShadow.Y = Parent.Border.Thickness.Top - (Parent.Border.Thickness.Top > 2 && Parent.Border.ShowTitle ? 1 : 0);
+            _bottomShadow.X = Parent.Border.Thickness.Left;
+        }
     }
     }
 
 
+    private bool _pressed;
+    private void Margin_Highlight (object? sender, HighlightEventArgs e)
+    {
+        if (_shadow)
+        {
+            if (_pressed && e.HighlightStyle == HighlightStyle.None)
+            {
+                Thickness = new (Thickness.Left - 1, Thickness.Top, Thickness.Right + 1, Thickness.Bottom);
+
+                if (_rightShadow is { })
+                {
+                    _rightShadow.Visible = true;
+                }
+
+                if (_bottomShadow is { })
+                {
+                    _bottomShadow.Visible = true;
+                }
+
+                _pressed = false;
+                return;
+            }
+
+            if (!_pressed && (e.HighlightStyle.HasFlag (HighlightStyle.Pressed) /*|| e.HighlightStyle.HasFlag (HighlightStyle.PressedOutside)*/))
+            {
+                Thickness = new (Thickness.Left + 1, Thickness.Top, Thickness.Right - 1, Thickness.Bottom);
+                _pressed = true;
+                if (_rightShadow is { })
+                {
+                    _rightShadow.Visible = false;
+                }
+
+                if (_bottomShadow is { })
+                {
+                    _bottomShadow.Visible = false;
+                }
+            }
+        }
+
+    }
+
+
     /// <summary>
     /// <summary>
     ///     The color scheme for the Margin. If set to <see langword="null"/>, gets the <see cref="Adornment.Parent"/>'s
     ///     The color scheme for the Margin. If set to <see langword="null"/>, gets the <see cref="Adornment.Parent"/>'s
     ///     <see cref="View.SuperView"/> scheme. color scheme.
     ///     <see cref="View.SuperView"/> scheme. color scheme.
@@ -30,7 +87,7 @@ public class Margin : Adornment
                 return base.ColorScheme;
                 return base.ColorScheme;
             }
             }
 
 
-            return Parent?.SuperView?.ColorScheme ?? Colors.ColorSchemes ["TopLevel"];
+            return (Parent?.SuperView?.ColorScheme ?? Colors.ColorSchemes ["TopLevel"])!;
         }
         }
         set
         set
         {
         {
@@ -38,4 +95,157 @@ public class Margin : Adornment
             Parent?.SetNeedsDisplay ();
             Parent?.SetNeedsDisplay ();
         }
         }
     }
     }
+
+    private bool _shadow;
+
+    /// <summary>
+    ///     Gets or sets whether the Margin includes a shadow effect. The shadow is drawn on the right and bottom sides of the
+    ///     Margin.
+    /// </summary>
+    public bool EnableShadow (bool enable)
+    {
+        if (_shadow == enable)
+        {
+            return _shadow;
+        }
+
+        if (_shadow)
+        {
+            Thickness = new (Thickness.Left, Thickness.Top, Thickness.Right - 1, Thickness.Bottom - 1);
+        }
+
+        _shadow = enable;
+
+        if (_shadow)
+        {
+            Thickness = new (Thickness.Left, Thickness.Top, Thickness.Right + 1, Thickness.Bottom + 1);
+        }
+
+        if (_rightShadow is { })
+        {
+            _rightShadow.Visible = _shadow;
+        }
+
+        if (_bottomShadow is { })
+        {
+            _bottomShadow.Visible = _shadow;
+        }
+        return _shadow;
+    }
+
+    private View? _bottomShadow;
+    private View? _rightShadow;
+
+    /// <inheritdoc/>
+    public override void BeginInit ()
+    {
+        base.BeginInit ();
+
+        if (Parent is null)
+        {
+            return;
+        }
+
+        Attribute attr = Parent.GetNormalColor ();
+
+        Add (
+             _rightShadow = new ShadowView
+             {
+                 X = Pos.AnchorEnd (1),
+                 Y = 0,
+                 Width = 1,
+                 Height = Dim.Fill (),
+                 Visible = _shadow,
+                 Orientation = Orientation.Vertical
+             },
+             _bottomShadow = new ShadowView
+             {
+                 X = 0,
+                 Y = Pos.AnchorEnd (1),
+                 Width = Dim.Fill (),
+                 Height = 1,
+                 Visible = _shadow,
+                 Orientation = Orientation.Horizontal
+             }
+            );
+    }
+}
+
+/// <summary>
+///     Draws a shadow on the right or bottom of the view.
+/// </summary>
+internal class ShadowView : View
+{
+    // TODO: Add these to CM.Glyphs
+    private readonly char VERTICAL_START_GLYPH = '\u2596';
+    private readonly char VERTICAL_GLYPH = '\u258C';
+    private readonly char HORIZONTAL_START_GLYPH = '\u259d';
+    private readonly char HORIZONTAL_GLYPH = '\u2580';
+    private readonly char HORIZONTAL_END_GLYPH = '\u2598';
+
+    /// <summary>
+    ///     Gets or sets the orientation of the shadow.
+    /// </summary>
+    public Orientation Orientation { get; set; }
+
+    /// <inheritdoc />
+    public override Attribute GetNormalColor ()
+    {
+        if (SuperView is Adornment adornment)
+        {
+            if (adornment.Parent.SuperView is { })
+            {
+                Attribute attr = adornment.Parent.SuperView.GetNormalColor ();
+                return new (new Attribute (attr.Foreground.GetDarkerColor (), attr.Background));
+            }
+            else
+            {
+                Attribute attr = Application.Top.GetNormalColor ();
+                return new (new Attribute (attr.Foreground.GetDarkerColor (), attr.Background));
+            }
+        }
+        return base.GetNormalColor ();
+    }
+
+    /// <inheritdoc/>
+    public override void OnDrawContent (Rectangle viewport)
+    {
+        //base.OnDrawContent (viewport);
+
+        if (Orientation == Orientation.Vertical)
+        {
+            DrawVerticalShadow (viewport);
+        }
+        else
+        {
+            DrawHorizontalShadow (viewport);
+        }
+    }
+
+    private void DrawHorizontalShadow (Rectangle rectangle)
+    {
+        // Draw the start glyph
+        AddRune (0, 0, (Rune)HORIZONTAL_START_GLYPH);
+
+        // Fill the rest of the rectangle with the glyph
+        for (var i = 1; i < rectangle.Width - 1; i++)
+        {
+            AddRune (i, 0, (Rune)HORIZONTAL_GLYPH);
+        }
+
+        // Last is special
+        AddRune (rectangle.Width - 1, 0, (Rune)HORIZONTAL_END_GLYPH);
+    }
+
+    private void DrawVerticalShadow (Rectangle viewport)
+    {
+        // Draw the start glyph
+        AddRune (0, 0, (Rune)VERTICAL_START_GLYPH);
+
+        // Fill the rest of the rectangle with the glyph
+        for (var i = 1; i < viewport.Height; i++)
+        {
+            AddRune (0, i, (Rune)VERTICAL_GLYPH);
+        }
+    }
 }
 }

+ 30 - 0
Terminal.Gui/View/ViewAdornments.cs

@@ -59,6 +59,36 @@ public partial class View
     /// </remarks>
     /// </remarks>
     public Margin Margin { get; private set; }
     public Margin Margin { get; private set; }
 
 
+    [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+    public static bool DefaultShadow { get; set; } = false;
+
+
+    private bool _shadow;
+    /// <summary>
+    ///     Gets or sets whether the View is shown with a shadow effect. The shadow is drawn on the right and bottom sides of the
+    ///     Margin.
+    /// </summary>
+    /// <remarks>
+    ///     Setting this property to <see langword="true"/> will add a shadow to the right and bottom sides of the Margin.
+    ///     The View 's <see cref="Frame"/> will be expanded to include the shadow.
+    /// </remarks>
+    public bool Shadow
+    {
+        get => _shadow;
+        set
+        {
+            if (_shadow == value)
+            {
+                return;
+            }
+            _shadow = value;
+            if (Margin is { })
+            {
+                _shadow = Margin.EnableShadow (value);
+            }
+        }
+    }
+
     /// <summary>
     /// <summary>
     ///     The <see cref="Adornment"/> that offsets the <see cref="Viewport"/> from the <see cref="Margin"/>.
     ///     The <see cref="Adornment"/> that offsets the <see cref="Viewport"/> from the <see cref="Margin"/>.
     ///     The Border provides the space for a visual border (drawn using
     ///     The Border provides the space for a visual border (drawn using

+ 11 - 4
Terminal.Gui/View/ViewEventArgs.cs

@@ -58,8 +58,11 @@ public class DrawEventArgs : EventArgs
 public class FocusEventArgs : EventArgs
 public class FocusEventArgs : EventArgs
 {
 {
     /// <summary>Constructs.</summary>
     /// <summary>Constructs.</summary>
-    /// <param name="view">The view that gets or loses focus.</param>
-    public FocusEventArgs (View view) { View = view; }
+    /// <param name="leaving">The view that gets or loses focus.</param>
+    public FocusEventArgs (View leaving, View entering) {
+        Leaving = leaving;
+        Entering = entering;
+    }
 
 
     /// <summary>
     /// <summary>
     ///     Indicates if the current focus event has already been processed and the driver should stop notifying any other
     ///     Indicates if the current focus event has already been processed and the driver should stop notifying any other
@@ -68,6 +71,10 @@ public class FocusEventArgs : EventArgs
     /// </summary>
     /// </summary>
     public bool Handled { get; set; }
     public bool Handled { get; set; }
 
 
-    /// <summary>Indicates the current view that gets or loses focus.</summary>
-    public View View { get; set; }
+    /// <summary>Indicates the view that is losing focus.</summary>
+    public View Leaving { get; set; }
+
+    /// <summary>Indicates the view that is gaining focus.</summary>
+    public View Entering { get; set; }
+
 }
 }

+ 16 - 2
Terminal.Gui/View/ViewMouse.cs

@@ -335,14 +335,14 @@ public partial class View
 
 
             if (Viewport.Contains (mouseEvent.Position))
             if (Viewport.Contains (mouseEvent.Position))
             {
             {
-                if (SetHighlight (HighlightStyle.HasFlag (HighlightStyle.Pressed) ? HighlightStyle.Pressed : HighlightStyle.None) == true)
+                if (this is not Adornment && SetHighlight (HighlightStyle.HasFlag (HighlightStyle.Pressed) ? HighlightStyle.Pressed : HighlightStyle.None) == true)
                 {
                 {
                     return true;
                     return true;
                 }
                 }
             }
             }
             else
             else
             {
             {
-                if (SetHighlight (HighlightStyle.HasFlag (HighlightStyle.PressedOutside) ? HighlightStyle.PressedOutside : HighlightStyle.None) == true)
+                if (this is not Adornment && SetHighlight (HighlightStyle.HasFlag (HighlightStyle.PressedOutside) ? HighlightStyle.PressedOutside : HighlightStyle.None) == true)
 
 
                 {
                 {
                     return true;
                     return true;
@@ -533,6 +533,20 @@ public partial class View
         HighlightEventArgs args = new (highlight);
         HighlightEventArgs args = new (highlight);
         Highlight?.Invoke (this, args);
         Highlight?.Invoke (this, args);
 
 
+        if (args.Cancel)
+        {
+            return true;
+        }
+
+        args = new (highlight);
+        Margin?.Highlight?.Invoke (this, args);
+
+        //args = new (highlight);
+        //Border?.Highlight?.Invoke (this, args);
+
+        //args = new (highlight);
+        //Padding?.Highlight?.Invoke (this, args);
+
         return args.Cancel;
         return args.Cancel;
     }
     }
 
 

+ 2 - 2
Terminal.Gui/View/ViewSubViews.cs

@@ -505,7 +505,7 @@ public partial class View
     /// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
     /// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
     public virtual bool OnEnter (View view)
     public virtual bool OnEnter (View view)
     {
     {
-        var args = new FocusEventArgs (view);
+        var args = new FocusEventArgs (view, this);
         Enter?.Invoke (this, args);
         Enter?.Invoke (this, args);
 
 
         if (args.Handled)
         if (args.Handled)
@@ -521,7 +521,7 @@ public partial class View
     /// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
     /// <returns><c>true</c>, if the event was handled, <c>false</c> otherwise.</returns>
     public virtual bool OnLeave (View view)
     public virtual bool OnLeave (View view)
     {
     {
-        var args = new FocusEventArgs (view);
+        var args = new FocusEventArgs (this, view);
         Leave?.Invoke (this, args);
         Leave?.Invoke (this, args);
 
 
         if (args.Handled)
         if (args.Handled)

+ 10 - 1
Terminal.Gui/Views/Button.cs

@@ -33,6 +33,12 @@ public class Button : View
     private readonly Rune _rightDefault;
     private readonly Rune _rightDefault;
     private bool _isDefault;
     private bool _isDefault;
 
 
+    /// <summary>
+    /// Gets or sets whether <see cref="Button"/>s are shown with a shadow effect by default.
+    /// </summary>
+    [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+    public new static bool DefaultShadow { get; set; } = false;
+
     /// <summary>Initializes a new instance of <see cref="Button"/>.</summary>
     /// <summary>Initializes a new instance of <see cref="Button"/>.</summary>
     public Button ()
     public Button ()
     {
     {
@@ -44,14 +50,15 @@ public class Button : View
         _leftDefault = Glyphs.LeftDefaultIndicator;
         _leftDefault = Glyphs.LeftDefaultIndicator;
         _rightDefault = Glyphs.RightDefaultIndicator;
         _rightDefault = Glyphs.RightDefaultIndicator;
 
 
+        Height = Dim.Auto (DimAutoStyle.Text);
         Width = Dim.Auto (DimAutoStyle.Text);
         Width = Dim.Auto (DimAutoStyle.Text);
-        Height = Dim.Auto (DimAutoStyle.Text, minimumContentDim: 1);
 
 
         CanFocus = true;
         CanFocus = true;
         HighlightStyle |= HighlightStyle.Pressed;
         HighlightStyle |= HighlightStyle.Pressed;
 #if HOVER
 #if HOVER
         HighlightStyle |= HighlightStyle.Hover;
         HighlightStyle |= HighlightStyle.Hover;
 #endif
 #endif
+
         // Override default behavior of View
         // Override default behavior of View
         AddCommand (Command.HotKey, () =>
         AddCommand (Command.HotKey, () =>
         {
         {
@@ -64,6 +71,8 @@ public class Button : View
 
 
         TitleChanged += Button_TitleChanged;
         TitleChanged += Button_TitleChanged;
         MouseClick += Button_MouseClick;
         MouseClick += Button_MouseClick;
+
+        Shadow = DefaultShadow;
     }
     }
 
 
     private bool _wantContinuousButtonPressed;
     private bool _wantContinuousButtonPressed;

+ 4 - 0
Terminal.Gui/Views/ColorPicker.cs

@@ -107,6 +107,10 @@ public class ColorPicker : View
         get => (ColorName)_selectColorIndex;
         get => (ColorName)_selectColorIndex;
         set
         set
         {
         {
+            if (value == (ColorName)_selectColorIndex)
+            {
+                return;
+            }
             var prev = (ColorName)_selectColorIndex;
             var prev = (ColorName)_selectColorIndex;
             _selectColorIndex = (int)value;
             _selectColorIndex = (int)value;
 
 

+ 2 - 1
Terminal.Gui/Views/Dialog.cs

@@ -60,7 +60,8 @@ public class Dialog : Window
     /// <remarks>
     /// <remarks>
     ///     By default, <see cref="View.X"/>, <see cref="View.Y"/>, <see cref="View.Width"/>, and <see cref="View.Height"/> are
     ///     By default, <see cref="View.X"/>, <see cref="View.Y"/>, <see cref="View.Width"/>, and <see cref="View.Height"/> are
     ///     set
     ///     set
-    ///     such that the <see cref="Dialog"/> will be centered in, and no larger than 90% of the screen dimensions.
+    ///     such that the <see cref="Dialog"/> will be centered in, and no larger than 90% of <see cref="Application.Top"/>, if there is one. Otherwise,
+    ///     it will be bound by the screen dimensions.
     /// </remarks>
     /// </remarks>
     public Dialog ()
     public Dialog ()
     {
     {

+ 9 - 0
Terminal.Gui/Views/Window.cs

@@ -14,6 +14,14 @@ namespace Terminal.Gui;
 /// </remarks>
 /// </remarks>
 public class Window : Toplevel
 public class Window : Toplevel
 {
 {
+
+    /// <summary>
+    /// Gets or sets whether all <see cref="Window"/>s are shown with a shadow effect by default.
+    /// </summary>
+    [SerializableConfigurationProperty (Scope = typeof (ThemeScope))]
+    public static bool DefaultShadow { get; set; } = false;
+
+
     /// <summary>
     /// <summary>
     ///     Initializes a new instance of the <see cref="Window"/> class.
     ///     Initializes a new instance of the <see cref="Window"/> class.
     /// </summary>
     /// </summary>
@@ -22,6 +30,7 @@ public class Window : Toplevel
         CanFocus = true;
         CanFocus = true;
         ColorScheme = Colors.ColorSchemes ["Base"]; // TODO: make this a theme property
         ColorScheme = Colors.ColorSchemes ["Base"]; // TODO: make this a theme property
         BorderStyle = DefaultBorderStyle;
         BorderStyle = DefaultBorderStyle;
+        Shadow = DefaultShadow;
 
 
         // This enables the default button to be activated by the Enter key.
         // This enables the default button to be activated by the Enter key.
         AddCommand (
         AddCommand (

+ 2 - 0
UICatalog/Resources/config.json

@@ -33,6 +33,8 @@
     {
     {
       "UI Catalog Theme": {
       "UI Catalog Theme": {
         "Dialog.DefaultButtonAlignment": "Fill",
         "Dialog.DefaultButtonAlignment": "Fill",
+        "Button.DefaultShadow": true,
+        "Window.DefaultShadow": true,
         "ColorSchemes": [
         "ColorSchemes": [
           {
           {
             "UI Catalog Scheme": {
             "UI Catalog Scheme": {

+ 3 - 4
UICatalog/Scenarios/Adornments.cs

@@ -21,10 +21,9 @@ public class Adornments : Scenario
             AutoSelectViewToEdit = true,
             AutoSelectViewToEdit = true,
             // This is for giggles, to show that the editor can be moved around.
             // This is for giggles, to show that the editor can be moved around.
             Arrangement = ViewArrangement.Movable,
             Arrangement = ViewArrangement.Movable,
-            X = Pos.AnchorEnd()
-
+            X = Pos.AnchorEnd(),
         };
         };
-        editor.Border.Thickness = new Thickness (1, 3, 1, 1);
+        editor.Border.Thickness = new Thickness (1, 2, 1, 1);
 
 
         app.Add (editor);
         app.Add (editor);
 
 
@@ -104,7 +103,7 @@ public class Adornments : Scenario
                                   window.Padding.Add (labelInPadding);
                                   window.Padding.Add (labelInPadding);
 
 
                                   var textFieldInPadding = new TextField
                                   var textFieldInPadding = new TextField
-                                  { X = Pos.Right (labelInPadding) + 1, Y = Pos.Top (labelInPadding), Width = 15, Text = "some text" };
+                                      { X = Pos.Right (labelInPadding) + 1, Y = Pos.Top (labelInPadding), Width = 15, Text = "some text" };
                                   textFieldInPadding.Accept += (s, e) => MessageBox.Query (20, 7, "TextField", textFieldInPadding.Text, "Ok");
                                   textFieldInPadding.Accept += (s, e) => MessageBox.Query (20, 7, "TextField", textFieldInPadding.Text, "Ok");
                                   window.Padding.Add (textFieldInPadding);
                                   window.Padding.Add (textFieldInPadding);
 
 

+ 2 - 0
UICatalog/Scenarios/Buttons.cs

@@ -433,6 +433,7 @@ public class Buttons : Scenario
                 Title = $"{CM.Glyphs.DownArrow}",
                 Title = $"{CM.Glyphs.DownArrow}",
                 WantContinuousButtonPressed = true,
                 WantContinuousButtonPressed = true,
                 CanFocus = false,
                 CanFocus = false,
+                Shadow = false,
             };
             };
 
 
             _number = new ()
             _number = new ()
@@ -457,6 +458,7 @@ public class Buttons : Scenario
                 Title = $"{CM.Glyphs.UpArrow}",
                 Title = $"{CM.Glyphs.UpArrow}",
                 WantContinuousButtonPressed = true,
                 WantContinuousButtonPressed = true,
                 CanFocus = false,
                 CanFocus = false,
+                Shadow = false,
             };
             };
 
 
             CanFocus = true;
             CanFocus = true;

+ 1 - 0
UICatalog/Scenarios/ExpanderButton.cs

@@ -36,6 +36,7 @@ public class ExpanderButton : Button
         Height = 1;
         Height = 1;
         NoDecorations = true;
         NoDecorations = true;
         NoPadding = true;
         NoPadding = true;
+        Shadow = false;
 
 
         AddCommand (Command.HotKey, Toggle);
         AddCommand (Command.HotKey, Toggle);
         AddCommand (Command.ToggleExpandCollapse, Toggle);
         AddCommand (Command.ToggleExpandCollapse, Toggle);

+ 14 - 0
UICatalog/Scenarios/MarginEditor.cs

@@ -13,6 +13,20 @@ public class MarginEditor : AdornmentEditor
 
 
     private void MarginEditor_Initialized (object sender, EventArgs e)
     private void MarginEditor_Initialized (object sender, EventArgs e)
     {
     {
+        var ckbShadow = new CheckBox
+        {
+            X = 0,
+            Y = Pos.AnchorEnd (),
 
 
+            SuperViewRendersLineCanvas = true,
+            Title = "_Shadow",
+            Enabled = AdornmentToEdit is { },
+        };
+
+        ckbShadow.Toggled += (sender, args) =>
+                             {
+                                 ((Margin)AdornmentToEdit).EnableShadow (args.NewValue!.Value);
+                             };
+        Add (ckbShadow);
     }
     }
 }
 }

+ 62 - 0
UICatalog/Scenarios/ThreeD.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics.Metrics;
+using System.Linq;
+using Terminal.Gui;
+
+namespace UICatalog.Scenarios;
+
+[ScenarioMetadata ("3D Effects Demo", "Demonstrates 3D UI Effects.")]
+[ScenarioCategory ("Layout")]
+public class ThreeD : Scenario
+{
+    public override void Main ()
+    {
+        Window app = new ()
+        {
+            Title = $"{Application.QuitKey} to Quit - Scenario: {GetName ()}"
+        };
+
+
+        var editor = new AdornmentsEditor ()
+        {
+            AutoSelectViewToEdit = true,
+        };
+        app.Add (editor);
+
+        Window win = new ()
+        {
+            X = Pos.Right (editor),
+            Y = 0,
+            Width = Dim.Percent (30),
+            Height = Dim.Percent (30),
+            Title = "Shadow Window",
+            Arrangement = ViewArrangement.Movable,
+        };
+
+        var buttonInWin = new Button
+        {
+            X = Pos.Center (),
+            Y = Pos.Center (), Text = "Button in Window",
+            //Shadow = true
+        };
+        win.Add (buttonInWin);
+        app.Add (win);
+
+        var button = new Button
+        {
+            X = Pos.Right (editor) + 10,
+            Y = Pos.Center (), Text = "Button",
+        };
+        app.Add (button);
+
+
+        Application.Run (app);
+        app.Dispose ();
+
+        Application.Shutdown ();
+
+        return;
+    }
+}

+ 2 - 1
UICatalog/UICatalog.cs

@@ -330,7 +330,6 @@ internal class UICatalogApp
             // made by Scenario.Init() above
             // made by Scenario.Init() above
             // TODO: Throw if shutdown was not called already
             // TODO: Throw if shutdown was not called already
             Application.Shutdown ();
             Application.Shutdown ();
-
             VerifyObjectsWereDisposed ();
             VerifyObjectsWereDisposed ();
         }
         }
 
 
@@ -388,6 +387,8 @@ internal class UICatalogApp
 
 
         public UICatalogTopLevel ()
         public UICatalogTopLevel ()
         {
         {
+            _diagnosticFlags = View.Diagnostics;
+
             _themeMenuItems = CreateThemeMenuItems ();
             _themeMenuItems = CreateThemeMenuItems ();
             _themeMenuBarItem = new ("_Themes", _themeMenuItems);
             _themeMenuBarItem = new ("_Themes", _themeMenuItems);
 
 

+ 1 - 1
UnitTests/View/NeedsDisplayTests.cs

@@ -14,7 +14,7 @@ public class NeedsDisplayTests ()
         view.BeginInit();
         view.BeginInit();
         view.EndInit();
         view.EndInit();
         Assert.False (view.NeedsDisplay);
         Assert.False (view.NeedsDisplay);
-        Assert.False (view.SubViewNeedsDisplay);
+        //Assert.False (view.SubViewNeedsDisplay);
     }
     }
 
 
 
 

+ 1 - 1
UnitTests/Views/LabelTests.cs

@@ -247,7 +247,7 @@ This TextFormatter (tf2) with fill will be cleared on rewritten.       ",
         label.Text = "This label is rewritten.";
         label.Text = "This label is rewritten.";
         Assert.True (label.NeedsDisplay);
         Assert.True (label.NeedsDisplay);
         Assert.True (label.LayoutNeeded);
         Assert.True (label.LayoutNeeded);
-        Assert.False (label.SubViewNeedsDisplay);
+        //Assert.False (label.SubViewNeedsDisplay);
         label.Draw ();
         label.Draw ();
 
 
         tf1.Text = "This TextFormatter (tf1) is rewritten.";
         tf1.Text = "This TextFormatter (tf1) is rewritten.";

+ 5 - 5
UnitTests/Views/ToplevelTests.cs

@@ -1165,12 +1165,12 @@ public class ToplevelTests (ITestOutputHelper output)
                         if (iterations == 1)
                         if (iterations == 1)
                         {
                         {
                             steps [0] = iterations;
                             steps [0] = iterations;
-                            Assert.Null (e.View);
+                            Assert.Null (e.Leaving);
                         }
                         }
                         else
                         else
                         {
                         {
                             steps [3] = iterations;
                             steps [3] = iterations;
-                            Assert.Equal (diag, e.View);
+                            Assert.Equal (diag, e.Leaving);
                         }
                         }
                     };
                     };
 
 
@@ -1179,7 +1179,7 @@ public class ToplevelTests (ITestOutputHelper output)
                         // This will never be raised
                         // This will never be raised
                         iterations++;
                         iterations++;
                         isLeaveTop = true;
                         isLeaveTop = true;
-                        Assert.Equal (diag, e.View);
+                        Assert.Equal (diag, e.Leaving);
                     };
                     };
         top.Add (vt);
         top.Add (vt);
 
 
@@ -1205,7 +1205,7 @@ public class ToplevelTests (ITestOutputHelper output)
                         iterations++;
                         iterations++;
                         steps [1] = iterations;
                         steps [1] = iterations;
                         isEnterDiag = true;
                         isEnterDiag = true;
-                        Assert.Null (e.View);
+                        Assert.Null (e.Leaving);
                     };
                     };
 
 
         vd.Leave += (s, e) =>
         vd.Leave += (s, e) =>
@@ -1213,7 +1213,7 @@ public class ToplevelTests (ITestOutputHelper output)
                         iterations++;
                         iterations++;
                         steps [2] = iterations;
                         steps [2] = iterations;
                         isLeaveDiag = true;
                         isLeaveDiag = true;
-                        Assert.Equal (top, e.View);
+                        Assert.Equal (top, e.Entering);
                     };
                     };
         diag.Add (vd);
         diag.Add (vd);