diff --git a/Examples/UICatalog/Scenarios/ShadowStyleDemo.cs b/Examples/UICatalog/Scenarios/ShadowStyleDemo.cs
index 189ca0ef7b..8392bb66af 100644
--- a/Examples/UICatalog/Scenarios/ShadowStyleDemo.cs
+++ b/Examples/UICatalog/Scenarios/ShadowStyleDemo.cs
@@ -12,30 +12,31 @@ public override void Main ()
using IApplication app = Application.Create ();
app.Init ();
- using Window window = new ()
- {
- Id = "app",
- Title = GetQuitKeyAndName ()
- };
+ using Window window = new ();
+ window.Id = "app";
+ window.Title = GetQuitKeyAndName ();
+ window.SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Accent);
AdornmentsEditor editor = new ()
{
- Id = "editor",
+ BorderStyle = LineStyle.Single,
AutoSelectViewToEdit = true,
- ShowViewIdentifier = true
- };
- editor.Initialized += (_, _) => editor.MarginEditor!.ExpanderButton!.Collapsed = false;
- window.Add (editor);
+ // This is for giggles, to show that the editor can be moved around.
+ Arrangement = ViewArrangement.Movable,
+ Id = "editor"
+ };
+ editor.Border.Thickness = new Thickness (1, 2, 1, 1);
Window shadowWindow = new ()
{
Id = "shadowWindow",
- X = Pos.Right (editor),
+ X = Pos.Center (),
Y = 0,
Width = Dim.Percent (30),
Height = Dim.Percent (30),
Title = "Shadow Window",
+ SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Accent),
Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped,
BorderStyle = LineStyle.Double,
ShadowStyle = ShadowStyles.Transparent
@@ -51,11 +52,11 @@ public override void Main ()
{
Id = "buttonInWin",
X = Pos.Center (),
- Y = Pos.Center (), Text = "Button in Window",
+ Y = Pos.Center (),
+ Text = "Button in Window",
ShadowStyle = ShadowStyles.Opaque
};
shadowWindow.Add (buttonInWin);
- window.Add (shadowWindow);
Window shadowWindow2 = new ()
{
@@ -65,17 +66,18 @@ public override void Main ()
Width = Dim.Percent (30),
Height = Dim.Percent (30),
Title = "Shadow Window #2",
+ SchemeName = SchemeManager.SchemesToSchemeName (Schemes.Error),
Arrangement = ViewArrangement.Movable | ViewArrangement.Overlapped,
BorderStyle = LineStyle.Double,
ShadowStyle = ShadowStyles.Transparent
};
- window.Add (shadowWindow2);
Button button = new ()
{
Id = "button",
X = Pos.Right (editor) + 10,
- Y = Pos.Center (), Text = "Button",
+ Y = Pos.Center (),
+ Text = "Button",
ShadowStyle = ShadowStyles.Opaque
};
button.Accepting += ButtonOnAccepting;
@@ -84,7 +86,7 @@ public override void Main ()
{
Title = "ColorPicker to illustrate highlight (currently broken)",
BorderStyle = LineStyle.Dotted,
- Id = "colorPicker16",
+ Id = "colorPicker",
X = Pos.Center (),
Y = Pos.AnchorEnd (),
Width = Dim.Percent (80)
@@ -93,13 +95,18 @@ public override void Main ()
colorPicker.ValueChanged += (_, args) =>
{
Attribute normal = window.GetScheme ().Normal;
- window.SetScheme (window.GetScheme () with { Normal = new (normal.Foreground, args.NewValue ?? Color.Black) });
+
+ window.SetScheme (window.GetScheme () with
+ {
+ Normal = new Attribute (normal.Foreground, args.NewValue ?? Color.Black)
+ });
};
- window.Add (button, colorPicker);
+ window.Add (button, colorPicker, editor, shadowWindow, shadowWindow2);
+ editor.ShowViewIdentifier = true;
editor.AutoSelectViewToEdit = true;
editor.AutoSelectSuperView = window;
- editor.AutoSelectAdornments = false;
+ editor.AutoSelectAdornments = true;
app.Run (window);
}
diff --git a/Terminal.Gui/ViewBase/Adornment/Margin.cs b/Terminal.Gui/ViewBase/Adornment/Margin.cs
index 59c2281831..3e49b781bb 100644
--- a/Terminal.Gui/ViewBase/Adornment/Margin.cs
+++ b/Terminal.Gui/ViewBase/Adornment/Margin.cs
@@ -56,7 +56,7 @@ protected override void OnThicknessChanged ()
///
public ShadowStyles? ShadowStyle
{
- get => field ?? Parent?.SuperView?.ShadowStyle ?? null;
+ get => field;
set
{
if (field == value)
@@ -68,7 +68,11 @@ public ShadowStyles? ShadowStyle
if (field is null)
{
// null means no shadow and no thickness
- (View as MarginView)?.SetShadow (null);
+ if (View is MarginView mv)
+ {
+ mv.SetShadow (null);
+ mv.ShadowSize = Size.Empty;
+ }
return;
}
diff --git a/Tests/UnitTestsParallelizable/ViewBase/Adornment/ShadowTests.cs b/Tests/UnitTestsParallelizable/ViewBase/Adornment/ShadowTests.cs
index 6d4d55f6d4..353258d848 100644
--- a/Tests/UnitTestsParallelizable/ViewBase/Adornment/ShadowTests.cs
+++ b/Tests/UnitTestsParallelizable/ViewBase/Adornment/ShadowTests.cs
@@ -128,7 +128,7 @@ public void Changing_ShadowStyle_Correctly_Set_ShadowWidth_ShadowHeight_Thicknes
Assert.Equal (new Thickness (0, 0, 2, 2), view.Margin.Thickness);
view.ShadowStyle = null;
- Assert.Equal (new Size (2, 2), (view.Margin.View as MarginView)?.ShadowSize);
+ Assert.Equal (Size.Empty, (view.Margin.View as MarginView)?.ShadowSize);
Assert.Equal (new Thickness (0, 0, 0, 0), view.Margin.Thickness);
view.ShadowStyle = ShadowStyles.Opaque;
@@ -577,4 +577,62 @@ public void TransparentShadow_OverWide_Draws_Transparent_At_Driver_Output ()
output,
app.Driver);
}
+
+ ///
+ /// Proves Issue #5088: ShadowStyle getter returns an inherited value from
+ /// SuperView even though no shadow was ever set on the view itself. Reading the
+ /// value and writing it back should be a no-op, but instead it creates a
+ /// MarginView and adds shadow thickness.
+ ///
+ [Fact]
+ public void ShadowStyle_Getter_Does_Not_Inherit_From_SuperView ()
+ {
+ // Explicitly give the SuperView a transparent shadow for this inheritance test.
+ Window superView = new () { Width = 20, Height = 10, ShadowStyle = ShadowStyles.Transparent };
+
+ View child = new () { Width = 5, Height = 3 };
+ superView.Add (child);
+
+ // The subview was never assigned a ShadowStyle - it must be null.
+ Assert.Null (child.Margin.ShadowStyle);
+ Assert.Null (child.ShadowStyle);
+
+ // Round-trip: reading and writing back should be a safe no-op.
+ ShadowStyles? readBack = child.ShadowStyle;
+ child.ShadowStyle = readBack;
+
+ // After the round-trip the subview must still have no shadow and no Margin thickness.
+ Assert.Null (child.ShadowStyle);
+ Assert.Equal (Thickness.Empty, child.Margin.Thickness);
+
+ // MarginView should NOT have been created by a no-op assignment.
+ Assert.Null (child.Margin.View);
+
+ child.Dispose ();
+ superView.Dispose ();
+ }
+
+ ///
+ /// Proves that setting ShadowStyle to null resets ShadowSize on the MarginView
+ /// to , so that state is consistent when no shadow is active.
+ ///
+ [Fact]
+ public void Setting_ShadowStyle_Null_Resets_ShadowSize ()
+ {
+ View view = new ();
+
+ // Set a shadow - this creates a MarginView with ShadowSize {1,1}.
+ view.ShadowStyle = ShadowStyles.Transparent;
+ var marginView = view.Margin.View as MarginView;
+ Assert.NotNull (marginView);
+ Assert.Equal (new Size (1, 1), marginView.ShadowSize);
+
+ // Now clear the shadow.
+ view.ShadowStyle = null;
+
+ // ShadowSize should be reset to Empty - no residual state.
+ Assert.Equal (Size.Empty, marginView.ShadowSize);
+
+ view.Dispose ();
+ }
}