home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
yacl-012.zip
/
ui
/
rectangl.cxx
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-04
|
9KB
|
392 lines
/*
*
* Copyright (C) 1994, M. A. Sridhar
*
*
* This software is Copyright M. A. Sridhar, 1994. You are free
* to copy, modify or distribute this software as you see fit,
* and to use it for any purpose, provided this copyright
* notice and the following disclaimer are included with all
* copies.
*
* DISCLAIMER
*
* The author makes no warranties, either expressed or implied,
* with respect to this software, its quality, performance,
* merchantability, or fitness for any particular purpose. This
* software is distributed AS IS. The user of this software
* assumes all risks as to its quality and performance. In no
* event shall the author be liable for any direct, indirect or
* consequential damages, even if the author has been advised
* as to the possibility of such damages.
*
*/
#if defined(__GNUC__)
#pragma implementation
#endif
#include "ui/rectangl.h"
#include "ui/dwgsurf.h"
#include "ui/containr.h"
#if defined(__MS_WINDOWS__)
#include <windows.h>
#endif
#if defined(__GNUC__)
#include "base/basicops.h"
template class CL_Basics<UI_Rectangle>;
#endif
//
//------------Constructors--------------------
//
UI_Rectangle::UI_Rectangle(const UI_Point& origin, long width, long height)
{
_origin = origin;
if (width < 0) {
width = -width;
_origin = _origin - UI_Point (width-1, 0); // Shift origin to left end
}
if (height < 0) {
height = -height;
_origin = _origin - UI_Point (0, height-1);
}
_height = height;
_width = width;
}
UI_Rectangle::UI_Rectangle (long x, long y, long width, long height)
{
_origin = UI_Point (x, y);
if (width < 0) {
width = -width;
_origin = _origin - UI_Point (width-1, 0); // Shift origin to left end
}
if (height < 0) {
height = -height;
_origin = _origin - UI_Point (0, height-1);
}
_height = height;
_width = width;
}
UI_Rectangle::UI_Rectangle()
{
_height = 0;
_width = 0;
}
UI_Rectangle::UI_Rectangle (const UI_RectangleStruct& r)
: _origin (r.x, r.y)
{
_width = r.w;
_height = r.h;
}
UI_Rectangle::UI_Rectangle(const UI_Rectangle& r)
{
_origin = r._origin;
_height = r. _height;
_width = r._width;
}
UI_Rectangle::~UI_Rectangle()
{
}
//
//------------Query and modification--------------
//
long UI_Rectangle::Height() const
{
return _height;
}
long UI_Rectangle::Width() const
{
return _width;
}
long UI_Rectangle::Area() const
{
return _height*_width;
}
UI_Rectangle UI_Rectangle::operator+ (const UI_Point& p) const
{
UI_Rectangle q (*this);
q._origin += p;
return q;
}
//
//----------------Virtual member functions from CL_Object--------
//
void UI_Rectangle::operator= (const CL_Object& r)
{
if (!IsA (r))
return;
*this = (const UI_Rectangle&) r;
}
void UI_Rectangle::operator= (const UI_Rectangle& r)
{
if (this == &r || *this == r || !PrepareToChange())
return;
_origin = r._origin;
_height = r._height;
_width = r._width;
Notify();
}
//
//------------Virtual methods from CL_Object-----------
//
bool UI_Rectangle::operator== (const CL_Object& r) const
{
if (!IsA (r))
return FALSE;
return (*this == (const UI_Rectangle&) r);
}
bool UI_Rectangle::operator== (const UI_Rectangle& r) const
{
if (_origin != r._origin || _width != r._width || _height != r._height)
return FALSE;
return TRUE;
}
CL_String UI_Rectangle::AsString() const
{
CL_String s;
s.AssignWithFormat ("(%ld, %ld, %ld, %ld)", _origin.XCoord(),
_origin.YCoord(), _width, _height);
return s;
}
void UI_Rectangle::Origin (const UI_Point& o)
{
if (!PrepareToChange())
return;
_origin = o;
Notify();
}
void UI_Rectangle::AddToHeight (long incr)
{
long new_val = _height + incr;
if (new_val >= 0) {
if (!PrepareToChange())
return;
_height = new_val;
Notify();
}
}
void UI_Rectangle::AddToWidth (long incr)
{
long new_val = _width + incr;
if (new_val >= 0) {
if (!PrepareToChange())
return;
_width = new_val;
Notify();
}
}
bool UI_Rectangle::DrawOn (UI_DrawingSurface& sfc, const UI_Point& p) const
{
UI_Rectangle r (*this);
r += p;
sfc.DrawRectangle (r, UID_Outline);
return TRUE;
}
bool UI_Rectangle::Fill (UI_DrawingSurface& s) const
{
s.DrawRectangle (*this, UID_Fill);
return TRUE;
}
bool UI_Rectangle::Includes(const UI_Point& p) const
{
long x, y, x1, x2, y1, y2;
x = p.XCoord();
y = p.YCoord();
x1 = _origin.XCoord();
y1 = _origin.YCoord();
x2 = x1 + _width;
y2 = y1 + _height;
return (x >= x1 && x <= x2 && y >= y1 && y <= y2);
}
bool UI_Rectangle::OnBoundary (const UI_Point& p) const
{
long px = p.XCoord(), py = p.YCoord();
long left = _origin.XCoord();
long right = left + _width;
long top = _origin.YCoord();
long bottom = top + _height;
return ((px == left || px == right) && py >= top && py <= bottom)
// on left or right side
|| ((py == top || py == bottom) && px >= left && px <= right);
// on top or bottom side
}
UI_HitTest UI_Rectangle::HitTest (const UI_Point& p) const
{
return OnBoundary (p) ? UIHit_Boundary
: (Includes (p) ? UIHit_Inside : UIHit_Outside);
}
static bool Intersects (const UI_Point& p1, long l1,
const UI_Point& p2, long l2)
{
// Determine if the vertical line segment at p1 of length l1
// intersects the horizontal line segment at p2 of length l2
long x1 = p1.XCoord(), y1 = p1.YCoord();
long x2 = p2.XCoord(), y2 = p2.YCoord();
return y1 <= y2 && y1 + l1 > y2 && x1 >= x2 && x1 < x2 + l2;
}
bool UI_Rectangle::IntersectsBoundary (const UI_Rectangle& rect) const
{
// UI_Point tl = TopLeft(), tr = TopRight();
// UI_Point bl = BottomLeft(), br = BottomRight();
// bool b1 = rect.Includes (tl), b2 = rect.Includes (bl);
// bool b2 = rect.Includes (tr), b4 = rect.Includes (br);
// if ((b1 || b2 || b3 || b4) && ! (b1 && b2 && b3 && b4))
// return TRUE;
// tl = rect.TopLeft(); tr = rect.TopRight();
// bl = rect.BottomLeft(), br = rect.BottomRight();
// b1 = Includes (tl), b2 = Includes (bl);
// b2 = Includes (tr), b4 = Includes (br);
// if ((b1 || b2 || b3 || b4) && ! (b1 && b2 && b3 && b4))
// return TRUE;
long h = rect.Height(), w = rect.Width();
if (Intersects (rect.TopLeft(), h, TopLeft(), _width) ||
Intersects (rect.TopRight(), h, TopLeft(), _width) ||
Intersects (rect.TopLeft(), h, BottomLeft(), _width) ||
Intersects (rect.TopRight(), h, BottomLeft(), _width) ||
Intersects (TopLeft(), _height, rect.TopLeft(), w) ||
Intersects (TopRight(), _height, rect.TopLeft(), w) ||
Intersects (TopLeft(), _height, rect.BottomLeft(), w) ||
Intersects (TopRight(), _height, rect.BottomLeft(), w)
)
return TRUE;
return FALSE;
}
UI_Point UI_Rectangle::Center () const
{
return UI_Point (_origin.XCoord() + maxl (1, _width)/2 - 1,
_origin.YCoord() + maxl (1, _height)/2 - 1);
}
bool UI_Rectangle::ReshapeTo (const UI_Point& p1, const UI_Point& p2)
{
UI_Rectangle r (p1, p2.XCoord() - p1.XCoord() + 1, p2.YCoord() -
p1.YCoord() + 1);
*this = r; // This does the notification
return TRUE;
}
bool UI_Rectangle::IsContainedIn (const UI_Rectangle& r) const
{
return Includes (r.TopLeft()) && Includes (r.BottomLeft())
&& Includes (r.TopRight()) && Includes (r.BottomRight());
}
CL_Sequence<UI_Point> UI_Rectangle::RowMajor (long m, long n) const
{
if (m <= 0 || n <= 0) {
CL_Error::Warning ("UI_Rectangle::RowMajor: invalid parameters"
" %ld %ld", m, n);
CL_Sequence<UI_Point> junk;
return junk;
}
long ncols = _width/m;
long nrows = _height/n;
if (nrows <= 0 || ncols <= 0) {
CL_Sequence<UI_Point> junk;
return junk;
}
CL_Sequence<UI_Point> seq (nrows * ncols);
long x = _origin.XCoord();
long y = _origin.YCoord();
for (long i = 0; i < nrows; i++) {
long xpt = x;
long ypt = y + i * n;
for (long j = 0; j < ncols; j++) {
seq[i * ncols + j] = UI_Point (xpt, ypt);
xpt += m;
}
}
return seq;
}
#if defined(__MS_WINDOWS__)
tagRECT UI_Rectangle::AsMSRect () const
{
RECT rect;
rect.left = Left ();
rect.top = Top ();
rect.right = Right();
rect.bottom = Bottom();
return rect;
}
#endif