RectangleF.cs 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT license.
  3. // See the LICENSE file in the project root for more information.
  4. // Copied from https://github.com/dotnet/corefx/tree/master/src/System.Drawing.Primitives/src/System/Drawing
  5. using System;
  6. using System.ComponentModel;
  7. namespace Terminal.Gui {
  8. /// <summary>
  9. /// Stores the location and size of a rectangular region.
  10. /// </summary>
  11. public struct RectangleF : IEquatable<RectangleF> {
  12. /// <summary>
  13. /// Initializes a new instance of the <see cref='Terminal.Gui.RectangleF'/> class.
  14. /// </summary>
  15. public static readonly RectangleF Empty;
  16. private float x; // Do not rename (binary serialization)
  17. private float y; // Do not rename (binary serialization)
  18. private float width; // Do not rename (binary serialization)
  19. private float height; // Do not rename (binary serialization)
  20. /// <summary>
  21. /// Initializes a new instance of the <see cref='Terminal.Gui.RectangleF'/> class with the specified location
  22. /// and size.
  23. /// </summary>
  24. public RectangleF (float x, float y, float width, float height)
  25. {
  26. this.x = x;
  27. this.y = y;
  28. this.width = width;
  29. this.height = height;
  30. }
  31. /// <summary>
  32. /// Initializes a new instance of the <see cref='Terminal.Gui.RectangleF'/> class with the specified location
  33. /// and size.
  34. /// </summary>
  35. public RectangleF (PointF location, SizeF size)
  36. {
  37. x = location.X;
  38. y = location.Y;
  39. width = size.Width;
  40. height = size.Height;
  41. }
  42. /// <summary>
  43. /// Creates a new <see cref='Terminal.Gui.RectangleF'/> with the specified location and size.
  44. /// </summary>
  45. public static RectangleF FromLTRB (float left, float top, float right, float bottom) =>
  46. new RectangleF (left, top, right - left, bottom - top);
  47. /// <summary>
  48. /// Gets or sets the coordinates of the upper-left corner of the rectangular region represented by this
  49. /// <see cref='Terminal.Gui.RectangleF'/>.
  50. /// </summary>
  51. [Browsable (false)]
  52. public PointF Location {
  53. get => new PointF (X, Y);
  54. set {
  55. X = value.X;
  56. Y = value.Y;
  57. }
  58. }
  59. /// <summary>
  60. /// Gets or sets the size of this <see cref='Terminal.Gui.RectangleF'/>.
  61. /// </summary>
  62. [Browsable (false)]
  63. public SizeF Size {
  64. get => new SizeF (Width, Height);
  65. set {
  66. Width = value.Width;
  67. Height = value.Height;
  68. }
  69. }
  70. /// <summary>
  71. /// Gets or sets the x-coordinate of the upper-left corner of the rectangular region defined by this
  72. /// <see cref='Terminal.Gui.RectangleF'/>.
  73. /// </summary>
  74. public float X {
  75. get => x;
  76. set => x = value;
  77. }
  78. /// <summary>
  79. /// Gets or sets the y-coordinate of the upper-left corner of the rectangular region defined by this
  80. /// <see cref='Terminal.Gui.RectangleF'/>.
  81. /// </summary>
  82. public float Y {
  83. get => y;
  84. set => y = value;
  85. }
  86. /// <summary>
  87. /// Gets or sets the width of the rectangular region defined by this <see cref='Terminal.Gui.RectangleF'/>.
  88. /// </summary>
  89. public float Width {
  90. get => width;
  91. set => width = value;
  92. }
  93. /// <summary>
  94. /// Gets or sets the height of the rectangular region defined by this <see cref='Terminal.Gui.RectangleF'/>.
  95. /// </summary>
  96. public float Height {
  97. get => height;
  98. set => height = value;
  99. }
  100. /// <summary>
  101. /// Gets the x-coordinate of the upper-left corner of the rectangular region defined by this
  102. /// <see cref='Terminal.Gui.RectangleF'/> .
  103. /// </summary>
  104. [Browsable (false)]
  105. public float Left => X;
  106. /// <summary>
  107. /// Gets the y-coordinate of the upper-left corner of the rectangular region defined by this
  108. /// <see cref='Terminal.Gui.RectangleF'/>.
  109. /// </summary>
  110. [Browsable (false)]
  111. public float Top => Y;
  112. /// <summary>
  113. /// Gets the x-coordinate of the lower-right corner of the rectangular region defined by this
  114. /// <see cref='Terminal.Gui.RectangleF'/>.
  115. /// </summary>
  116. [Browsable (false)]
  117. public float Right => X + Width;
  118. /// <summary>
  119. /// Gets the y-coordinate of the lower-right corner of the rectangular region defined by this
  120. /// <see cref='Terminal.Gui.RectangleF'/>.
  121. /// </summary>
  122. [Browsable (false)]
  123. public float Bottom => Y + Height;
  124. /// <summary>
  125. /// Tests whether this <see cref='Terminal.Gui.RectangleF'/> has a <see cref='Terminal.Gui.RectangleF.Width'/> or a <see cref='Terminal.Gui.RectangleF.Height'/> of 0.
  126. /// </summary>
  127. [Browsable (false)]
  128. public bool IsEmpty => (Width <= 0) || (Height <= 0);
  129. /// <summary>
  130. /// Tests whether <paramref name="obj"/> is a <see cref='Terminal.Gui.RectangleF'/> with the same location and
  131. /// size of this <see cref='Terminal.Gui.RectangleF'/>.
  132. /// </summary>
  133. public override bool Equals (object obj) => obj is RectangleF && Equals ((RectangleF)obj);
  134. /// <summary>
  135. /// Returns true if two <see cref='Terminal.Gui.RectangleF'/> objects have equal location and size.
  136. /// </summary>
  137. /// <param name="other"></param>
  138. /// <returns></returns>
  139. public bool Equals (RectangleF other) => this == other;
  140. /// <summary>
  141. /// Tests whether two <see cref='Terminal.Gui.RectangleF'/> objects have equal location and size.
  142. /// </summary>
  143. public static bool operator == (RectangleF left, RectangleF right) =>
  144. left.X == right.X && left.Y == right.Y && left.Width == right.Width && left.Height == right.Height;
  145. /// <summary>
  146. /// Tests whether two <see cref='Terminal.Gui.RectangleF'/> objects differ in location or size.
  147. /// </summary>
  148. public static bool operator != (RectangleF left, RectangleF right) => !(left == right);
  149. /// <summary>
  150. /// Determines if the specified point is contained within the rectangular region defined by this
  151. /// <see cref='Terminal.Gui.Rect'/> .
  152. /// </summary>
  153. public bool Contains (float x, float y) => X <= x && x < X + Width && Y <= y && y < Y + Height;
  154. /// <summary>
  155. /// Determines if the specified point is contained within the rectangular region defined by this
  156. /// <see cref='Terminal.Gui.Rect'/> .
  157. /// </summary>
  158. public bool Contains (PointF pt) => Contains (pt.X, pt.Y);
  159. /// <summary>
  160. /// Determines if the rectangular region represented by <paramref name="rect"/> is entirely contained within
  161. /// the rectangular region represented by this <see cref='Terminal.Gui.Rect'/> .
  162. /// </summary>
  163. public bool Contains (RectangleF rect) =>
  164. (X <= rect.X) && (rect.X + rect.Width <= X + Width) && (Y <= rect.Y) && (rect.Y + rect.Height <= Y + Height);
  165. /// <summary>
  166. /// Gets the hash code for this <see cref='Terminal.Gui.RectangleF'/>.
  167. /// </summary>
  168. public override int GetHashCode ()
  169. {
  170. return (Height.GetHashCode () + Width.GetHashCode ()) ^ X.GetHashCode () + Y.GetHashCode ();
  171. }
  172. /// <summary>
  173. /// Inflates this <see cref='Terminal.Gui.Rect'/> by the specified amount.
  174. /// </summary>
  175. public void Inflate (float x, float y)
  176. {
  177. X -= x;
  178. Y -= y;
  179. Width += 2 * x;
  180. Height += 2 * y;
  181. }
  182. /// <summary>
  183. /// Inflates this <see cref='Terminal.Gui.Rect'/> by the specified amount.
  184. /// </summary>
  185. public void Inflate (SizeF size) => Inflate (size.Width, size.Height);
  186. /// <summary>
  187. /// Creates a <see cref='Terminal.Gui.Rect'/> that is inflated by the specified amount.
  188. /// </summary>
  189. public static RectangleF Inflate (RectangleF rect, float x, float y)
  190. {
  191. RectangleF r = rect;
  192. r.Inflate (x, y);
  193. return r;
  194. }
  195. /// <summary>
  196. /// Creates a Rectangle that represents the intersection between this Rectangle and rect.
  197. /// </summary>
  198. public void Intersect (RectangleF rect)
  199. {
  200. RectangleF result = Intersect (rect, this);
  201. X = result.X;
  202. Y = result.Y;
  203. Width = result.Width;
  204. Height = result.Height;
  205. }
  206. /// <summary>
  207. /// Creates a rectangle that represents the intersection between a and b. If there is no intersection, an
  208. /// empty rectangle is returned.
  209. /// </summary>
  210. public static RectangleF Intersect (RectangleF a, RectangleF b)
  211. {
  212. float x1 = Math.Max (a.X, b.X);
  213. float x2 = Math.Min (a.X + a.Width, b.X + b.Width);
  214. float y1 = Math.Max (a.Y, b.Y);
  215. float y2 = Math.Min (a.Y + a.Height, b.Y + b.Height);
  216. if (x2 >= x1 && y2 >= y1) {
  217. return new RectangleF (x1, y1, x2 - x1, y2 - y1);
  218. }
  219. return Empty;
  220. }
  221. /// <summary>
  222. /// Determines if this rectangle intersects with rect.
  223. /// </summary>
  224. public bool IntersectsWith (RectangleF rect) =>
  225. (rect.X < X + Width) && (X < rect.X + rect.Width) && (rect.Y < Y + Height) && (Y < rect.Y + rect.Height);
  226. /// <summary>
  227. /// Creates a rectangle that represents the union between a and b.
  228. /// </summary>
  229. public static RectangleF Union (RectangleF a, RectangleF b)
  230. {
  231. float x1 = Math.Min (a.X, b.X);
  232. float x2 = Math.Max (a.X + a.Width, b.X + b.Width);
  233. float y1 = Math.Min (a.Y, b.Y);
  234. float y2 = Math.Max (a.Y + a.Height, b.Y + b.Height);
  235. return new RectangleF (x1, y1, x2 - x1, y2 - y1);
  236. }
  237. /// <summary>
  238. /// Adjusts the location of this rectangle by the specified amount.
  239. /// </summary>
  240. public void Offset (PointF pos) => Offset (pos.X, pos.Y);
  241. /// <summary>
  242. /// Adjusts the location of this rectangle by the specified amount.
  243. /// </summary>
  244. public void Offset (float x, float y)
  245. {
  246. X += x;
  247. Y += y;
  248. }
  249. /// <summary>
  250. /// Converts the specified <see cref='Terminal.Gui.Rect'/> to a
  251. /// <see cref='Terminal.Gui.RectangleF'/>.
  252. /// </summary>
  253. public static implicit operator RectangleF (Rect r) => new RectangleF (r.X, r.Y, r.Width, r.Height);
  254. /// <summary>
  255. /// Converts the <see cref='Terminal.Gui.RectangleF.Location'/> and <see cref='Terminal.Gui.RectangleF.Size'/>
  256. /// of this <see cref='Terminal.Gui.RectangleF'/> to a human-readable string.
  257. /// </summary>
  258. public override string ToString () =>
  259. "{X=" + X.ToString () + ",Y=" + Y.ToString () +
  260. ",Width=" + Width.ToString () + ",Height=" + Height.ToString () + "}";
  261. }
  262. }