Rect.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. //
  2. // Derived from System.Drawing.Rectangle.cs
  3. //
  4. // Author:
  5. // Mike Kestner ([email protected])
  6. //
  7. // Copyright (C) 2001 Mike Kestner
  8. // Copyright (C) 2004 Novell, Inc. http://www.novell.com
  9. //
  10. using System;
  11. namespace Terminal.Gui {
  12. /// <summary>
  13. /// Stores a set of four integers that represent the location and size of a rectangle
  14. /// </summary>
  15. public struct Rect {
  16. int width;
  17. int height;
  18. /// <summary>
  19. /// Gets or sets the x-coordinate of the upper-left corner of this Rectangle structure.
  20. /// </summary>
  21. public int X;
  22. /// <summary>
  23. /// Gets or sets the y-coordinate of the upper-left corner of this Rectangle structure.
  24. /// </summary>
  25. public int Y;
  26. /// <summary>
  27. /// Gets or sets the width of this Rect structure.
  28. /// </summary>
  29. public int Width {
  30. get { return width; }
  31. set {
  32. if (value < 0)
  33. throw new ArgumentException ("Width must be greater or equal to 0.");
  34. width = value;
  35. }
  36. }
  37. /// <summary>
  38. /// Gets or sets the height of this Rectangle structure.
  39. /// </summary>
  40. public int Height {
  41. get { return height; }
  42. set {
  43. if (value < 0)
  44. throw new ArgumentException ("Height must be greater or equal to 0.");
  45. height = value;
  46. }
  47. }
  48. /// <summary>
  49. /// Empty Shared Field
  50. /// </summary>
  51. ///
  52. /// <remarks>
  53. /// An uninitialized Rectangle Structure.
  54. /// </remarks>
  55. public static readonly Rect Empty;
  56. /// <summary>
  57. /// FromLTRB Shared Method
  58. /// </summary>
  59. ///
  60. /// <remarks>
  61. /// Produces a Rectangle structure from left, top, right
  62. /// and bottom coordinates.
  63. /// </remarks>
  64. public static Rect FromLTRB (int left, int top,
  65. int right, int bottom)
  66. {
  67. return new Rect (left, top, right - left,
  68. bottom - top);
  69. }
  70. /// <summary>
  71. /// Produces a new Rect by inflating an existing Rect by the specified coordinate values.
  72. /// </summary>
  73. ///
  74. /// <remarks>
  75. /// Produces a new Rect by inflating an existing Rect by the specified coordinate values.
  76. /// The rectangle is enlarged in both directions along an axis.
  77. /// </remarks>
  78. public static Rect Inflate (Rect rect, int x, int y)
  79. {
  80. Rect r = new Rect (rect.Location, rect.Size);
  81. r.Inflate (x, y);
  82. return r;
  83. }
  84. /// <summary>
  85. /// Inflates an existing Rect by the specified coordinate values.
  86. /// </summary>
  87. ///
  88. /// <remarks>
  89. /// This method enlarges this rectangle, not a copy of it. The rectangle is enlarged in both directions along an axis.
  90. /// </remarks>
  91. public void Inflate (int width, int height)
  92. {
  93. // Set dims first so we don't lose the original values on exception
  94. Width += width * 2;
  95. Height += height * 2;
  96. X -= width;
  97. Y -= height;
  98. }
  99. /// <summary>
  100. /// Inflates an existing Rect by the specified Sizwe.
  101. /// </summary>
  102. ///
  103. /// <remarks>
  104. /// This method enlarges this rectangle, not a copy of it. The rectangle is enlarged in both directions along an axis.
  105. /// </remarks>
  106. public void Inflate (Size size)
  107. {
  108. Inflate (size.Width, size.Height);
  109. }
  110. /// <summary>
  111. /// Intersect Shared Method
  112. /// </summary>
  113. ///
  114. /// <remarks>
  115. /// Produces a new Rectangle by intersecting 2 existing
  116. /// Rectangles. Returns Empty if there is no intersection.
  117. /// </remarks>
  118. public static Rect Intersect (Rect a, Rect b)
  119. {
  120. // MS.NET returns a non-empty rectangle if the two rectangles
  121. // touch each other
  122. if (!a.IntersectsWithInclusive (b))
  123. return Empty;
  124. return Rect.FromLTRB (
  125. Math.Max (a.Left, b.Left),
  126. Math.Max (a.Top, b.Top),
  127. Math.Min (a.Right, b.Right),
  128. Math.Min (a.Bottom, b.Bottom));
  129. }
  130. /// <summary>
  131. /// Intersect Method
  132. /// </summary>
  133. ///
  134. /// <remarks>
  135. /// Replaces the Rectangle with the intersection of itself
  136. /// and another Rectangle.
  137. /// </remarks>
  138. public void Intersect (Rect rect)
  139. {
  140. this = Rect.Intersect (this, rect);
  141. }
  142. /// <summary>
  143. /// Produces the uninion of two rectangles.
  144. /// </summary>
  145. ///
  146. /// <remarks>
  147. /// Produces a new Rectangle from the union of 2 existing
  148. /// Rectangles.
  149. /// </remarks>
  150. public static Rect Union (Rect a, Rect b)
  151. {
  152. //int x1 = Math.Min (a.X, b.X);
  153. //int x2 = Math.Max (a.X + a.Width, b.X + b.Width);
  154. //int y1 = Math.Min (a.Y, b.Y);oS
  155. //int y2 = Math.Max (a.Y + a.Height, b.Y + b.Height);
  156. //return new Rect (x1, y1, x2 - x1, y2 - y1);
  157. int x1 = Math.Min (a.X, b.X);
  158. int x2 = Math.Max (a.X + Math.Abs (a.Width), b.X + Math.Abs (b.Width));
  159. int y1 = Math.Min (a.Y, b.Y);
  160. int y2 = Math.Max (a.Y + Math.Abs (a.Height), b.Y + Math.Abs (b.Height));
  161. return new Rect (x1, y1, x2 - x1, y2 - y1);
  162. }
  163. /// <summary>
  164. /// Equality Operator
  165. /// </summary>
  166. ///
  167. /// <remarks>
  168. /// Compares two Rectangle objects. The return value is
  169. /// based on the equivalence of the Location and Size
  170. /// properties of the two Rectangles.
  171. /// </remarks>
  172. public static bool operator == (Rect left, Rect right)
  173. {
  174. return ((left.Location == right.Location) &&
  175. (left.Size == right.Size));
  176. }
  177. /// <summary>
  178. /// Inequality Operator
  179. /// </summary>
  180. ///
  181. /// <remarks>
  182. /// Compares two Rectangle objects. The return value is
  183. /// based on the equivalence of the Location and Size
  184. /// properties of the two Rectangles.
  185. /// </remarks>
  186. public static bool operator != (Rect left, Rect right)
  187. {
  188. return ((left.Location != right.Location) ||
  189. (left.Size != right.Size));
  190. }
  191. // -----------------------
  192. // Public Constructors
  193. // -----------------------
  194. /// <summary>
  195. /// Rectangle Constructor
  196. /// </summary>
  197. ///
  198. /// <remarks>
  199. /// Creates a Rectangle from Point and Size values.
  200. /// </remarks>
  201. public Rect (Point location, Size size)
  202. {
  203. X = location.X;
  204. Y = location.Y;
  205. width = size.Width;
  206. height = size.Height;
  207. Width = width;
  208. Height = height;
  209. }
  210. /// <summary>
  211. /// Rectangle Constructor
  212. /// </summary>
  213. ///
  214. /// <remarks>
  215. /// Creates a Rectangle from a specified x,y location and
  216. /// width and height values.
  217. /// </remarks>
  218. public Rect (int x, int y, int width, int height)
  219. {
  220. X = x;
  221. Y = y;
  222. this.width = width;
  223. this.height = height;
  224. Width = this.width;
  225. Height = this.height;
  226. }
  227. /// <summary>
  228. /// Bottom Property
  229. /// </summary>
  230. ///
  231. /// <remarks>
  232. /// The Y coordinate of the bottom edge of the Rectangle.
  233. /// Read only.
  234. /// </remarks>
  235. public int Bottom {
  236. get {
  237. return Y + Height;
  238. }
  239. }
  240. /// <summary>
  241. /// IsEmpty Property
  242. /// </summary>
  243. ///
  244. /// <remarks>
  245. /// Indicates if the width or height are zero. Read only.
  246. /// </remarks>
  247. public bool IsEmpty {
  248. get {
  249. return ((X == 0) && (Y == 0) && (Width == 0) && (Height == 0));
  250. }
  251. }
  252. /// <summary>
  253. /// Left Property
  254. /// </summary>
  255. ///
  256. /// <remarks>
  257. /// The X coordinate of the left edge of the Rectangle.
  258. /// Read only.
  259. /// </remarks>
  260. public int Left {
  261. get {
  262. return X;
  263. }
  264. }
  265. /// <summary>
  266. /// Location Property
  267. /// </summary>
  268. ///
  269. /// <remarks>
  270. /// The Location of the top-left corner of the Rectangle.
  271. /// </remarks>
  272. public Point Location {
  273. get {
  274. return new Point (X, Y);
  275. }
  276. set {
  277. X = value.X;
  278. Y = value.Y;
  279. }
  280. }
  281. /// <summary>
  282. /// Right Property
  283. /// </summary>
  284. ///
  285. /// <remarks>
  286. /// The X coordinate of the right edge of the Rectangle.
  287. /// Read only.
  288. /// </remarks>
  289. public int Right {
  290. get {
  291. return X + Width;
  292. }
  293. }
  294. /// <summary>
  295. /// Size Property
  296. /// </summary>
  297. ///
  298. /// <remarks>
  299. /// The Size of the Rectangle.
  300. /// </remarks>
  301. public Size Size {
  302. get {
  303. return new Size (Width, Height);
  304. }
  305. set {
  306. Width = value.Width;
  307. Height = value.Height;
  308. }
  309. }
  310. /// <summary>
  311. /// Top Property
  312. /// </summary>
  313. ///
  314. /// <remarks>
  315. /// The Y coordinate of the top edge of the Rectangle.
  316. /// Read only.
  317. /// </remarks>
  318. public int Top {
  319. get {
  320. return Y;
  321. }
  322. }
  323. /// <summary>
  324. /// Contains Method
  325. /// </summary>
  326. ///
  327. /// <remarks>
  328. /// Checks if an x,y coordinate lies within this Rectangle.
  329. /// </remarks>
  330. public bool Contains (int x, int y)
  331. {
  332. return ((x >= Left) && (x < Right) &&
  333. (y >= Top) && (y < Bottom));
  334. }
  335. /// <summary>
  336. /// Contains Method
  337. /// </summary>
  338. ///
  339. /// <remarks>
  340. /// Checks if a Point lies within this Rectangle.
  341. /// </remarks>
  342. public bool Contains (Point pt)
  343. {
  344. return Contains (pt.X, pt.Y);
  345. }
  346. /// <summary>
  347. /// Contains Method
  348. /// </summary>
  349. ///
  350. /// <remarks>
  351. /// Checks if a Rectangle lies entirely within this
  352. /// Rectangle.
  353. /// </remarks>
  354. public bool Contains (Rect rect)
  355. {
  356. return (rect == Intersect (this, rect));
  357. }
  358. /// <summary>
  359. /// Equals Method
  360. /// </summary>
  361. ///
  362. /// <remarks>
  363. /// Checks equivalence of this Rectangle and another object.
  364. /// </remarks>
  365. public override bool Equals (object obj)
  366. {
  367. if (!(obj is Rect))
  368. return false;
  369. return (this == (Rect)obj);
  370. }
  371. /// <summary>
  372. /// GetHashCode Method
  373. /// </summary>
  374. ///
  375. /// <remarks>
  376. /// Calculates a hashing value.
  377. /// </remarks>
  378. public override int GetHashCode ()
  379. {
  380. return (Height + Width) ^ X + Y;
  381. }
  382. /// <summary>
  383. /// IntersectsWith Method
  384. /// </summary>
  385. ///
  386. /// <remarks>
  387. /// Checks if a Rectangle intersects with this one.
  388. /// </remarks>
  389. public bool IntersectsWith (Rect rect)
  390. {
  391. return !((Left >= rect.Right) || (Right <= rect.Left) ||
  392. (Top >= rect.Bottom) || (Bottom <= rect.Top));
  393. }
  394. bool IntersectsWithInclusive (Rect r)
  395. {
  396. return !((Left > r.Right) || (Right < r.Left) ||
  397. (Top > r.Bottom) || (Bottom < r.Top));
  398. }
  399. /// <summary>
  400. /// Offset Method
  401. /// </summary>
  402. ///
  403. /// <remarks>
  404. /// Moves the Rectangle a specified distance.
  405. /// </remarks>
  406. public void Offset (int x, int y)
  407. {
  408. this.X += x;
  409. this.Y += y;
  410. }
  411. /// <summary>
  412. /// Offset Method
  413. /// </summary>
  414. ///
  415. /// <remarks>
  416. /// Moves the Rectangle a specified distance.
  417. /// </remarks>
  418. public void Offset (Point pos)
  419. {
  420. X += pos.X;
  421. Y += pos.Y;
  422. }
  423. /// <summary>
  424. /// ToString Method
  425. /// </summary>
  426. ///
  427. /// <remarks>
  428. /// Formats the Rectangle as a string in (x,y,w,h) notation.
  429. /// </remarks>
  430. public override string ToString ()
  431. {
  432. return $"({X},{Y},{Width},{Height})";
  433. }
  434. }
  435. }