From fb29b5c139dfda3fd03743c143ed88e27d5b9c54 Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 6 Jul 2024 20:11:55 -0600 Subject: [PATCH 1/4] Made Thickness a record struct --- Terminal.Gui/Drawing/Thickness.cs | 44 +------------------------ UnitTests/View/Adornment/BorderTests.cs | 10 +++--- 2 files changed, 6 insertions(+), 48 deletions(-) diff --git a/Terminal.Gui/Drawing/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs index ad684470b8..54178a8469 100644 --- a/Terminal.Gui/Drawing/Thickness.cs +++ b/Terminal.Gui/Drawing/Thickness.cs @@ -15,7 +15,7 @@ namespace Terminal.Gui; /// /// Use the helper API ( to draw the frame with the specified thickness. /// -public class Thickness : IEquatable +public record struct Thickness { /// Gets or sets the width of the lower side of the rectangle. [JsonInclude] @@ -240,32 +240,6 @@ rect with return GetInside (rect); } - /// Determines whether the specified object is equal to the current object. - /// The object to compare with the current object. - /// true if the specified object is equal to the current object; otherwise, false. - public override bool Equals (object obj) - { - //Check for null and compare run-time types. - if (obj is null || !GetType ().Equals (obj.GetType ())) - { - return false; - } - - return Equals ((Thickness)obj); - } - - /// - public override int GetHashCode () - { - var hashCode = 1380952125; - hashCode = hashCode * -1521134295 + Left.GetHashCode (); - hashCode = hashCode * -1521134295 + Right.GetHashCode (); - hashCode = hashCode * -1521134295 + Top.GetHashCode (); - hashCode = hashCode * -1521134295 + Bottom.GetHashCode (); - - return hashCode; - } - /// /// Returns a rectangle describing the location and size of the inside area of with the /// thickness widths subtracted. The height and width of the returned rectangle will never be less than 0. @@ -289,23 +263,7 @@ public Rectangle GetInside (Rectangle rect) return new (x, y, width, height); } - /// - public static bool operator == (Thickness left, Thickness right) { return EqualityComparer.Default.Equals (left, right); } - - /// - public static bool operator != (Thickness left, Thickness right) { return !(left == right); } - /// Returns the thickness widths of the Thickness formatted as a string. /// The thickness widths as a string. public override string ToString () { return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; } - - private int validate (int width) - { - if (width < 0) - { - throw new ArgumentException ("Thickness widths cannot be negative."); - } - - return width; - } } diff --git a/UnitTests/View/Adornment/BorderTests.cs b/UnitTests/View/Adornment/BorderTests.cs index d2f88916b1..387844dbe6 100644 --- a/UnitTests/View/Adornment/BorderTests.cs +++ b/UnitTests/View/Adornment/BorderTests.cs @@ -18,7 +18,7 @@ public void Border_Parent_HasFocus_Title_Uses_FocusAttribute () view.Border.Thickness = new (0, 1, 0, 0); view.Border.LineStyle = LineStyle.Single; - view.ColorScheme = new() + view.ColorScheme = new () { Normal = new (Color.Red, Color.Green), Focus = new (Color.Green, Color.Red) @@ -53,7 +53,7 @@ public void Border_Uses_Parent_ColorScheme () view.Border.Thickness = new (0, 1, 0, 0); view.Border.LineStyle = LineStyle.Single; - view.ColorScheme = new() + view.ColorScheme = new () { Normal = new (Color.Red, Color.Green), Focus = new (Color.Green, Color.Red) }; @@ -90,7 +90,7 @@ public void Border_With_Title_Border_Double_Thickness_Top_Four_Size_Width (int w { Title = "1234", Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Double }; - win.Border.Thickness.Top = 4; + win.Border.Thickness = win.Border.Thickness with { Top = 4 }; RunState rs = Application.Begin (win); var firstIteration = false; @@ -224,7 +224,7 @@ public void Border_With_Title_Border_Double_Thickness_Top_Three_Size_Width (int { Title = "1234", Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Double }; - win.Border.Thickness.Top = 3; + win.Border.Thickness = win.Border.Thickness with { Top = 3 }; RunState rs = Application.Begin (win); var firstIteration = false; @@ -358,7 +358,7 @@ public void Border_With_Title_Border_Double_Thickness_Top_Two_Size_Width (int wi { Title = "1234", Width = Dim.Fill (), Height = Dim.Fill (), BorderStyle = LineStyle.Double }; - win.Border.Thickness.Top = 2; + win.Border.Thickness = win.Border.Thickness with { Top = 2 }; RunState rs = Application.Begin (win); var firstIteration = false; From 4f1688f6db9f5df78fb5cc9d2513131677d61ef6 Mon Sep 17 00:00:00 2001 From: Tig Date: Sat, 6 Jul 2024 20:25:13 -0600 Subject: [PATCH 2/4] Code cleanup --- Terminal.Gui/Drawing/Thickness.cs | 109 ++++++++++++++---------------- 1 file changed, 51 insertions(+), 58 deletions(-) diff --git a/Terminal.Gui/Drawing/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs index 54178a8469..653b210ac7 100644 --- a/Terminal.Gui/Drawing/Thickness.cs +++ b/Terminal.Gui/Drawing/Thickness.cs @@ -15,24 +15,8 @@ namespace Terminal.Gui; /// /// Use the helper API ( to draw the frame with the specified thickness. /// -public record struct Thickness +public record struct Thickness { - /// Gets or sets the width of the lower side of the rectangle. - [JsonInclude] - public int Bottom; - - /// Gets or sets the width of the left side of the rectangle. - [JsonInclude] - public int Left; - - /// Gets or sets the width of the right side of the rectangle. - [JsonInclude] - public int Right; - - /// Gets or sets the width of the upper side of the rectangle. - [JsonInclude] - public int Top; - /// Initializes a new instance of the class with all widths set to 0. public Thickness () { } @@ -56,35 +40,29 @@ public Thickness (int left, int top, int right, int bottom) Bottom = bottom; } - // TODO: add operator overloads - /// Gets an empty thickness. - public static Thickness Empty => new (0); + /// Gets or sets the width of the lower side of the rectangle. + [JsonInclude] + public int Bottom { get; set; } - /// - /// Gets the total width of the left and right sides of the rectangle. Sets the width of the left and rigth sides - /// of the rectangle to half the specified value. - /// - public int Horizontal - { - get => Left + Right; - set => Left = Right = value / 2; - } + /// Gets or sets the width of the left side of the rectangle. + [JsonInclude] + public int Left { get; set; } + + /// Gets or sets the width of the right side of the rectangle. + [JsonInclude] + public int Right { get; set; } + + /// Gets or sets the width of the upper side of the rectangle. + [JsonInclude] + public int Top { get; set; } /// - /// Gets the total height of the top and bottom sides of the rectangle. Sets the height of the top and bottom - /// sides of the rectangle to half the specified value. + /// Adds the thickness widths of another to the current , returning a + /// new . /// - public int Vertical - { - get => Top + Bottom; - set => Top = Bottom = value / 2; - } - - // IEquitable - /// Indicates whether the current object is equal to another object of the same type. /// - /// true if the current object is equal to the other parameter; otherwise, false. - public bool Equals (Thickness other) { return other is { } && Left == other.Left && Right == other.Right && Top == other.Top && Bottom == other.Bottom; } + /// + public readonly Thickness Add (Thickness other) { return new (Left + other.Left, Top + other.Top, Right + other.Right, Bottom + other.Bottom); } /// /// Gets whether the specified coordinates lie within the thickness (inside the bounding rectangle but outside @@ -100,22 +78,6 @@ public bool Contains (in Rectangle outside, in Point location) return outside.Contains (location) && !inside.Contains (location); } - /// - /// Adds the thickness widths of another to the current , returning a - /// new . - /// - /// - /// - public Thickness Add (Thickness other) { return new (Left + other.Left, Top + other.Top, Right + other.Right, Bottom + other.Bottom); } - - /// - /// Adds the thickness widths of another to another . - /// - /// - /// - /// - public static Thickness operator + (Thickness a, Thickness b) { return a.Add (b); } - /// Draws the rectangle with an optional diagnostics label. /// /// If is set to @@ -240,6 +202,9 @@ rect with return GetInside (rect); } + /// Gets an empty thickness. + public static Thickness Empty => new (0); + /// /// Returns a rectangle describing the location and size of the inside area of with the /// thickness widths subtracted. The height and width of the returned rectangle will never be less than 0. @@ -263,7 +228,35 @@ public Rectangle GetInside (Rectangle rect) return new (x, y, width, height); } + /// + /// Gets the total width of the left and right sides of the rectangle. Sets the width of the left and rigth sides + /// of the rectangle to half the specified value. + /// + public int Horizontal + { + get => Left + Right; + set => Left = Right = value / 2; + } + + /// + /// Adds the thickness widths of another to another . + /// + /// + /// + /// + public static Thickness operator + (Thickness a, Thickness b) { return a.Add (b); } + /// Returns the thickness widths of the Thickness formatted as a string. /// The thickness widths as a string. - public override string ToString () { return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; } + public readonly override string ToString () { return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; } + + /// + /// Gets the total height of the top and bottom sides of the rectangle. Sets the height of the top and bottom + /// sides of the rectangle to half the specified value. + /// + public int Vertical + { + get => Top + Bottom; + set => Top = Bottom = value / 2; + } } From efcb635477663b9759cada9df3b4ed84bd6a879a Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 7 Jul 2024 08:41:32 -0600 Subject: [PATCH 3/4] Use Vector4 --- Terminal.Gui/Drawing/Thickness.cs | 48 ++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/Terminal.Gui/Drawing/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs index 653b210ac7..733275c88f 100644 --- a/Terminal.Gui/Drawing/Thickness.cs +++ b/Terminal.Gui/Drawing/Thickness.cs @@ -1,4 +1,5 @@ -using System.Text.Json.Serialization; +using System.Numerics; +using System.Text.Json.Serialization; namespace Terminal.Gui; @@ -17,8 +18,19 @@ namespace Terminal.Gui; /// public record struct Thickness { + private Vector4 _sides; + + /// Initializes a new instance of the class. + public Thickness (float left, float top, float right, float bottom) + { + _sides = new (left, top, right, bottom); + } + /// Initializes a new instance of the class with all widths set to 0. - public Thickness () { } + public Thickness () + { + _sides = new (0, 0, 0, 0); + } /// Initializes a new instance of the class with a uniform width to each side. /// @@ -40,21 +52,37 @@ public Thickness (int left, int top, int right, int bottom) Bottom = bottom; } - /// Gets or sets the width of the lower side of the rectangle. - [JsonInclude] - public int Bottom { get; set; } /// Gets or sets the width of the left side of the rectangle. [JsonInclude] - public int Left { get; set; } + public int Left + { + get => (int)_sides.X; + set => _sides.X = value; + } + /// Gets or sets the width of the upper side of the rectangle. + [JsonInclude] + public int Top + { + get => (int)_sides.Y; + set => _sides.Y = value; + } /// Gets or sets the width of the right side of the rectangle. [JsonInclude] - public int Right { get; set; } + public int Right + { + get => (int)_sides.Z; + set => _sides.Z = value; + } - /// Gets or sets the width of the upper side of the rectangle. + /// Gets or sets the width of the lower side of the rectangle. [JsonInclude] - public int Top { get; set; } + public int Bottom + { + get => (int)_sides.W; + set => _sides.W = value; + } /// /// Adds the thickness widths of another to the current , returning a @@ -248,7 +276,7 @@ public int Horizontal /// Returns the thickness widths of the Thickness formatted as a string. /// The thickness widths as a string. - public readonly override string ToString () { return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; } + public override string ToString () { return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; } /// /// Gets the total height of the top and bottom sides of the rectangle. Sets the height of the top and bottom From 8d527709e2141c3c35d36990cfa2a0d3781d9fb2 Mon Sep 17 00:00:00 2001 From: Tig Date: Sun, 7 Jul 2024 08:45:10 -0600 Subject: [PATCH 4/4] Code cleanup --- Terminal.Gui/Drawing/Thickness.cs | 83 +++++++++++++++---------------- 1 file changed, 40 insertions(+), 43 deletions(-) diff --git a/Terminal.Gui/Drawing/Thickness.cs b/Terminal.Gui/Drawing/Thickness.cs index 733275c88f..532c0af8a3 100644 --- a/Terminal.Gui/Drawing/Thickness.cs +++ b/Terminal.Gui/Drawing/Thickness.cs @@ -14,23 +14,18 @@ namespace Terminal.Gui; /// frame, /// with the thickness widths subtracted. /// -/// Use the helper API ( to draw the frame with the specified thickness. +/// +/// Use the helper API ( to draw the frame with the specified thickness. +/// +/// +/// Thickness uses intenrally. As a result, there is a potential precision loss for very +/// large numbers. This is typically not an issue for UI dimensions but could be relevant in other contexts. +/// /// public record struct Thickness { - private Vector4 _sides; - - /// Initializes a new instance of the class. - public Thickness (float left, float top, float right, float bottom) - { - _sides = new (left, top, right, bottom); - } - /// Initializes a new instance of the class with all widths set to 0. - public Thickness () - { - _sides = new (0, 0, 0, 0); - } + public Thickness () { _sides = Vector4.Zero; } /// Initializes a new instance of the class with a uniform width to each side. /// @@ -52,29 +47,15 @@ public Thickness (int left, int top, int right, int bottom) Bottom = bottom; } + private Vector4 _sides; - /// Gets or sets the width of the left side of the rectangle. - [JsonInclude] - public int Left - { - get => (int)_sides.X; - set => _sides.X = value; - } - /// Gets or sets the width of the upper side of the rectangle. - [JsonInclude] - public int Top - { - get => (int)_sides.Y; - set => _sides.Y = value; - } - - /// Gets or sets the width of the right side of the rectangle. - [JsonInclude] - public int Right - { - get => (int)_sides.Z; - set => _sides.Z = value; - } + /// + /// Adds the thickness widths of another to the current , returning a + /// new . + /// + /// + /// + public readonly Thickness Add (Thickness other) { return new (Left + other.Left, Top + other.Top, Right + other.Right, Bottom + other.Bottom); } /// Gets or sets the width of the lower side of the rectangle. [JsonInclude] @@ -84,14 +65,6 @@ public int Bottom set => _sides.W = value; } - /// - /// Adds the thickness widths of another to the current , returning a - /// new . - /// - /// - /// - public readonly Thickness Add (Thickness other) { return new (Left + other.Left, Top + other.Top, Right + other.Right, Bottom + other.Bottom); } - /// /// Gets whether the specified coordinates lie within the thickness (inside the bounding rectangle but outside /// the rectangle described by . @@ -266,6 +239,14 @@ public int Horizontal set => Left = Right = value / 2; } + /// Gets or sets the width of the left side of the rectangle. + [JsonInclude] + public int Left + { + get => (int)_sides.X; + set => _sides.X = value; + } + /// /// Adds the thickness widths of another to another . /// @@ -274,6 +255,22 @@ public int Horizontal /// public static Thickness operator + (Thickness a, Thickness b) { return a.Add (b); } + /// Gets or sets the width of the right side of the rectangle. + [JsonInclude] + public int Right + { + get => (int)_sides.Z; + set => _sides.Z = value; + } + + /// Gets or sets the width of the upper side of the rectangle. + [JsonInclude] + public int Top + { + get => (int)_sides.Y; + set => _sides.Y = value; + } + /// Returns the thickness widths of the Thickness formatted as a string. /// The thickness widths as a string. public override string ToString () { return $"(Left={Left},Top={Top},Right={Right},Bottom={Bottom})"; }