diff --git a/Terminal.Gui/View/Adornment/Adornment.cs b/Terminal.Gui/View/Adornment/Adornment.cs
index 08ff83691..0f30216f9 100644
--- a/Terminal.Gui/View/Adornment/Adornment.cs
+++ b/Terminal.Gui/View/Adornment/Adornment.cs
@@ -1,6 +1,7 @@
#nullable enable
using System.ComponentModel;
using Terminal.Gui;
+using static Terminal.Gui.SpinnerStyle;
using Attribute = Terminal.Gui.Attribute;
///
@@ -15,7 +16,7 @@ using Attribute = Terminal.Gui.Attribute;
/// mouse input. Each can be customized by manipulating their Subviews.
///
///
-public class Adornment : View
+public class Adornment : View, IDesignable
{
///
public Adornment ()
@@ -63,6 +64,7 @@ public class Adornment : View
{
Parent?.SetAdornmentFrames ();
SetLayoutNeeded ();
+ SetNeedsDisplay ();
//Parent?.SetLayoutNeeded ();
OnThicknessChanged ();
@@ -88,9 +90,12 @@ public class Adornment : View
/// Adornments cannot be used as sub-views (see ); setting this property will throw
/// .
///
+ ///
+ /// While there are no real use cases for an Adornment being a subview, it is not explicitly dis-allowed to support testing. E.g. in AllViewsTester.
+ ///
public override View? SuperView
{
- get => null!;
+ get => base.SuperView!;
set => throw new InvalidOperationException (@"Adornments can not be Subviews or have SuperViews. Use Parent instead.");
}
@@ -115,7 +120,7 @@ public class Adornment : View
///
public override Rectangle Viewport
{
- get => Frame with { Location = Point.Empty };
+ get => base.Viewport;
set => throw new InvalidOperationException (@"The Viewport of an Adornment cannot be modified.");
}
@@ -124,6 +129,14 @@ public class Adornment : View
{
if (Parent is null)
{
+ // While there are no real use cases for an Adornment being a subview, we support it for
+ // testing. E.g. in AllViewsTester.
+ if (SuperView is { })
+ {
+ Point super = SuperView.ViewportToScreen (Frame.Location);
+
+ return new (super, Frame.Size);
+ }
return Frame;
}
@@ -254,4 +267,15 @@ public class Adornment : View
// }
//}
#endregion Mouse Support
+
+
+ ///
+ bool IDesignable.EnableForDesign ()
+ {
+ Thickness = new (3);
+ Frame = new (0, 0, 10, 10);
+ Diagnostics = ViewDiagnosticFlags.Padding;
+
+ return true;
+ }
}
diff --git a/Terminal.Gui/View/Adornment/Border.cs b/Terminal.Gui/View/Adornment/Border.cs
index 9a36b583e..e37bbccce 100644
--- a/Terminal.Gui/View/Adornment/Border.cs
+++ b/Terminal.Gui/View/Adornment/Border.cs
@@ -191,7 +191,7 @@ public class Border : Adornment
// TODO: Make Border.LineStyle inherit from the SuperView hierarchy
// TODO: Right now, Window and FrameView use CM to set BorderStyle, which negates
// TODO: all this.
- return Parent!.SuperView?.BorderStyle ?? LineStyle.None;
+ return Parent?.SuperView?.BorderStyle ?? LineStyle.None;
}
set => _lineStyle = value;
}
@@ -634,12 +634,15 @@ public class Border : Adornment
int maxTitleWidth = Math.Max (
0,
Math.Min (
- Parent!.TitleTextFormatter.FormatAndGetSize ().Width,
+ Parent?.TitleTextFormatter.FormatAndGetSize ().Width ?? 0,
Math.Min (screenBounds.Width - 4, borderBounds.Width - 4)
)
);
- Parent.TitleTextFormatter.ConstrainToSize = new (maxTitleWidth, 1);
+ if (Parent is { })
+ {
+ Parent.TitleTextFormatter.ConstrainToSize = new (maxTitleWidth, 1);
+ }
int sideLineLength = borderBounds.Height;
bool canDrawBorder = borderBounds is { Width: > 0, Height: > 0 };
@@ -678,7 +681,7 @@ public class Border : Adornment
}
}
- if (canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && Settings.FastHasFlags (BorderSettings.Title) && !string.IsNullOrEmpty (Parent?.Title))
+ if (Parent is {} && canDrawBorder && Thickness.Top > 0 && maxTitleWidth > 0 && Settings.FastHasFlags (BorderSettings.Title) && !string.IsNullOrEmpty (Parent?.Title))
{
Attribute focus = Parent.GetNormalColor ();
diff --git a/Terminal.Gui/Views/ColorPicker.16.cs b/Terminal.Gui/Views/ColorPicker.16.cs
index 5504e623e..2bb0492d3 100644
--- a/Terminal.Gui/Views/ColorPicker.16.cs
+++ b/Terminal.Gui/Views/ColorPicker.16.cs
@@ -135,7 +135,7 @@ public class ColorPicker16 : View
{
base.OnDrawContent (viewport);
- Driver.SetAttribute (HasFocus ? ColorScheme.Focus : GetNormalColor ());
+ Driver?.SetAttribute (HasFocus ? ColorScheme.Focus : GetNormalColor ());
var colorIndex = 0;
for (var y = 0; y < Math.Max (2, viewport.Height / BoxHeight); y++)
@@ -149,7 +149,7 @@ public class ColorPicker16 : View
continue;
}
- Driver.SetAttribute (new ((ColorName16)foregroundColorIndex, (ColorName16)colorIndex));
+ Driver?.SetAttribute (new ((ColorName16)foregroundColorIndex, (ColorName16)colorIndex));
bool selected = x == Cursor.X && y == Cursor.Y;
DrawColorBox (x, y, selected);
colorIndex++;
@@ -223,7 +223,7 @@ public class ColorPicker16 : View
for (var zoomedX = 0; zoomedX < BoxWidth; zoomedX++)
{
Move (x * BoxWidth + zoomedX, y * BoxHeight + zoomedY);
- Driver.AddRune ((Rune)' ');
+ Driver?.AddRune ((Rune)' ');
index++;
}
}
diff --git a/Terminal.Gui/Views/ColorPicker.cs b/Terminal.Gui/Views/ColorPicker.cs
index 5acb61f10..51eb4587e 100644
--- a/Terminal.Gui/Views/ColorPicker.cs
+++ b/Terminal.Gui/Views/ColorPicker.cs
@@ -103,7 +103,7 @@ public partial class ColorPicker : View
{
base.OnDrawContent (viewport);
Attribute normal = GetNormalColor ();
- Driver.SetAttribute (new (SelectedColor, normal.Background));
+ Driver?.SetAttribute (new (SelectedColor, normal.Background));
int y = _bars.Count + (Style.ShowColorName ? 1 : 0);
AddRune (13, y, (Rune)'■');
}
diff --git a/Terminal.Gui/Views/TextField.cs b/Terminal.Gui/Views/TextField.cs
index 0b08e1f04..c69f482d6 100644
--- a/Terminal.Gui/Views/TextField.cs
+++ b/Terminal.Gui/Views/TextField.cs
@@ -997,11 +997,11 @@ public class TextField : View
}
}
- Driver.SetAttribute (GetFocusColor ());
+ Driver?.SetAttribute (GetFocusColor ());
for (int i = col; i < width; i++)
{
- Driver.AddRune ((Rune)' ');
+ Driver?.AddRune ((Rune)' ');
}
PositionCursor ();
diff --git a/UICatalog/Scenarios/AllViewsTester.cs b/UICatalog/Scenarios/AllViewsTester.cs
index 804ab8c3c..d0b286d33 100644
--- a/UICatalog/Scenarios/AllViewsTester.cs
+++ b/UICatalog/Scenarios/AllViewsTester.cs
@@ -360,7 +360,6 @@ public class AllViewsTester : Scenario
// Instantiate view
var view = (View)Activator.CreateInstance (type);
-
if (view is IDesignable designable)
{
designable.EnableForDesign (ref _demoText);
@@ -384,6 +383,7 @@ public class AllViewsTester : Scenario
view.Initialized += CurrentView_Initialized;
view.LayoutComplete += CurrentView_LayoutComplete;
+ view.Id = "_curView";
_curView = view;
_hostPane.Add (_curView);
}
diff --git a/UnitTests/View/Draw/AllViewsDrawTests.cs b/UnitTests/View/Draw/AllViewsDrawTests.cs
new file mode 100644
index 000000000..183499777
--- /dev/null
+++ b/UnitTests/View/Draw/AllViewsDrawTests.cs
@@ -0,0 +1,47 @@
+using Xunit.Abstractions;
+
+namespace Terminal.Gui.LayoutTests;
+
+public class AllViewsDrawTests (ITestOutputHelper _output) : TestsAllViews
+{
+ [Theory]
+ [MemberData (nameof (AllViewTypes))]
+ public void AllViews_Does_Not_Layout (Type viewType)
+ {
+ var view = (View)CreateInstanceIfNotGeneric (viewType);
+
+ if (view == null)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
+
+ return;
+ }
+
+ if (view is IDesignable designable)
+ {
+ designable.EnableForDesign ();
+ }
+
+ var drawContentCount = 0;
+ view.DrawContent += (s, e) => drawContentCount++;
+
+ var layoutStartedCount = 0;
+ view.LayoutStarted += (s, e) => layoutStartedCount++;
+
+ var layoutCompleteCount = 0;
+ view.LayoutComplete += (s, e) => layoutCompleteCount++;
+
+ view.SetLayoutNeeded ();
+ view.Layout ();
+
+ Assert.Equal (0, drawContentCount);
+ Assert.Equal (1, layoutStartedCount);
+ Assert.Equal (1, layoutCompleteCount);
+
+ view.Draw ();
+
+ Assert.Equal (1, drawContentCount);
+ Assert.Equal (1, layoutStartedCount);
+ Assert.Equal (1, layoutCompleteCount);
+ }
+}
diff --git a/UnitTests/View/Layout/LayoutTests.cs b/UnitTests/View/Layout/LayoutTests.cs
new file mode 100644
index 000000000..91f899241
--- /dev/null
+++ b/UnitTests/View/Layout/LayoutTests.cs
@@ -0,0 +1,41 @@
+using Xunit.Abstractions;
+
+namespace Terminal.Gui.LayoutTests;
+
+public class LayoutTests (ITestOutputHelper _output) : TestsAllViews
+{
+ [Theory]
+ [MemberData (nameof (AllViewTypes))]
+ public void AllViews_Layout_Does_Not_Draw (Type viewType)
+ {
+ var view = (View)CreateInstanceIfNotGeneric (viewType);
+
+ if (view == null)
+ {
+ _output.WriteLine ($"Ignoring {viewType} - It's a Generic");
+
+ return;
+ }
+
+ if (view is IDesignable designable)
+ {
+ designable.EnableForDesign ();
+ }
+
+ var drawContentCount = 0;
+ view.DrawContent += (s, e) => drawContentCount++;
+
+ var layoutStartedCount = 0;
+ view.LayoutStarted += (s, e) => layoutStartedCount++;
+
+ var layoutCompleteCount = 0;
+ view.LayoutComplete += (s, e) => layoutCompleteCount++;
+
+ view.SetLayoutNeeded ();
+ view.Layout ();
+
+ Assert.Equal (0, drawContentCount);
+ Assert.Equal (1, layoutStartedCount);
+ Assert.Equal (1, layoutCompleteCount);
+ }
+}
diff --git a/UnitTests/View/Layout/SetLayoutTests.cs b/UnitTests/View/Layout/SetLayoutTests.cs
index bef53d71d..856f67c48 100644
--- a/UnitTests/View/Layout/SetLayoutTests.cs
+++ b/UnitTests/View/Layout/SetLayoutTests.cs
@@ -807,4 +807,6 @@ public class SetLayoutTests (ITestOutputHelper output)
Assert.Equal (19, v2.Frame.Height);
t.Dispose ();
}
+
+
}