Added all views tester for draw/layout.

Made Adornment support being a subview for testing purposes.
This commit is contained in:
Tig
2024-10-22 10:43:17 -06:00
parent fe2497ef25
commit 262c6710ac
9 changed files with 131 additions and 14 deletions

View File

@@ -1,6 +1,7 @@
#nullable enable
using System.ComponentModel;
using Terminal.Gui;
using static Terminal.Gui.SpinnerStyle;
using Attribute = Terminal.Gui.Attribute;
/// <summary>
@@ -15,7 +16,7 @@ using Attribute = Terminal.Gui.Attribute;
/// mouse input. Each can be customized by manipulating their Subviews.
/// </para>
/// </remarsk>
public class Adornment : View
public class Adornment : View, IDesignable
{
/// <inheritdoc/>
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 <see cref="Parent"/>); setting this property will throw
/// <see cref="InvalidOperationException"/>.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
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
/// </remarks>
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
/// <inheritdoc/>
bool IDesignable.EnableForDesign ()
{
Thickness = new (3);
Frame = new (0, 0, 10, 10);
Diagnostics = ViewDiagnosticFlags.Padding;
return true;
}
}

View File

@@ -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 ();

View File

@@ -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++;
}
}

View File

@@ -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)'■');
}

View File

@@ -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 ();

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -807,4 +807,6 @@ public class SetLayoutTests (ITestOutputHelper output)
Assert.Equal (19, v2.Frame.Height);
t.Dispose ();
}
}