diff --git a/Terminal.Gui/TextEffects/New/GradientFill.cs b/Terminal.Gui/TextEffects/New/GradientFill.cs index e17351469..a6d69f4e3 100644 --- a/Terminal.Gui/TextEffects/New/GradientFill.cs +++ b/Terminal.Gui/TextEffects/New/GradientFill.cs @@ -17,15 +17,19 @@ public class GradientFill : IFill public GradientFill (Rectangle area, Gradient gradient, Gradient.Direction direction) { - _map = + _map = gradient.BuildCoordinateColorMapping (area.Height, area.Width, direction) - .ToDictionary( - (k)=> new Point(k.Key.Column,k.Key.Row), - (v)=> new Terminal.Gui.Color (v.Value.R, v.Value.G, v.Value.B)); + .ToDictionary ( + (k) => new Point (k.Key.Column, k.Key.Row), + (v) => new Terminal.Gui.Color (v.Value.R, v.Value.G, v.Value.B)); } public Terminal.Gui.Color GetColor (Point point) { - return _map [point]; + if (_map.TryGetValue (point, out var color)) + { + return color; + } + return new Terminal.Gui.Color (0, 0, 0); // Default to black if point not found } -} +} \ No newline at end of file diff --git a/UICatalog/Scenarios/TextEffectsScenario.cs b/UICatalog/Scenarios/TextEffectsScenario.cs index 5cfd265f2..b8e65b8c2 100644 --- a/UICatalog/Scenarios/TextEffectsScenario.cs +++ b/UICatalog/Scenarios/TextEffectsScenario.cs @@ -24,6 +24,7 @@ public class TextEffectsScenario : Scenario { Width = Dim.Fill(), Height = Dim.Fill (), + Title = "Text Effects Scenario" }; w.Loaded += (s, e) => @@ -34,7 +35,11 @@ public class TextEffectsScenario : Scenario }; w.SizeChanging += (s,e)=> { - SetupGradientLineCanvas (w, e.Size); + if(e.Size.HasValue) + { + SetupGradientLineCanvas (w, e.Size.Value); + } + // TODO: Does not work //SetupGradientLineCanvas (tabView, tabView.Frame.Size); }; @@ -87,14 +92,14 @@ public class TextEffectsScenario : Scenario } - private void SetupGradientLineCanvas (View w, Size? size) + private void SetupGradientLineCanvas (View w, Size size) { - GetAppealingGradientColors (out var stops, out var steps); + GetAppealingGradientColors (size, out var stops, out var steps); var g = new Gradient (stops, steps); var fore = new GradientFill ( - new Rectangle (0, 0, size.Value.Width, size.Value.Height), g, Gradient.Direction.Diagonal); + new Rectangle (0, 0, size.Width, size.Height), g, Gradient.Direction.Diagonal); var back = new SolidFill (new Terminal.Gui.Color (ColorName.Black)); w.LineCanvas.Fill = new FillPair ( @@ -102,7 +107,7 @@ public class TextEffectsScenario : Scenario back); } - private void GetAppealingGradientColors (out List stops, out List steps) + private void GetAppealingGradientColors (Size size, out List stops, out List steps) { // Define the colors of the gradient stops with more appealing colors stops = new List @@ -114,8 +119,11 @@ public class TextEffectsScenario : Scenario Color.FromRgb(255, 0, 128) // Bright Pink }; - // Define the number of steps between each color for smoother transitions - steps = new List { 15, 15, 15, 15 }; // 15 steps between each color + // Calculate the number of steps based on the size + int maxSteps = Math.Max (size.Width, size.Height); + + // Define the number of steps between each color for smoother transitions + steps = new List { maxSteps / 4, maxSteps / 4, maxSteps / 4, maxSteps / 4 }; } } diff --git a/UnitTests/TextEffects/New/GradientFillTests.cs b/UnitTests/TextEffects/New/GradientFillTests.cs new file mode 100644 index 000000000..400425dc5 --- /dev/null +++ b/UnitTests/TextEffects/New/GradientFillTests.cs @@ -0,0 +1,111 @@ +namespace Terminal.Gui.TextEffects.Tests; + +public class GradientFillTests +{ + private Gradient _gradient; + + public GradientFillTests () + { + // Define the colors of the gradient stops + var stops = new List + { + Color.FromRgb(255, 0, 0), // Red + Color.FromRgb(0, 0, 255) // Blue + }; + + // Define the number of steps between each color + var steps = new List { 10 }; // 10 steps between Red -> Blue + + _gradient = new Gradient (stops, steps, loop: false); + } + + [Fact] + public void TestGradientFillCorners () + { + var area = new Rectangle (0, 0, 10, 10); + var gradientFill = new GradientFill (area, _gradient, Gradient.Direction.Diagonal); + + // Test the corners + var topLeft = new Point (0, 0); + var topRight = new Point (area.Width - 1, 0); + var bottomLeft = new Point (0, area.Height - 1); + var bottomRight = new Point (area.Width - 1, area.Height - 1); + + var topLeftColor = gradientFill.GetColor (topLeft); + var topRightColor = gradientFill.GetColor (topRight); + var bottomLeftColor = gradientFill.GetColor (bottomLeft); + var bottomRightColor = gradientFill.GetColor (bottomRight); + + // Validate the colors at the corners + Assert.NotNull (topLeftColor); + Assert.NotNull (topRightColor); + Assert.NotNull (bottomLeftColor); + Assert.NotNull (bottomRightColor); + + // Expected colors + var expectedTopLeftColor = new Terminal.Gui.Color (255, 0, 0); // Red + var expectedBottomRightColor = new Terminal.Gui.Color (0, 0, 255); // Blue + + Assert.Equal (expectedTopLeftColor, topLeftColor); + Assert.Equal (expectedBottomRightColor, bottomRightColor); + + // Additional checks can be added to verify the exact expected colors if known + Console.WriteLine ($"Top-left: {topLeftColor}"); + Console.WriteLine ($"Top-right: {topRightColor}"); + Console.WriteLine ($"Bottom-left: {bottomLeftColor}"); + Console.WriteLine ($"Bottom-right: {bottomRightColor}"); + } + + [Fact] + public void TestGradientFillColorTransition () + { + var area = new Rectangle (0, 0, 10, 10); + var gradientFill = new GradientFill (area, _gradient, Gradient.Direction.Diagonal); + + for (int row = 0; row < area.Height; row++) + { + int previousRed = 255; + int previousBlue = 0; + + for (int col = 0; col < area.Width; col++) + { + var point = new Point (col, row); + var color = gradientFill.GetColor (point); + + // Ensure color is not null + Assert.NotNull (color); + + // Check if the current color is 'more blue' and 'less red' as it goes right and down + Assert.True (color.R <= previousRed, $"Failed at ({col}, {row}): {color.R} > {previousRed}"); + Assert.True (color.B >= previousBlue, $"Failed at ({col}, {row}): {color.B} < {previousBlue}"); + + // Update the previous color values for the next iteration + previousRed = color.R; + previousBlue = color.B; + } + } + + for (int col = 0; col < area.Width; col++) + { + int previousRed = 255; + int previousBlue = 0; + + for (int row = 0; row < area.Height; row++) + { + var point = new Point (col, row); + var color = gradientFill.GetColor (point); + + // Ensure color is not null + Assert.NotNull (color); + + // Check if the current color is 'more blue' and 'less red' as it goes right and down + Assert.True (color.R <= previousRed, $"Failed at ({col}, {row}): {color.R} > {previousRed}"); + Assert.True (color.B >= previousBlue, $"Failed at ({col}, {row}): {color.B} < {previousBlue}"); + + // Update the previous color values for the next iteration + previousRed = color.R; + previousBlue = color.B; + } + } + } +}