Rect.cs 10 KB

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