GridLength.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. // Copyright (c) The Avalonia Project. All rights reserved.
  2. // Licensed under the MIT license. See licence.md file in the project root for full license information.
  3. using Avalonia.Utilities;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Globalization;
  7. using System.Linq;
  8. namespace Avalonia.Controls
  9. {
  10. /// <summary>
  11. /// Defines the valid units for a <see cref="GridLength"/>.
  12. /// </summary>
  13. public enum GridUnitType
  14. {
  15. /// <summary>
  16. /// The row or column is auto-sized to fit its content.
  17. /// </summary>
  18. Auto = 0,
  19. /// <summary>
  20. /// The row or column is sized in device independent pixels.
  21. /// </summary>
  22. Pixel = 1,
  23. /// <summary>
  24. /// The row or column is sized as a weighted proportion of available space.
  25. /// </summary>
  26. Star = 2,
  27. }
  28. /// <summary>
  29. /// Holds the width or height of a <see cref="Grid"/>'s column and row definitions.
  30. /// </summary>
  31. public struct GridLength : IEquatable<GridLength>
  32. {
  33. private readonly GridUnitType _type;
  34. private readonly double _value;
  35. /// <summary>
  36. /// Initializes a new instance of the <see cref="GridLength"/> struct.
  37. /// </summary>
  38. /// <param name="value">The size of the GridLength in device independent pixels.</param>
  39. public GridLength(double value)
  40. : this(value, GridUnitType.Pixel)
  41. {
  42. }
  43. /// <summary>
  44. /// Initializes a new instance of the <see cref="GridLength"/> struct.
  45. /// </summary>
  46. /// <param name="value">The size of the GridLength.</param>
  47. /// <param name="type">The unit of the GridLength.</param>
  48. public GridLength(double value, GridUnitType type)
  49. {
  50. if (value < 0 || double.IsNaN(value) || double.IsInfinity(value))
  51. {
  52. throw new ArgumentException("Invalid value", "value");
  53. }
  54. if (type < GridUnitType.Auto || type > GridUnitType.Star)
  55. {
  56. throw new ArgumentException("Invalid value", "type");
  57. }
  58. _type = type;
  59. _value = value;
  60. }
  61. /// <summary>
  62. /// Gets an instance of <see cref="GridLength"/> that indicates that a row or column should
  63. /// auto-size to fit its content.
  64. /// </summary>
  65. public static GridLength Auto => new GridLength(0, GridUnitType.Auto);
  66. /// <summary>
  67. /// Gets the unit of the <see cref="GridLength"/>.
  68. /// </summary>
  69. public GridUnitType GridUnitType => _type;
  70. /// <summary>
  71. /// Gets a value that indicates whether the <see cref="GridLength"/> has a <see cref="GridUnitType"/> of Pixel.
  72. /// </summary>
  73. public bool IsAbsolute => _type == GridUnitType.Pixel;
  74. /// <summary>
  75. /// Gets a value that indicates whether the <see cref="GridLength"/> has a <see cref="GridUnitType"/> of Auto.
  76. /// </summary>
  77. public bool IsAuto => _type == GridUnitType.Auto;
  78. /// <summary>
  79. /// Gets a value that indicates whether the <see cref="GridLength"/> has a <see cref="GridUnitType"/> of Star.
  80. /// </summary>
  81. public bool IsStar => _type == GridUnitType.Star;
  82. /// <summary>
  83. /// Gets the length.
  84. /// </summary>
  85. public double Value => _value;
  86. /// <summary>
  87. /// Compares two GridLength structures for equality.
  88. /// </summary>
  89. /// <param name="a">The first GridLength.</param>
  90. /// <param name="b">The second GridLength.</param>
  91. /// <returns>True if the structures are equal, otherwise false.</returns>
  92. public static bool operator ==(GridLength a, GridLength b)
  93. {
  94. return (a.IsAuto && b.IsAuto) || (a._value == b._value && a._type == b._type);
  95. }
  96. /// <summary>
  97. /// Compares two GridLength structures for inequality.
  98. /// </summary>
  99. /// <param name="gl1">The first GridLength.</param>
  100. /// <param name="gl2">The first GridLength.</param>
  101. /// <returns>True if the structures are unequal, otherwise false.</returns>
  102. public static bool operator !=(GridLength gl1, GridLength gl2)
  103. {
  104. return !(gl1 == gl2);
  105. }
  106. /// <summary>
  107. /// Determines whether the <see cref="GridLength"/> is equal to the specified object.
  108. /// </summary>
  109. /// <param name="o">The object with which to test equality.</param>
  110. /// <returns>True if the objects are equal, otherwise false.</returns>
  111. public override bool Equals(object o)
  112. {
  113. if (o == null)
  114. {
  115. return false;
  116. }
  117. if (!(o is GridLength))
  118. {
  119. return false;
  120. }
  121. return this == (GridLength)o;
  122. }
  123. /// <summary>
  124. /// Compares two GridLength structures for equality.
  125. /// </summary>
  126. /// <param name="gridLength">The structure with which to test equality.</param>
  127. /// <returns>True if the structures are equal, otherwise false.</returns>
  128. public bool Equals(GridLength gridLength)
  129. {
  130. return this == gridLength;
  131. }
  132. /// <summary>
  133. /// Gets a hash code for the GridLength.
  134. /// </summary>
  135. /// <returns>The hash code.</returns>
  136. public override int GetHashCode()
  137. {
  138. return _value.GetHashCode() ^ _type.GetHashCode();
  139. }
  140. /// <summary>
  141. /// Gets a string representation of the <see cref="GridLength"/>.
  142. /// </summary>
  143. /// <returns>The string representation.</returns>
  144. public override string ToString()
  145. {
  146. if (IsAuto)
  147. {
  148. return "Auto";
  149. }
  150. string s = _value.ToString();
  151. return IsStar ? s + "*" : s;
  152. }
  153. /// <summary>
  154. /// Parses a string to return a <see cref="GridLength"/>.
  155. /// </summary>
  156. /// <param name="s">The string.</param>
  157. /// <returns>The <see cref="GridLength"/>.</returns>
  158. public static GridLength Parse(string s)
  159. {
  160. s = s.ToUpperInvariant();
  161. if (s == "AUTO")
  162. {
  163. return Auto;
  164. }
  165. else if (s.EndsWith("*"))
  166. {
  167. var valueString = s.Substring(0, s.Length - 1).Trim();
  168. var value = valueString.Length > 0 ? double.Parse(valueString, CultureInfo.InvariantCulture) : 1;
  169. return new GridLength(value, GridUnitType.Star);
  170. }
  171. else
  172. {
  173. var value = double.Parse(s, CultureInfo.InvariantCulture);
  174. return new GridLength(value, GridUnitType.Pixel);
  175. }
  176. }
  177. /// <summary>
  178. /// Parses a string to return a collection of <see cref="GridLength"/>s.
  179. /// </summary>
  180. /// <param name="s">The string.</param>
  181. /// <returns>The <see cref="GridLength"/>.</returns>
  182. public static IEnumerable<GridLength> ParseLengths(string s)
  183. {
  184. using (var tokenizer = new StringTokenizer(s, CultureInfo.InvariantCulture))
  185. {
  186. while (tokenizer.TryReadString(out var item))
  187. {
  188. yield return Parse(item);
  189. }
  190. }
  191. }
  192. }
  193. }