Browse Source

Add Boxshadow(s) Documentation Comments (#19644)

* Fix formatting errors/warnings in BoxShadow

* Fix formatting errors/warnings in BoxShadows

* Add documentation comments to BoxShadow

* Add documentation comments to BoxShadows
robloo 4 months ago
parent
commit
8a444ef3f0
2 changed files with 241 additions and 19 deletions
  1. 133 9
      src/Avalonia.Base/Media/BoxShadow.cs
  2. 108 10
      src/Avalonia.Base/Media/BoxShadows.cs

+ 133 - 9
src/Avalonia.Base/Media/BoxShadow.cs

@@ -6,25 +6,90 @@ using Avalonia.Utilities;
 
 namespace Avalonia.Media
 {
+    /// <summary>
+    /// Represents a box shadow which can be attached to an element or control.
+    /// </summary>
     public struct BoxShadow
     {
+        private readonly static char[] s_Separator = new char[] { ' ', '\t' };
+
+        /// <summary>
+        /// Gets or sets the horizontal offset (distance) of the shadow.
+        /// </summary>
+        /// <remarks>
+        /// Positive values place the shadow to the right of the element while
+        /// negative values place the shadow to the left.
+        /// </remarks>
         public double OffsetX { get; set; }
+
+        /// <summary>
+        /// Gets or sets the vertical offset (distance) of the shadow.
+        /// </summary>
+        /// <remarks>
+        /// Positive values place the shadow below the element while
+        /// negative values place the shadow above.
+        /// </remarks>
         public double OffsetY { get; set; }
+
+        /// <summary>
+        /// Gets or sets the blur radius.
+        /// This is used to control the amount of blurring.
+        /// </summary>
+        /// <remarks>
+        /// The larger this value, the bigger the blur effect, so the shadow becomes larger and more transparent.
+        /// Negative values are not allowed. If not specified, the default (zero) is used and the shadow edge is sharp.
+        /// </remarks>
         public double Blur { get; set; }
+
+        /// <summary>
+        /// Gets or sets the spread radius.
+        /// This is used to control the overall size of the shadow.
+        /// </summary>
+        /// <remarks>
+        /// Positive values will cause the shadow to expand and grow larger, negative values will cause the shadow to shrink.
+        /// If not specified, the default (zero) is used and the shadow will be the same size as the element.
+        /// </remarks>
         public double Spread { get; set; }
+
+        /// <summary>
+        /// Gets or sets the color of the shadow.
+        /// </summary>
         public Color Color { get; set; }
+
+        /// <summary>
+        /// Gets or sets a value indicating whether the shadow is inset and drawn within the element rather than outside of it.
+        /// </summary>
+        /// <remarks>
+        /// Inset changes the shadow to inside the element (as if the content was depressed inside the box).
+        /// If false (the default), the shadow is assumed to be a drop shadow (as if the box were raised above the content).
+        /// <br/><br/>
+        /// Inset shadows are drawn inside the element, above the background (even when it's transparent), but below any content.
+        /// </remarks>
         public bool IsInset { get; set; }
 
+        /// <summary>
+        /// Indicates whether the current object is equal to another object of the same type.
+        /// </summary>
+        /// <param name="other">An object to compare with this object.</param>
+        /// <returns>
+        /// <c>true</c> if the current object is equal to the other parameter; otherwise, <c>false</c>.
+        /// </returns>
         public bool Equals(in BoxShadow other)
         {
-            return OffsetX.Equals(other.OffsetX) && OffsetY.Equals(other.OffsetY) && Blur.Equals(other.Blur) && Spread.Equals(other.Spread) && Color.Equals(other.Color);
+            return OffsetX.Equals(other.OffsetX)
+                && OffsetY.Equals(other.OffsetY)
+                && Blur.Equals(other.Blur)
+                && Spread.Equals(other.Spread)
+                && Color.Equals(other.Color);
         }
 
+        /// <inheritdoc/>
         public override bool Equals(object? obj)
         {
             return obj is BoxShadow other && Equals(other);
         }
 
+        /// <inheritdoc/>
         public override int GetHashCode()
         {
             unchecked
@@ -38,8 +103,6 @@ namespace Avalonia.Media
             }
         }
 
-        private readonly static char[] s_Separator = new char[] { ' ', '\t' };
-
         struct ArrayReader
         {
             private int _index;
@@ -55,20 +118,28 @@ namespace Avalonia.Media
             {
                 s = null;
                 if (_index >= _arr.Length)
+                {
                     return false;
+                }
+
                 s = _arr[_index];
                 _index++;
+
                 return true;
             }
 
             public string ReadString()
             {
-                if(!TryReadString(out var rv))
+                if (!TryReadString(out var rv))
+                {
                     throw new FormatException();
+                }
+
                 return rv;
             }
         }
 
+        /// <inheritdoc/>
         public override string ToString()
         {
             var sb = StringBuilderCache.Acquire();
@@ -106,20 +177,45 @@ namespace Avalonia.Media
             Color.ToString(sb);
         }
 
+        /// <summary>
+        /// Parses a <see cref="BoxShadow"/> string.
+        /// </summary>
+        /// <remarks>
+        /// A box shadow may be specified in multiple formats with separate components:
+        ///   <list type="bullet">
+        ///     <item>Two, three, or four length values.</item>
+        ///     <item>A color value.</item>
+        ///     <item>An optional inset keyword.</item>
+        ///   </list>
+        /// If only two length values are given they will be interpreted as <see cref="OffsetX"/> and <see cref="OffsetY"/>.
+        /// If a third value is given, it is interpreted as a <see cref="Blur"/>, and if a fourth value is given,
+        /// it is interpreted as <see cref="Spread"/>.
+        /// </remarks>
+        /// <param name="s">The input string to parse.</param>
+        /// <returns>A new <see cref="BoxShadow"/></returns>
         public static unsafe BoxShadow Parse(string s)
         {
-            if(s == null)
+            if (s == null)
+            {
                 throw new ArgumentNullException();
+            }
+
             if (s.Length == 0)
+            {
                 throw new FormatException();
+            }
 
             var p = s.Split(s_Separator, StringSplitOptions.RemoveEmptyEntries);
             if (p.Length == 1 && p[0] == "none")
+            {
                 return default;
-            
+            }
+
             if (p.Length < 3 || p.Length > 6)
+            {
                 throw new FormatException();
-            
+            }
+
             bool inset = false;
 
             var tokenizer = new ArrayReader(p);
@@ -135,16 +231,20 @@ namespace Avalonia.Media
             var offsetY = double.Parse(tokenizer.ReadString(), CultureInfo.InvariantCulture);
             double blur = 0;
             double spread = 0;
-            
 
             tokenizer.TryReadString(out var token3);
             tokenizer.TryReadString(out var token4);
             tokenizer.TryReadString(out var token5);
 
-            if (token4 != null) 
+            if (token4 != null)
+            {
                 blur = double.Parse(token3!, CultureInfo.InvariantCulture);
+            }
+
             if (token5 != null)
+            {
                 spread = double.Parse(token4!, CultureInfo.InvariantCulture);
+            }
 
             var color = Color.Parse(token5 ?? token4 ?? token3!);
             return new BoxShadow
@@ -158,12 +258,36 @@ namespace Avalonia.Media
             };
         }
 
+        /// <summary>
+        /// Transforms the specified bounding rectangle to account for the shadow's offset, spread, and blur.
+        /// </summary>
+        /// <param name="rect">The original bounding <see cref="Rect"/> to transform.</param>
+        /// <returns>
+        /// A new <see cref="Rect"/> that includes the shadow's offset, spread, and blur if the shadow is not inset;
+        /// otherwise, the original rectangle.
+        /// </returns>
         public Rect TransformBounds(in Rect rect)
             => IsInset ? rect : rect.Translate(new Vector(OffsetX, OffsetY)).Inflate(Spread + Blur);
 
+        /// <summary>
+        /// Determines whether two <see cref="BoxShadow"/> values are equal.
+        /// </summary>
+        /// <param name="left">The first <see cref="BoxShadow"/> to compare.</param>
+        /// <param name="right">The second <see cref="BoxShadow"/> to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the two <see cref="BoxShadow"/> values are equal; otherwise, <c>false</c>.
+        /// </returns>
         public static bool operator ==(BoxShadow left, BoxShadow right) =>
             left.Equals(right);
 
+        /// <summary>
+        /// Determines whether two <see cref="BoxShadow"/> values are not equal.
+        /// </summary>
+        /// <param name="left">The first <see cref="BoxShadow"/> to compare.</param>
+        /// <param name="right">The second <see cref="BoxShadow"/> to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the two <see cref="BoxShadow"/> values are not equal; otherwise, <c>false</c>.
+        /// </returns>
         public static bool operator !=(BoxShadow left, BoxShadow right) => 
             !(left == right);
     }

