home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / yacl-012.zip / ui / rectangl.cxx < prev    next >
C/C++ Source or Header  |  1995-04-04  |  9KB  |  392 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6. /*
  7.  *
  8.  *          Copyright (C) 1994, M. A. Sridhar
  9.  *  
  10.  *
  11.  *     This software is Copyright M. A. Sridhar, 1994. You are free
  12.  *     to copy, modify or distribute this software  as you see fit,
  13.  *     and to use  it  for  any  purpose, provided   this copyright
  14.  *     notice and the following   disclaimer are included  with all
  15.  *     copies.
  16.  *
  17.  *                        DISCLAIMER
  18.  *
  19.  *     The author makes no warranties, either expressed or implied,
  20.  *     with respect  to  this  software, its  quality, performance,
  21.  *     merchantability, or fitness for any particular purpose. This
  22.  *     software is distributed  AS IS.  The  user of this  software
  23.  *     assumes all risks  as to its quality  and performance. In no
  24.  *     event shall the author be liable for any direct, indirect or
  25.  *     consequential damages, even if the  author has been  advised
  26.  *     as to the possibility of such damages.
  27.  *
  28.  */
  29.  
  30.  
  31.  
  32. #if defined(__GNUC__)
  33. #pragma implementation
  34. #endif
  35.  
  36.  
  37.  
  38. #include "ui/rectangl.h"
  39. #include "ui/dwgsurf.h"
  40. #include "ui/containr.h"
  41.  
  42. #if defined(__MS_WINDOWS__)
  43. #include <windows.h>
  44. #endif
  45.  
  46. #if defined(__GNUC__)
  47. #include "base/basicops.h"
  48. template class CL_Basics<UI_Rectangle>;
  49. #endif
  50.  
  51. //
  52. //------------Constructors--------------------
  53. //
  54.  
  55. UI_Rectangle::UI_Rectangle(const UI_Point& origin, long width, long height)
  56. {
  57.     _origin = origin;
  58.     if (width < 0) {
  59.         width = -width;
  60.         _origin = _origin - UI_Point (width-1, 0); // Shift origin to left end
  61.     }
  62.     if (height < 0) {
  63.         height = -height;
  64.         _origin = _origin - UI_Point (0, height-1); 
  65.     }
  66.     _height = height;
  67.     _width  = width;
  68. }
  69.  
  70. UI_Rectangle::UI_Rectangle (long x, long y, long width, long height)
  71. {
  72.     _origin = UI_Point (x, y);
  73.     if (width < 0) {
  74.         width = -width;
  75.         _origin = _origin - UI_Point (width-1, 0); // Shift origin to left end
  76.     }
  77.     if (height < 0) {
  78.         height = -height;
  79.         _origin = _origin - UI_Point (0, height-1); 
  80.     }
  81.     _height = height;
  82.     _width  = width;
  83. }
  84.  
  85.  
  86. UI_Rectangle::UI_Rectangle()
  87. {
  88.    _height = 0;
  89.    _width  = 0;
  90. }
  91.  
  92.  
  93. UI_Rectangle::UI_Rectangle (const UI_RectangleStruct& r)
  94. : _origin (r.x, r.y)
  95. {
  96.     _width = r.w;
  97.     _height = r.h;
  98. }
  99.  
  100.  
  101. UI_Rectangle::UI_Rectangle(const UI_Rectangle& r)
  102. {
  103.     _origin = r._origin;
  104.     _height = r. _height;
  105.     _width = r._width;
  106.  
  107.     
  108. }
  109.  
  110.  
  111. UI_Rectangle::~UI_Rectangle()
  112. {
  113. }
  114.  
  115. //
  116. //------------Query and modification--------------
  117. //
  118.     
  119. long UI_Rectangle::Height() const
  120. {
  121.     return _height;
  122. }
  123.  
  124. long UI_Rectangle::Width() const
  125. {
  126.     return _width;
  127. }
  128.  
  129. long UI_Rectangle::Area() const
  130. {
  131.     return _height*_width;
  132. }
  133.  
  134.  
  135.  
  136.  
  137. UI_Rectangle UI_Rectangle::operator+ (const UI_Point& p) const
  138. {
  139.     UI_Rectangle q (*this);
  140.     q._origin += p;
  141.     return q;
  142. }
  143.  
  144. //
  145. //----------------Virtual member functions from CL_Object--------
  146. //
  147.  
  148. void UI_Rectangle::operator= (const CL_Object& r)
  149. {
  150.     if (!IsA (r))
  151.         return;
  152.     *this = (const UI_Rectangle&) r;
  153. }
  154.  
  155.  
  156. void UI_Rectangle::operator= (const UI_Rectangle& r)
  157. {
  158.     if (this == &r  || *this == r || !PrepareToChange())
  159.         return;
  160.     _origin = r._origin; 
  161.     _height = r._height;
  162.     _width  = r._width;
  163.     Notify();
  164. }
  165.  
  166.  
  167. //
  168. //------------Virtual methods from CL_Object-----------
  169. //
  170.  
  171. bool UI_Rectangle::operator== (const CL_Object& r) const
  172. {
  173.     if (!IsA (r))
  174.         return FALSE;
  175.     return (*this == (const UI_Rectangle&) r);
  176. }
  177.  
  178.  
  179. bool UI_Rectangle::operator== (const UI_Rectangle& r) const
  180. {
  181.     if (_origin != r._origin || _width != r._width || _height != r._height)
  182.         return FALSE;
  183.     return TRUE;
  184. }
  185.  
  186.  
  187. CL_String UI_Rectangle::AsString() const
  188. {
  189.     CL_String s;
  190.     s.AssignWithFormat ("(%ld, %ld, %ld, %ld)", _origin.XCoord(),
  191.                         _origin.YCoord(), _width, _height);
  192.     return s;
  193. }
  194.  
  195.  
  196. void UI_Rectangle::Origin  (const UI_Point& o)
  197. {
  198.     if (!PrepareToChange())
  199.         return;
  200.     _origin = o;
  201.     Notify();
  202. }
  203.  
  204.  
  205.  
  206. void UI_Rectangle::AddToHeight (long incr)
  207. {
  208.     long new_val = _height + incr;
  209.     if (new_val >= 0) {
  210.         if (!PrepareToChange())
  211.             return;
  212.         _height = new_val;
  213.         Notify();
  214.     }
  215. }
  216.  
  217.  
  218.  
  219. void UI_Rectangle::AddToWidth (long incr)
  220. {
  221.     long new_val = _width + incr;
  222.     if (new_val >= 0) {
  223.         if (!PrepareToChange())
  224.             return;
  225.         _width = new_val;
  226.         Notify();
  227.     }
  228. }
  229.  
  230.  
  231.  
  232. bool UI_Rectangle::DrawOn (UI_DrawingSurface& sfc, const UI_Point& p) const
  233. {
  234.     UI_Rectangle r (*this);
  235.     r += p;
  236.     sfc.DrawRectangle (r, UID_Outline);
  237.     return TRUE;
  238. }
  239.  
  240.  
  241. bool UI_Rectangle::Fill (UI_DrawingSurface& s) const
  242. {
  243.     s.DrawRectangle (*this, UID_Fill);
  244.     return TRUE;
  245. }
  246.  
  247.  
  248.  
  249. bool UI_Rectangle::Includes(const UI_Point& p) const
  250. {
  251.     long x, y, x1, x2, y1, y2;
  252.     x = p.XCoord();
  253.     y = p.YCoord();
  254.  
  255.     x1 = _origin.XCoord();
  256.     y1 = _origin.YCoord();
  257.  
  258.     x2 = x1 + _width;
  259.     y2 = y1 + _height;
  260.  
  261.     return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
  262. }
  263.  
  264. bool UI_Rectangle::OnBoundary (const UI_Point& p) const
  265. {
  266.     long px = p.XCoord(), py = p.YCoord();
  267.     long left    = _origin.XCoord();
  268.     long right   = left + _width;
  269.     long top     = _origin.YCoord();
  270.     long bottom  = top + _height;
  271.     return ((px == left || px == right)  && py >= top  && py <= bottom)
  272.                // on left or right side
  273.         || ((py == top || py == bottom)  && px >= left && px <= right);
  274.                // on top or bottom side
  275. }
  276.  
  277.  
  278. UI_HitTest UI_Rectangle::HitTest (const UI_Point& p) const
  279. {
  280.     return OnBoundary (p) ? UIHit_Boundary
  281.         : (Includes (p) ? UIHit_Inside : UIHit_Outside);
  282. }
  283.  
  284.  
  285.  
  286.  
  287. static bool Intersects (const UI_Point& p1, long l1,
  288.                         const UI_Point& p2, long l2)
  289. {
  290.     // Determine if the vertical line segment at p1 of length l1
  291.     // intersects the horizontal line segment at p2 of length l2
  292.     long x1 = p1.XCoord(), y1 = p1.YCoord();
  293.     long x2 = p2.XCoord(), y2 = p2.YCoord();
  294.     return y1 <= y2 && y1 + l1 > y2 && x1 >= x2 && x1 < x2 + l2;
  295. }
  296.  
  297. bool UI_Rectangle::IntersectsBoundary (const UI_Rectangle& rect) const
  298. {
  299. //     UI_Point tl = TopLeft(),    tr = TopRight();
  300. //     UI_Point bl = BottomLeft(), br = BottomRight();
  301. //     bool b1 = rect.Includes (tl),  b2 = rect.Includes (bl);
  302. //     bool b2 = rect.Includes (tr),  b4 = rect.Includes (br);
  303. //     if ((b1 || b2 || b3 || b4) && ! (b1 && b2 && b3 && b4))
  304. //         return TRUE;
  305. //     tl = rect.TopLeft(); tr = rect.TopRight();
  306. //     bl = rect.BottomLeft(), br = rect.BottomRight();
  307. //     b1 = Includes (tl),  b2 = Includes (bl);
  308. //     b2 = Includes (tr),  b4 = Includes (br);
  309. //     if ((b1 || b2 || b3 || b4) && ! (b1 && b2 && b3 && b4))
  310. //         return TRUE;
  311.     long h = rect.Height(), w = rect.Width();
  312.     if (Intersects (rect.TopLeft(),  h, TopLeft(), _width) ||
  313.         Intersects (rect.TopRight(), h, TopLeft(), _width) ||
  314.         Intersects (rect.TopLeft(),  h, BottomLeft(), _width) ||
  315.         Intersects (rect.TopRight(), h, BottomLeft(), _width) ||
  316.         Intersects (TopLeft(),  _height, rect.TopLeft(), w) ||
  317.         Intersects (TopRight(), _height, rect.TopLeft(), w) ||
  318.         Intersects (TopLeft(),  _height, rect.BottomLeft(), w) ||
  319.         Intersects (TopRight(), _height, rect.BottomLeft(), w)
  320.         )
  321.         return TRUE;
  322.     return FALSE;
  323. }
  324.  
  325.  
  326. UI_Point UI_Rectangle::Center () const
  327. {
  328.     return UI_Point (_origin.XCoord() + maxl (1, _width)/2 - 1,
  329.                      _origin.YCoord() + maxl (1, _height)/2 - 1);
  330. }
  331.  
  332.  
  333. bool UI_Rectangle::ReshapeTo (const UI_Point& p1, const UI_Point& p2)
  334. {
  335.     UI_Rectangle r (p1, p2.XCoord() - p1.XCoord() + 1, p2.YCoord() -
  336.                     p1.YCoord() + 1);
  337.     *this = r; // This does the notification
  338.     return TRUE;
  339. }
  340.  
  341.  
  342. bool UI_Rectangle::IsContainedIn (const UI_Rectangle& r) const
  343. {
  344.     return  Includes (r.TopLeft())  && Includes (r.BottomLeft())
  345.         &&  Includes (r.TopRight()) && Includes (r.BottomRight());
  346. }
  347.  
  348.  
  349. CL_Sequence<UI_Point> UI_Rectangle::RowMajor (long m, long n) const
  350. {
  351.     if (m <= 0 || n <= 0) {
  352.         CL_Error::Warning ("UI_Rectangle::RowMajor: invalid parameters"
  353.                            " %ld %ld", m, n);
  354.         CL_Sequence<UI_Point> junk;
  355.         return junk;
  356.     }
  357.     long ncols = _width/m;
  358.     long nrows = _height/n;
  359.     if (nrows <= 0 || ncols <= 0) {
  360.         CL_Sequence<UI_Point> junk;
  361.         return junk;
  362.     }
  363.     CL_Sequence<UI_Point> seq (nrows * ncols);
  364.     long x = _origin.XCoord();
  365.     long y = _origin.YCoord();
  366.     for (long i = 0; i < nrows; i++) {
  367.         long xpt = x;
  368.         long ypt = y + i * n;
  369.         for (long j = 0; j < ncols; j++) {
  370.             seq[i * ncols + j] = UI_Point (xpt, ypt);
  371.             xpt += m;
  372.         }
  373.     }
  374.     return seq;
  375. }
  376.  
  377.  
  378.  
  379. #if defined(__MS_WINDOWS__)
  380. tagRECT UI_Rectangle::AsMSRect () const
  381. {
  382.     RECT rect;
  383.     rect.left   = Left ();  
  384.     rect.top    = Top ();
  385.     rect.right  = Right();
  386.     rect.bottom = Bottom();
  387.     return rect;
  388. }
  389.  
  390. #endif
  391.  
  392.