+ 108 - 10
src/Avalonia.Base/Media/BoxShadows.cs

@@ -1,16 +1,28 @@
 using System;
 using System.ComponentModel;
-using Avalonia.Animation.Animators;
 using Avalonia.Utilities;
 
 namespace Avalonia.Media
 {
+    /// <summary>
+    /// Represents a collection of <see cref="BoxShadow"/>s.
+    /// </summary>
     public struct BoxShadows
     {
+        private static readonly char[] s_Separators = new[] { ',' };
+
         private readonly BoxShadow _first;
         private readonly BoxShadow[]? _list;
+
+        /// <summary>
+        /// Gets the number of <see cref="BoxShadow"/>s in the collection.
+        /// </summary>
         public int Count { get; }
-        
+
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BoxShadows"/> struct.
+        /// </summary>
+        /// <param name="shadow">The first <see cref="BoxShadow"/> to add to the collection.</param>
         public BoxShadows(BoxShadow shadow)
         {
             _first = shadow;
@@ -18,6 +30,11 @@ namespace Avalonia.Media
             Count = _first == default ? 0 : 1;
         }
 
+        /// <summary>
+        /// Initializes a new instance of the <see cref="BoxShadows"/> struct.
+        /// </summary>
+        /// <param name="first">The first <see cref="BoxShadow"/> to add to the collection.</param>
+        /// <param name="rest">All remaining <see cref="BoxShadow"/>s to add to the collection.</param>
         public BoxShadows(BoxShadow first, BoxShadow[] rest)
         {
             _first = first;
@@ -25,18 +42,33 @@ namespace Avalonia.Media
             Count = 1 + (rest?.Length ?? 0);
         }
 
-        public BoxShadow this[int c]
+        /// <summary>
+        /// Gets the <see cref="BoxShadow"/> at the specified index.
+        /// </summary>
+        /// <param name="index">The index of the <see cref="BoxShadow"/> to return.</param>
+        /// <returns>The <see cref="BoxShadow"/> at the specified index.</returns>
+        /// <exception cref="IndexOutOfRangeException">
+        /// Thrown when index less than 0 or index greater than or equal to <see cref="Count"/>.
+        /// </exception>
+        public BoxShadow this[int index]
         {
             get
             {
-                if (c< 0 || c >= Count)
+                if (index < 0 || index >= Count)
+                {
                     throw new IndexOutOfRangeException();
-                if (c == 0)
+                }
+
+                if (index == 0)
+                {
                     return _first;
-                return _list![c - 1];
+                }
+
+                return _list![index - 1];
             }
         }
 
+        /// <inheritdoc/>
         public override string ToString()
         {
             if (Count == 0)
@@ -81,7 +113,11 @@ namespace Avalonia.Media
         [EditorBrowsable(EditorBrowsableState.Never)]
         public BoxShadowsEnumerator GetEnumerator() => new BoxShadowsEnumerator(this);
 
-        private static readonly char[] s_Separators = new[] { ',' };
+        /// <summary>
+        /// Parses a <see cref="BoxShadows"/> string representing one or more <see cref="BoxShadow"/>s.
+        /// </summary>
+        /// <param name="s">The input string to parse.</param>
+        /// <returns>A new <see cref="BoxShadows"/> collection.</returns>
         public static BoxShadows Parse(string s)
         {
             var sp = s.Split(s_Separators, StringSplitOptions.RemoveEmptyEntries);
@@ -89,66 +125,128 @@ namespace Avalonia.Media
                 || (sp.Length == 1 &&
                     (string.IsNullOrWhiteSpace(sp[0])
                      || sp[0] == "none")))
+            {
                 return new BoxShadows();
+            }
 
             var first = BoxShadow.Parse(sp[0]);
             if (sp.Length == 1)
+            {
                 return new BoxShadows(first);
+            }
 
             var rest = new BoxShadow[sp.Length - 1];
             for (var c = 0; c < rest.Length; c++)
+            {
                 rest[c] = BoxShadow.Parse(sp[c + 1]);
+            }
+
             return new BoxShadows(first, rest);
         }
 
+        /// <summary>
+        /// Transforms the specified bounding rectangle to account for all shadow's offset, spread, and blur.
+        /// </summary>
+        /// <param name="rect">The original bounding <see cref="Rect"/> to transform.</param>
+        /// <returns>
+        /// A new <see cref="Rect"/> that includes all shadow's offset, spread, and blur in the collection.
+        /// </returns>
         public Rect TransformBounds(in Rect rect)
         {
             var final = rect;
             foreach (var shadow in this)
+            {
                 final = final.Union(shadow.TransformBounds(rect));
+            }
+
             return final;
         }
-        
+
+        /// <summary>
+        /// Gets a value indicating whether any <see cref="BoxShadow"/> in the collection has
+        /// <see cref="BoxShadow.IsInset"/> set to <c>true</c>.
+        /// </summary>
         public bool HasInsetShadows
         {
             get
             {
                 foreach(var boxShadow in this)
+                {
                     if (boxShadow != default && boxShadow.IsInset)
+                    {
                         return true;
+                    }
+                }
+
                 return false;
             }
         }
-        
+
+        /// <summary>
+        /// Indicates whether the current object is equal to another object of the same type.
+        /// </summary>
+        /// <param name="other">An object to compare with this object.</param>
+        /// <returns>
+        /// <c>true</c> if the current object is equal to the other parameter; otherwise, <c>false</c>.
+        /// </returns>
         public bool Equals(BoxShadows other)
         {
             if (other.Count != Count)
+            {
                 return false;
-            for(var c=0; c<Count ; c++)
+            }
+
+            for (var c = 0; c < Count; c++)
+            {
                 if (!this[c].Equals(other[c]))
+                {
                     return false;
+                }
+            }
+
             return true;
         }
 
+        /// <inheritdoc/>
         public override bool Equals(object? obj)
         {
             return obj is BoxShadows other && Equals(other);
         }
 
+        /// <inheritdoc/>
         public override int GetHashCode()
         {
             unchecked
             {
                 int hashCode = 0;
                 foreach (var s in this)
+                {
                     hashCode = (hashCode * 397) ^ s.GetHashCode();
+                }
+
                 return hashCode;
             }
         }
 
+        /// <summary>
+        /// Determines whether two <see cref="BoxShadows"/> collections are equal.
+        /// </summary>
+        /// <param name="left">The first <see cref="BoxShadows"/> collection to compare.</param>
+        /// <param name="right">The second <see cref="BoxShadows"/> collection to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the two <see cref="BoxShadows"/> collections are equal; otherwise, <c>false</c>.
+        /// </returns>
         public static bool operator ==(BoxShadows left, BoxShadows right) => 
             left.Equals(right);
 
+        /// <summary>
+        /// Determines whether two <see cref="BoxShadows"/> collections are not equal.
+        /// </summary>
+        /// <param name="left">The first <see cref="BoxShadows"/> collection to compare.</param>
+        /// <param name="right">The second <see cref="BoxShadows"/> collection to compare.</param>
+        /// <returns>
+        /// <c>true</c> if the two <see cref="BoxShadows"/> collections are not equal; otherwise, <c>false</c>.
+        /// </returns>
         public static bool operator !=(BoxShadows left, BoxShadows right) =>
             !(left == right);
     }