// Copyright 2000
// College of Computer Science
// Northeastern University Boston MA 02115

// This software may be used for educational purposes as long as this copyright
// notice is retained at the top of all files

// Should this software be modified, the words "Modified from Original" must be
// included as a comment below this notice

// All publication rights are retained.  This software or its documentation may
// not be published in any media either in whole or in part.

///////////////////////////////////////////////////////////////////////////////

// GraphicsWidget.h

///////////////////////////////////////////////////////////////////////////////

#ifndef GRAPHICSWIDGET_H_
#define GRAPHICSWIDGET_H_

#include "GraphicsObject.h"
#include "RGB.h"
#include "Scale2D.h"


///////////////////////////////////////////////////////////////////////////////

class EXPORT PolygonWidget;

class EXPORT RectWidget;
class EXPORT OvalWidget;

class EXPORT PixelWidget;

class EXPORT MoveToWidget;
class EXPORT LineWidget;
class EXPORT LineToWidget;
class EXPORT DeltaLineWidget;
class EXPORT DeltaMoveWidget;

class EXPORT TransformWidget;

class EXPORT PolygonWidget2D;

class EXPORT RectWidget2D;
class EXPORT OvalWidget2D;

class EXPORT LineWidget2D;
class EXPORT LineToWidget2D;
class EXPORT MoveToWidget2D;
class EXPORT DeltaLineWidget2D;
class EXPORT DeltaMoveWidget2D;

class EXPORT PenSizeWidget;
class EXPORT PenModeWidget;
class EXPORT PenColorWidget;
class EXPORT FillColorWidget;

class EXPORT TextWidget;
class EXPORT TextAlignWidget;
class EXPORT TextColorWidget;

class EXPORT BackgroundModeWidget;
class EXPORT BackgroundColorWidget;


///////////////////////////////////////////////////////////////////////////////

// PolygonWidget can be framed or filled or both

class EXPORT PolygonWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	PenSize, PenMode, PenColor, FillColor
	// changes:
	
	// The following modes will fill:
	//    Fill,  FrameFill == FillFrame, White, Black, Invert
	//
	// The following modes will frame:
	//    Frame, FrameFill == FillFrame
	//
	// FrameFill == FillFrame fills first then frames

private:

	friend class Polygon2D;

	// represent a polygon

	PolygonData Poly;

	// ImageMethod variable defines how to image the object

	short ImageMethod;

	// represent the polygon fill mode (PFM_Regular or PFM_Winding)

	short PolyFillMode;


	virtual void DrawDetails(GraphicsWindow& G) const;

	void DoFill (GraphicsWindow& G) const;				// interior

	void DoFrame(GraphicsWindow& G) const;				// exterior

	void DoBoth (GraphicsWindow& G) const;				// interior + exterior

#if defined(CORE_PLATFORM_WIN32)

	HRGN PolygonInterior(GraphicsWindow& G) const;		// interior

	HRGN PolygonExterior(GraphicsWindow& G) const;		// exterior

	HRGN CompletePolygon(GraphicsWindow& G) const;		// interior + exterior

#endif	// end WIN32 specific

public:

	virtual GraphicsObject* Clone() const {
		return new PolygonWidget(*this);
	};

	
	// set function

	PolygonWidget& Set(const PolygonData& poly) { Poly = poly; return *this; };


	// constructors

	PolygonWidget(int size = 1) :
		Poly(size),
		ImageMethod(FF_FrameFill),
		PolyFillMode(PFM_Regular)
			{ };


	PolygonWidget(const PolygonData& poly) :
		Poly(poly),
		ImageMethod(FF_FrameFill),
		PolyFillMode(PFM_Regular)
			{ };


	// building functions

	bool Append(const PointData& P) {
		return Poly.Append(P);
	};


	bool Append(short x, short y) {
		return Poly.Append(x, y);
	};


	// ClearPolygon makes all data invalid

	PolygonWidget& ClearPolygon() { 
		Poly.ClearPolygon();
		return *this;
	};


	// ClosePolygon appends a point at the end equal to the first point
	// Does nothing if polygon is empty

	PolygonWidget& ClosePolygon() {
		Poly.ClosePolygon();
		return *this;
	};


	// Offset shifts the polygon

	PolygonWidget& Offset(const PointData& P) {
		Poly.Offset(P);
		return *this;
	};


	PolygonWidget& Offset(short dx, short dy) {
		PointData P(dx, dy);
		return Offset(P);
	};


	// change the amount of allocated polygon memory

	PolygonWidget& ChangeMemory(int NewSize) {
		Poly.ChangeMemory(NewSize);
		return *this;
	};


	// destructor

	virtual ~PolygonWidget() { };


	// setting frame and fill

	PolygonWidget& SetFill()
		{ ImageMethod = FF_Fill; return *this; };

	PolygonWidget& SetFrame()
		{ ImageMethod = FF_Frame; return *this; };

	// SetFrameFill() and SetFrameFill() are the same

	PolygonWidget& SetFillFrame()
		{ ImageMethod = FF_FillFrame; return *this; };

	PolygonWidget& SetFrameFill()
		{ ImageMethod = FF_FrameFill; return *this; };

	// set the current ImageMethod

	PolygonWidget& SetImageMethod(short imagemethod) {
		switch (imagemethod) {
			case FF_Fill:
			case FF_Frame:
			case FF_FrameFill:

				ImageMethod = imagemethod;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this; 
	};

	// get the current ImageMethod

	short GetImageMethod() const
		{ return ImageMethod; };


	// handle fill mode

	PolygonWidget& SetRegularFill()
		{ PolyFillMode = PFM_Regular; return *this; };


	PolygonWidget& SetWindingFill()
		{ PolyFillMode = PFM_Winding; return *this; };


	PolygonWidget& SetPolyFillMode(short mode) {
		switch(mode) {
		
			case PFM_Regular:
			case PFM_Winding:
		
				PolyFillMode = mode;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this;
	};


	short GetPolyFillMode()
		{ return PolyFillMode; };

}; // PolygonWidget


///////////////////////////////////////////////////////////////////////////////

// RectWidget handles drawing of rectangles

class EXPORT RectWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	PenSize, PenMode, PenColor, FillColor
	// changes:	

private:

	friend class RectWidget2D;

	// represent a rectangle

	RectData R;

	// ImageMethod variable defines how to image the object

	short ImageMethod;


	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new RectWidget(*this);
	};


	RectWidget& Set(const RectData& r) {
		R = r;

		return *this;
	};


	RectWidget& Set(const PointData& p, const PointData& q) {
		R.Set(p, q);

		return *this;
	};


	RectWidget& Set(short x1, short y1, short x2, short y2) {
		R.Set(x1, y1, x2, y2);

		return *this;
	};


	void Get(RectData& r) const { r = R; };


	void Get(PointData& p, PointData& q) const { R.Get(p, q); };


	void Get(short& x1, short& y1, short& x2, short& y2) const { R.Get(x1, y1, x2, y2); };


	// default in constructors is to choose both frame and fill

	RectWidget() :
		ImageMethod(FF_FrameFill)
			{ Set(0, 0, 0, 0); };


	RectWidget(const RectData& r) :
		ImageMethod(FF_FrameFill)
			{ Set(r); };


	RectWidget(const PointData& p, const PointData& q) :
		ImageMethod(FF_FrameFill)
			{ Set(p, q); };


	RectWidget(short x1, short y1, short x2, short y2) :
		ImageMethod(FF_FrameFill)
			{ Set(x1, y1, x2, y2); };


	virtual ~RectWidget() { };


	// setting frame and fill

	RectWidget& SetFill()
		{ ImageMethod = FF_Fill; return *this; };

	RectWidget& SetFrame()
		{ ImageMethod = FF_Frame; return *this; };

	// SetFrameFill() and SetFrameFill() are the same

	RectWidget& SetFillFrame()
		{ ImageMethod = FF_FillFrame; return *this; };

	RectWidget& SetFrameFill()
		{ ImageMethod = FF_FrameFill; return *this; };

	// set the current ImageMethod

	RectWidget& SetImageMethod(short imagemethod) {
		switch (imagemethod) {
			case FF_Fill:
			case FF_Frame:
			case FF_FrameFill:

				ImageMethod = imagemethod;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this; 
	};

	// get the current ImageMethod

	short GetImageMethod() const
		{ return ImageMethod; };

}; // RectWidget


class EXPORT OvalWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	PenSize, PenMode, PenColor, FillColor
	// changes:	

private:

	friend class OvalWidget2D;
	
	// represent the rectangle forming the bounding box of the oval

	RectData R;

	// ImageMethod variable defines how to image the object

	short ImageMethod;


	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new OvalWidget(*this);
	};


	OvalWidget& Set(const RectData& r) {
		R = r;

		return *this;
	};


	OvalWidget& Set(const PointData& p, const PointData& q) {
		R.Set(p, q);

		return *this;
	};


	OvalWidget& Set(short x1, short y1, short x2, short y2) {
		R.Set(x1, y1, x2, y2);

		return *this;
	};


	void Get(RectData& r) const { r = R; };


	void Get(PointData& p, PointData& q) const { R.Get(p, q); };


	void Get(short& x1, short& y1, short& x2, short& y2) const { R.Get(x1, y1, x2, y2); };


	// default in constructors is to choose both frame and fill

	OvalWidget() :
		ImageMethod(FF_FrameFill)
			{ Set(0, 0, 0, 0); };


	OvalWidget(const RectData& r) :
		ImageMethod(FF_FrameFill)
			{ Set(r); };


	OvalWidget(const PointData& p, const PointData& q) :
		ImageMethod(FF_FrameFill)
			{ Set(p, q); };


	OvalWidget(short x1, short y1, short x2, short y2) :
		ImageMethod(FF_FrameFill)
			{ Set(x1, y1, x2, y2); };


	virtual ~OvalWidget() { };


	// setting frame and fill

	OvalWidget& SetFill()
		{ ImageMethod = FF_Fill; return *this; };

	OvalWidget& SetFrame()
		{ ImageMethod = FF_Frame; return *this; };

	// SetFrameFill() and SetFrameFill() are the same

	OvalWidget& SetFillFrame()
		{ ImageMethod = FF_FillFrame; return *this; };

	OvalWidget& SetFrameFill()
		{ ImageMethod = FF_FrameFill; return *this; };

	// set the current ImageMethod

	OvalWidget& SetImageMethod(short imagemethod) {
		switch (imagemethod) {
			case FF_Fill:
			case FF_Frame:
			case FF_FrameFill:

				ImageMethod = imagemethod;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this; 
	};

	// get the current ImageMethod

	short GetImageMethod() const
		{ return ImageMethod; };

}; // OvalWidget

///////////////////////////////////////////////////////////////////////////////

// PixelWidget stores an x,y position and a color
// The Draw method sets the pixel at x,y with the internal color
// The Peek method sets the internal color using the pixel value at x,y

// Sample usages for a PixelWidget PW interacting with the default window
//
// Draw:
//     PW.Set(X, Y, R, G, B).Draw();
//
// Peek:
//     PW.SetPixel(X, Y).Peek().GetColor(R, G, B);


class EXPORT PixelWidget : public GraphicsObject {

	// No GraphicsState interactions
	// No ImageMethod

private:

	short x;
	short y;
	RGBdata color;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new PixelWidget(*this);
	};


	PixelWidget& Peek(GraphicsWindow& G);


	PixelWidget& Peek(int index = -1);


	PixelWidget& Set(const PointData& P, const RGBdata& Color) {
		P.Get(x, y);
		color = Color;

		return *this;
	};


	PixelWidget& Set(short X, short Y, const RGBdata& Color) {
		x = X;
		y = Y;
		color = Color;

		return *this;
	};


	PixelWidget& Set(const PointData& P, byte R, byte G, byte B) {
		P.Get(x, y);
		color.Set(R, G, B);

		return *this;
	};


	PixelWidget& Set(short X, short Y, byte R, byte G, byte B) {
		x = X;
		y = Y;
		color.Set(R, G, B);

		return *this;
	};


	PixelWidget& SetPixel(const PointData& P) {
		P.Get(x, y);

		return *this;
	};


	PixelWidget& SetPixel(short X, short Y) {
		x = X;
		y = Y;

		return *this;
	};


	PixelWidget& SetColor(const RGBdata& Color) {
		color = Color;

		return *this;
	};


	PixelWidget& SetColor(byte R, byte G, byte B) {
		color.Set(R, G, B);

		return *this;
	};


	void Get(PointData& P, RGBdata& Color) const {
		P.Set(x, y);
		Color = color;
	};


	void Get(short& X, short& Y, RGBdata& Color) const {
		X = x;
		Y = y;
		Color = color;
	};


	void Get(PointData& P, byte& R, byte& G, byte& B) const {
		P.Set(x, y);
		color.Get(R, G, B);
	};


	void Get(short& X, short& Y, byte& R, byte& G, byte& B) const {
		X = x;
		Y = y;
		color.Get(R, G, B);
	};


	void Get(PointData& P, short& R, short& G, short& B) const {
		P.Set(x, y);
		color.Get(R, G, B);
	};

	
	void Get(short& X, short& Y, short& R, short& G, short& B) const {
		X = x;
		Y = y;
		color.Get(R, G, B);
	};


	void GetPixel(PointData& P) const {
		P.Set(x, y);
	};


	void GetPixel(short& X, short& Y) const {
		X = x;
		Y = y;
	};


	void GetPixel(long& X, long& Y) const {
		X = x;
		Y = y;
	};


	void GetPixel(int& X, int& Y) const {
		X = x;
		Y = y;
	};


	void GetColor(RGBdata& Color) const {
		Color = color;
	};


	void GetColor(byte& R, byte& G, byte& B) const {
		color.Get(R, G, B);
	};


	void GetColor(short& R, short& G, short& B) const {
		color.Get(R, G, B);
	};


	void GetColor(long& R, long& G, long& B) const {
		color.Get(R, G, B);
	};


	void GetColor(int& R, int& G, int& B) const {
		color.Get(R, G, B);
	};


	PixelWidget()
		{ Set(0, 0, 0, 0, 0); };


	PixelWidget(const PointData& P, const RGBdata& Color)
		{ Set(P, Color); };


	PixelWidget(short X, short Y, const RGBdata& Color)
		{ Set(X, Y, Color); };


	PixelWidget(const PointData& P, byte R, byte G, byte B)
		{ Set(P, R, G, B); };


	PixelWidget(short X, short Y, byte R, byte G, byte B)
		{ Set(X, Y, R, G, B); };


	virtual ~PixelWidget() { };

}; // PixelWidget


///////////////////////////////////////////////////////////////////////////////

// For line widgets only Frame makes sense so
// Fill and FrameFill calls will be omitted

// For move widgets there is no ImageMethod

///////////////////////////////////////////////////////////////////////////////

// MoveToWidget changes current location to a new absolute position

class EXPORT MoveToWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	
	// changes:	Location

private:

	friend class MoveToWidget2D;

	// represent a target point P

	PointData P;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new MoveToWidget(*this);
	};


	MoveToWidget& Set(const PointData& p) {
		P = p;

		return *this;
	};


	MoveToWidget& Set(short x, short y) {
		P.Set(x, y);

		return *this;
	};


	void Get(PointData& p) const {
		p = P;
	};


	void Get(short& x, short& y) const {
		P.Get(x, y);
	};


	MoveToWidget() { Set(0, 0); };


	MoveToWidget(const PointData& p) { Set(p); };


	MoveToWidget(short x, short y) { Set(x, y); };


	virtual ~MoveToWidget() { };

}; // MoveToWidget


// LineWidget draws a line given two absolute point positions

class EXPORT LineWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	PenSize, PenMode, PenColor [BackgroundMode, BackgroundColor]
	// changes:	Location

private:

	friend class LineWidget2D;

	// represent a line from P to Q

	PointData P;
	PointData Q;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new LineWidget(*this);
	};


	LineWidget& Set(const PointData& p, const PointData& q) {
		P = p;
		Q = q;

		return *this;
	};


	LineWidget& Set(short x1, short y1, short x2, short y2) {
		P.Set(x1, y1);
		Q.Set(x2, y2);

		return *this;
	};


	void Get(PointData& p, PointData& q) const {
		p = P;
		q = Q;
	};


	void Get(short& x1, short& y1, short& x2, short& y2) const {
		P.Get(x1, y1);
		Q.Get(x2, y2);
	};


	LineWidget() { Set(0, 0, 0, 0); };


	LineWidget(const PointData& p, const PointData& q) { Set(p, q); };


	LineWidget(short x1, short y1, short x2, short y2) { Set(x1, y1, x2, y2); };


	virtual ~LineWidget() { };

}; // LineWidget


// LineToWidget draws a line from current location to a new absolute position

class EXPORT LineToWidget : public IndirectObject {

	// GraphicsState interactions
	// uses:	Location, PenMode, PenSize, PenColor [BackgroundMode, BackgroundColor]
	// changes:	Location

private:

	friend class LineToWidget2D;

	// represent a target point P

	PointData P;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	LineToWidget& Set(const PointData& p) {
		P = p;

		return *this;
	};


	LineToWidget& Set(short x, short y) {
		P.Set(x, y);

		return *this;
	};


	void Get(PointData& p) const {
		p = P;
	};


	void Get(short& x, short& y) const {
		P.Get(x, y);
	};


	LineToWidget() { Set(0, 0); };


	LineToWidget(const PointData& p) { Set(p); };


	LineToWidget(short x, short y) { Set(x, y); };


	virtual ~LineToWidget() { };

}; // LineToWidget


// DeltaLineWidget draws a line from current location using displacement Delta

class EXPORT DeltaLineWidget : public IndirectObject {

	// GraphicsState interactions
	// uses:	Location, PenMode, PenSize, PenColor [BackgroundMode, BackgroundColor]
	// changes:	Location

private:

	friend class DeltaLineWidget;

	// represent a displacement Delta

	PointData Delta;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	DeltaLineWidget& Set(const PointData& delta) {
		Delta = delta;

		return *this;
	};


	DeltaLineWidget& Set(short dx, short dy) {
		Delta.Set(dx, dy);

		return *this;
	};


	void Get(PointData& delta) const {
		delta = Delta;
	};


	void Get(short& dx, short& dy) const {
		Delta.Get(dx, dy);
	};


	DeltaLineWidget() { Set(0, 0); };


	DeltaLineWidget(const PointData& delta) { Set(delta); };


	DeltaLineWidget(short dx, short dy) { Set(dx, dy); };


	virtual ~DeltaLineWidget() { };

}; // DeltaLineWidget


// DeltaMoveWidget changes current location using displacement Delta

class EXPORT DeltaMoveWidget : public IndirectObject {

	// GraphicsState interactions
	// uses:	Location
	// changes:	Location

private:

	friend class DeltaMoveWidget2D;

	// represent a displacement Delta

	PointData Delta;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	DeltaMoveWidget& Set(const PointData& delta) {
		Delta = delta;

		return *this;
	};


	DeltaMoveWidget& Set(short dx, short dy) {
		Delta.Set(dx, dy);

		return *this;
	};


	void Get(PointData& delta) const {
		delta = Delta;
	};


	void Get(short& dx, short& dy) const {
		Delta.Get(dx, dy);
	};


	DeltaMoveWidget() { Set(0, 0); };


	DeltaMoveWidget(const PointData& delta) { Set(delta); };


	DeltaMoveWidget(short dx, short dy) { Set(dx, dy); };


	virtual ~DeltaMoveWidget() { };

}; // DeltaMoveWidget


///////////////////////////////////////////////////////////////////////////////

// Typical usage for a ClipRectWidget CRW
// Define some RectData R
//
// To use R as the clip rect:
//
//    CRW.Set(R).Enable().Draw(...);
//
// To stop clipping:
//
//    CRW.Stop().Draw(...);
//
// To use the same rect again as the clip rect:
//
//    CRW.Enable().Draw(...);
//
// A ClipRectWidget is initialized in the Stop state


class EXPORT ClipRectWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	
	// changes:	ClipRect, EnableClip [in GraphicsState]

private:

	RectData ClipRect;

	bool EnableClip;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new ClipRectWidget(*this);
	};


	ClipRectWidget() { EnableClip = false; };


	ClipRectWidget& Set(const RectData& cliprect) {
		ClipRect = cliprect;
		return *this;
	};


	ClipRectWidget& Enable () { EnableClip = true;  return *this; };


	ClipRectWidget& Stop()    { EnableClip = false; return *this; };


	virtual ~ClipRectWidget() { };
};


///////////////////////////////////////////////////////////////////////////////

class EXPORT TransformWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	
	// changes:	Transform [in GraphicsState]

private:

	LinearScale2D Transform;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new TransformWidget(*this);
	};


	TransformWidget& Set(const LinearScale2D& T) {
		Transform = T;
		return *this;
	};


	void Get(LinearScale2D& T) const { T = Transform; };


	TransformWidget() { Transform.Set(1, 0, 1, 0); };


	TransformWidget(const LinearScale2D& T) : Transform(T) { };


	virtual ~TransformWidget() { };
};


///////////////////////////////////////////////////////////////////////////////

// The following 2D widgets use the Transform in the WindowState to clone
// themselves to the corresponding pixel widget.  The pixel widget does
// the graphics and the necessary state changes.

///////////////////////////////////////////////////////////////////////////////

// PolygonWidget2D can be framed or filled or both

class EXPORT PolygonWidget2D : public IndirectObject {

	// GraphicsState interactions
	// uses:	PenSize, PenMode, PenColor, FillColor
	// changes:
	
	// The following modes will fill:
	//    Fill,  FrameFill == FillFrame, White, Black, Invert
	//
	// The following modes will frame:
	//    Frame, FrameFill == FillFrame
	//
	// FrameFill == FillFrame fills first then frames

private:

	// represent a polygon

	Polygon2D Poly;

	// ImageMethod variable defines how to image the object

	short ImageMethod;

	// represent the polygon fill mode (PFM_Regular or PFM_Winding)

	short PolyFillMode;


	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	// set function

	PolygonWidget2D& Set(const Polygon2D& poly) { Poly = poly; return *this; };


	// constructors

	PolygonWidget2D(int size = 1) :
		Poly(size),
		ImageMethod(FF_FrameFill),
		PolyFillMode(PFM_Regular)
			{ };


	PolygonWidget2D(const Polygon2D& poly) :
		Poly(poly),
		ImageMethod(FF_FrameFill),
		PolyFillMode(PFM_Regular)
			{ };


	// building functions

	bool Append(const Point2D& P) {
		return Poly.Append(P);
	};


	bool Append(double x, double y) {
		return Poly.Append(x, y);
	};


	// ClearPolygon makes all data invalid

	PolygonWidget2D& ClearPolygon() { 
		Poly.ClearPolygon();
		return *this;
	};


	// ClosePolygon appends a point at the end equal to the first point
	// Does nothing if polygon is empty

	PolygonWidget2D& ClosePolygon() {
		Poly.ClosePolygon();
		return *this;
	};


	// Offset shifts the polygon

	PolygonWidget2D& Offset(const Point2D& P) {
		Poly.Offset(P);
		return *this;
	};


	PolygonWidget2D& Offset(short dx, short dy) {
		Point2D P(dx, dy);
		return Offset(P);
	};


	// change the amount of allocated polygon memory

	PolygonWidget2D& ChangeMemory(int NewSize) {
		Poly.ChangeMemory(NewSize);
		return *this;
	};


	// destructor

	virtual ~PolygonWidget2D() { };


	// setting frame and fill

	PolygonWidget2D& SetFill()
		{ ImageMethod = FF_Fill; return *this; };

	PolygonWidget2D& SetFrame()
		{ ImageMethod = FF_Frame; return *this; };

	// SetFrameFill() and SetFrameFill() are the same

	PolygonWidget2D& SetFillFrame()
		{ ImageMethod = FF_FillFrame; return *this; };

	PolygonWidget2D& SetFrameFill()
		{ ImageMethod = FF_FrameFill; return *this; };

	// set the current ImageMethod

	PolygonWidget2D& SetImageMethod(short imagemethod) {
		switch (imagemethod) {
			case FF_Fill:
			case FF_Frame:
			case FF_FrameFill:

				ImageMethod = imagemethod;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this; 
	};

	// get the current ImageMethod

	short GetImageMethod() const
		{ return ImageMethod; };


	// handle fill mode

	PolygonWidget2D& SetRegularFill()
		{ PolyFillMode = PFM_Regular; return *this; };


	PolygonWidget2D& SetWindingFill()
		{ PolyFillMode = PFM_Winding; return *this; };


	PolygonWidget2D& SetPolyFillMode(short mode) {
		switch(mode) {
		
			case PFM_Regular:
			case PFM_Winding:
		
				PolyFillMode = mode;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this;
	};


	short GetPolyFillMode()
		{ return PolyFillMode; };

}; // PolygonWidget2D


///////////////////////////////////////////////////////////////////////////////

// RectWidget2D handles drawing of rectangles

class EXPORT RectWidget2D : public IndirectObject {

private:

	// represent a rectangle

	Rect2D R;

	// ImageMethod variable defines how to image the object

	short ImageMethod;


	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	RectWidget2D& Set(const Rect2D& r) {
		R = r;

		return *this;
	};


	RectWidget2D& Set(const Point2D& p, const Point2D& q) {
		R.Set(p, q);

		return *this;
	};


	RectWidget2D& Set(double x1, double y1, double x2, double y2) {
		R.Set(x1, y1, x2, y2);

		return *this;
	};


	void Get(Rect2D& r) const { r = R; };


	void Get(Point2D& p, Point2D& q) const { R.Get(p, q); };


	void Get(double& x1, double& y1, double& x2, double& y2) const { R.Get(x1, y1, x2, y2); };


	// default in constructors is to choose both frame and fill

	RectWidget2D() { Set(0, 0, 0, 0); };


	RectWidget2D(const Rect2D& r) { Set(r); };


	RectWidget2D(const Point2D& p, const Point2D& q) { Set(p, q); };


	RectWidget2D(double x1, double y1, double x2, double y2) { Set(x1, y1, x2, y2); };


	virtual ~RectWidget2D() { };


	// setting frame and fill

	RectWidget2D& SetFill()
		{ ImageMethod = FF_Fill; return *this; };

	RectWidget2D& SetFrame()
		{ ImageMethod = FF_Frame; return *this; };

	// SetFrameFill() and SetFrameFill() are the same

	RectWidget2D& SetFillFrame()
		{ ImageMethod = FF_FillFrame; return *this; };

	RectWidget2D& SetFrameFill()
		{ ImageMethod = FF_FrameFill; return *this; };

	// set the current ImageMethod

	RectWidget2D& SetImageMethod(short imagemethod) {
		switch (imagemethod) {
			case FF_Fill:
			case FF_Frame:
			case FF_FrameFill:

				ImageMethod = imagemethod;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this; 
	};

	// get the current ImageMethod

	short GetImageMethod() const
		{ return ImageMethod; };

}; // RectWidget2D


class EXPORT OvalWidget2D : public IndirectObject {

private:

	// represent the rectangle forming the bounding box of the oval

	Rect2D R;

	// ImageMethod variable defines how to image the object

	short ImageMethod;


	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	OvalWidget2D& Set(const Rect2D& r) {
		R = r;

		return *this;
	};


	OvalWidget2D& Set(const Point2D& p, const Point2D& q) {
		R.Set(p, q);

		return *this;
	};


	OvalWidget2D& Set(double x1, double y1, double x2, double y2) {
		R.Set(x1, y1, x2, y2);

		return *this;
	};


	void Get(Rect2D& r) const { r = R; };


	void Get(Point2D& p, Point2D& q) const { R.Get(p, q); };


	void Get(double& x1, double& y1, double& x2, double& y2) const { R.Get(x1, y1, x2, y2); };


	// default in constructors is to choose both frame and fill

	OvalWidget2D() :
		ImageMethod(FF_FrameFill)
			{ Set(0, 0, 0, 0); };


	OvalWidget2D(const RectData& r) :
		ImageMethod(FF_FrameFill)
			{ Set(r); };
	

	OvalWidget2D(const Point2D& p, const Point2D& q) :
		ImageMethod(FF_FrameFill)
			{ Set(p, q); };


	OvalWidget2D(double x1, double y1, double x2, double y2) :
		ImageMethod(FF_FrameFill)
			{ Set(x1, y1, x2, y2); };


	virtual ~OvalWidget2D() { };


	// setting frame and fill

	OvalWidget2D& SetFill()
		{ ImageMethod = FF_Fill; return *this; };

	OvalWidget2D& SetFrame()
		{ ImageMethod = FF_Frame; return *this; };

	// SetFrameFill() and SetFrameFill() are the same

	OvalWidget2D& SetFillFrame()
		{ ImageMethod = FF_FillFrame; return *this; };

	OvalWidget2D& SetFrameFill()
		{ ImageMethod = FF_FrameFill; return *this; };

	// set the current ImageMethod

	OvalWidget2D& SetImageMethod(short imagemethod) {
		switch (imagemethod) {
			case FF_Fill:
			case FF_Frame:
			case FF_FrameFill:

				ImageMethod = imagemethod;
				break;

			default:		// do not change if parameter is invalid
				break;
		}

		return *this; 
	};

	// get the current ImageMethod

	short GetImageMethod() const
		{ return ImageMethod; };

}; // OvalWidget2D


///////////////////////////////////////////////////////////////////////////////

// LineWidget2D draws a line given two absolute point positions

class EXPORT LineWidget2D : public IndirectObject {

private:

	// represent a line from P to Q

	Point2D P;
	Point2D Q;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	LineWidget2D& Set(const Point2D& p, const Point2D& q) {
		P = p;
		Q = q;

		return *this;
	};


	LineWidget2D& Set(double x1, double y1, double x2, double y2) {
		P.Set(x1, y1);
		Q.Set(x2, y2);

		return *this;
	};


	void Get(Point2D& p, Point2D& q) const {
		p = P;
		q = Q;
	};


	void Get(double& x1, double& y1, double& x2, double& y2) const {
		P.Get(x1, y1);
		Q.Get(x2, y2);
	};


	LineWidget2D() { Set(0, 0, 0, 0); };


	LineWidget2D(const Point2D& p, const Point2D& q) { Set(p, q); };


	LineWidget2D(double x1, double y1, double x2, double y2) { Set(x1, y1, x2, y2); };


	virtual ~LineWidget2D() { };

}; // LineWidget2D


// LineToWidget2D draws a line from current location to a new absolute position

class EXPORT LineToWidget2D : public IndirectObject {

private:

	// represent a target point P

	Point2D P;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	LineToWidget2D& Set(const Point2D& p) {
		P = p;

		return *this;
	};


	LineToWidget2D& Set(double x, double y) {
		P.Set(x, y);

		return *this;
	};


	void Get(Point2D& p) const {
		p = P;
	};


	void Get(double& x, double& y) const {
		P.Get(x, y);
	};


	LineToWidget2D() { Set(0, 0); };


	LineToWidget2D(const Point2D& p) { Set(p); };


	LineToWidget2D(double x, double y) { Set(x, y); };


	virtual ~LineToWidget2D() { };

}; // LineToWidget2D


// MoveToWidget2D changes current location to a new absolute position

class EXPORT MoveToWidget2D : public IndirectObject {

private:

	// represent a target point P

	Point2D P;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	MoveToWidget2D& Set(const Point2D& p) {
		P = p;

		return *this;
	};


	MoveToWidget2D& Set(double x, double y) {
		P.Set(x, y);

		return *this;
	};


	void Get(Point2D& p) const {
		p = P;
	};


	void Get(double& x, double& y) const {
		P.Get(x, y);
	};


	MoveToWidget2D() { Set(0, 0); };


	MoveToWidget2D(const Point2D& p) { Set(p); };


	MoveToWidget2D(double x, double y) { Set(x, y); };


	virtual ~MoveToWidget2D() { };

}; // MoveToWidget2D


// DeltaLineWidget2D draws a line from current location using displacement Delta

class EXPORT DeltaLineWidget2D : public IndirectObject {

private:

	// represent a displacement Delta

	Point2D Delta;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	DeltaLineWidget2D& Set(const Point2D& delta) {
		Delta = delta;

		return *this;
	};


	DeltaLineWidget2D& Set(double dx, double dy) {
		Delta.Set(dx, dy);

		return *this;
	};


	void Get(Point2D& delta) const {
		delta = Delta;
	};


	void Get(double& dx, double& dy) const {
		Delta.Get(dx, dy);
	};


	DeltaLineWidget2D() { Set(0, 0); };


	DeltaLineWidget2D(const Point2D& delta) { Set(delta); };


	DeltaLineWidget2D(double dx, double dy) { Set(dx, dy); };


	virtual ~DeltaLineWidget2D() { };

}; // DeltaLineWidget2D


// DeltaMoveWidget2D changes current location using displacement Delta

class EXPORT DeltaMoveWidget2D : public IndirectObject {

private:

	// represent a displacement Delta

	Point2D Delta;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	DeltaMoveWidget2D& Set(const Point2D& delta) {
		Delta = delta;

		return *this;
	};


	DeltaMoveWidget2D& Set(double dx, double dy) {
		Delta.Set(dx, dy);

		return *this;
	};


	void Get(Point2D& delta) const {
		delta = Delta;
	};


	void Get(double& dx, double& dy) const {
		Delta.Get(dx, dy);
	};


	DeltaMoveWidget2D() { Set(0, 0); };


	DeltaMoveWidget2D(const Point2D& delta) { Set(delta); };


	DeltaMoveWidget2D(double dx, double dy) { Set(dx, dy); };


	virtual ~DeltaMoveWidget2D() { };

}; // DeltaMoveWidget2D


///////////////////////////////////////////////////////////////////////////////

class EXPORT PenSizeWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	
	// changes:	PenSize [in GraphicsState]

private:

	SizeData PenSize;
	
	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new PenSizeWidget(*this);
	};


	PenSizeWidget& Set(short x, short y) {
		PenSize.Set(x, y);

		return *this;
	};


	PenSizeWidget& Set(const SizeData& TheSize) {
		// do not change minimum and default

		short x, y;

		TheSize.Get(x, y);
		PenSize.Set(x, y);

		return *this;
	};


	void Get(short& x, short& y) const {
		PenSize.Get(x, y);
	};


	void Get(SizeData& TheSize) const {
		TheSize = PenSize;
	};


	PenSizeWidget() {
		PenSize.SetMinAndDef(1, 1);
		PenSize.Set(1, 1);
	};


	PenSizeWidget(short x, short y) {
		PenSize.SetMinAndDef(1, 1);
		PenSize.Set(x, y);
	};


	PenSizeWidget(const SizeData& TheSize) {
		PenSize.SetMinAndDef(1, 1);
		Set(TheSize);
	};


	virtual ~PenSizeWidget() { };

}; // PenSizeWidget


class EXPORT PenModeWidget : public GraphicsObject {

	// GraphicsState interactions
	// uses:	
	// changes:	PenMode [in GraphicsState]

private:

	short PenMode;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new PenModeWidget(*this);
	};


	PenModeWidget() : PenMode(PM_Normal) { };


	virtual ~PenModeWidget() { };


	PenModeWidget& SetNormal() { PenMode = PM_Normal; return *this; };


	PenModeWidget& SetWhite()  { PenMode = PM_White;  return *this; };


	PenModeWidget& SetBlack()  { PenMode = PM_Black;  return *this; };


	PenModeWidget& SetInvert() { PenMode = PM_Invert; return *this; };


	PenModeWidget& Set(short penmode) {
		switch (penmode) {
			case PM_Normal:
			case PM_White:
			case PM_Black:
			case PM_Invert:
				PenMode = penmode;
				break;

			default:
				break;
		}

		return *this;
	};


	short Get() { return PenMode; };

}; // PenModeWidget


class EXPORT PenColorWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	
	// changes:	PenColor [in GraphicsState]

private:

	RGBdata color;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new PenColorWidget(*this);
	};


	PenColorWidget& Set(byte r, byte g, byte b) {
		color.Set(r, g, b);

		return *this;
	};


	PenColorWidget& Set(const RGBdata& thecolor) {
		color.Set(thecolor);

		return *this;
	};


	void Get(byte& r, byte& g, byte& b) const {
		color.Get(r, g, b);
	};


	void Get(short& r, short& g, short& b) const {
		color.Get(r, g, b);
	};


	void Get(long& r, long& g, long& b) const {
		color.Get(r, g, b);
	};


	void Get(RGBdata& thecolor) {
		color.Get(thecolor);
	};


	PenColorWidget() : color() { };


	PenColorWidget(byte r, byte g, byte b) { Set(r, g, b); };


	PenColorWidget(const RGBdata& thecolor) { Set(thecolor); };


	virtual ~PenColorWidget() { };

}; // PenColorWidget


class EXPORT FillColorWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	
	// changes:	FillColor [in GraphicsState]

private:

	RGBdata color;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new FillColorWidget(*this);
	};


	FillColorWidget& Set(byte r, byte g, byte b) {
		color.Set(r, g, b);

		return *this;
	};


	FillColorWidget& Set(const RGBdata& thecolor) {
		color.Set(thecolor);

		return *this;
	};


	void Get(byte& r, byte& g, byte& b) const {
		color.Get(r, g, b);
	};


	void Get(short& r, short& g, short& b) const {
		color.Get(r, g, b);
	};


	void Get(long& r, long& g, long& b) const {
		color.Get(r, g, b);
	};


	void Get(RGBdata& thecolor) {
		color.Get(thecolor);
	};


	FillColorWidget() : color() { };


	FillColorWidget(byte r, byte g, byte b) { Set(r, g, b); };


	FillColorWidget(const RGBdata& thecolor) { Set(thecolor); };


	virtual ~FillColorWidget() { };

}; // FillColorWidget


///////////////////////////////////////////////////////////////////////////////

// TextWidget draws text
//
// TextWidget must set its text string
//
// TextWidget uses the current graphics location to set the text position
// The current position is set by the Move or Line widgets
// TextWidget does not change the current position
//
// TextAlignWidget sets the current default for how the location is used to align text
//
// TextColorWidget sets the current default text foreground color
//
// See also the "Background" widgets for how gaps are filled


class EXPORT TextWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	Location, TextAlign, TextColor, PenMode
	//			BackgroundMode, BackgroundColor
	// changes:	

private:

	string text;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new TextWidget(*this);
	};


	TextWidget& Set(const string& s) { text = s; return *this; };


	TextWidget& Set(const char* t)   { text = t; return *this; };


	void Get(string& s) const { s = text; };


	TextWidget() { };


	TextWidget(const string& s) { text = s; };


	TextWidget(const char* t) { text = t; };


	virtual ~TextWidget() { };

}; // TextWidget


class EXPORT TextAlignWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	
	// changes:	TextAlign [in GraphicsState]

private:

	int TextAlign;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new TextAlignWidget(*this);
	};


	// alignment settings use the constants defined in GraphicsState.h
	// define an alignment code in one of three ways:
	//
	//    aligncode = VAlign...
	//
	//    aligncode = HAlign...
	//
	//    aligncode = VAlign...  |  HAlign...

	TextAlignWidget& Set(int AlignCode);


	void Get(int& AlignCode) const { AlignCode = TextAlign; };


	// default constructor selects valign = top and halign = left
	// this happens to be the WIN32 default

	TextAlignWidget() {
		TextAlign = VAlign_Top | HAlign_Left;
	};


	// explicit constructor selects above default first to enable
	// error checking and then call Set to do the work

	TextAlignWidget(int AlignCode) {
		// initialize to standard state
		TextAlign = VAlign_Top | HAlign_Left;

		// now set using aligncode
		Set(AlignCode);
	};


	virtual ~TextAlignWidget() { };

}; // TextAlignWidget


class EXPORT TextColorWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	
	// changes:	TextColor [in GraphicsState]

private:

	RGBdata color;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new TextColorWidget(*this);
	};


	TextColorWidget& Set(byte r, byte g, byte b) {
		color.Set(r, g, b);

		return *this;
	};


	TextColorWidget& Set(const RGBdata& thecolor) {
		color.Set(thecolor);

		return *this;
	};


	void Get(byte& r, byte& g, byte& b) const {
		color.Get(r, g, b);
	};


	void Get(short& r, short& g, short& b) const {
		color.Get(r, g, b);
	};


	void Get(long& r, long& g, long& b) const {
		color.Get(r, g, b);
	};


	void Get(RGBdata& thecolor) {
		color.Get(thecolor);
	};


	TextColorWidget() : color() { };


	TextColorWidget(byte r, byte g, byte b) { Set(r, g, b); };


	TextColorWidget(const RGBdata& thecolor) { Set(thecolor); };


	virtual ~TextColorWidget() { };

}; // TextColorWidget


///////////////////////////////////////////////////////////////////////////////

// As text and certain other objects are drawn there are gaps that may be filled
// or may be left alone.
//
// In Opaque mode, the gaps are filled with the default background color
//
// In Transparent mode, the gaps are left as is and what is behind shows
//
// Transparent is the default
//
// See GraphicsState.h for constants Transparent and Opaque


class EXPORT BackgroundModeWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	
	// changes:	BackgroundMode [in GraphicsState]

private:

	int BackgroundMode;
	
	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new BackgroundModeWidget(*this);
	};

	
	BackgroundModeWidget& SetTransparent() {
		BackgroundMode = BM_Transparent;
		return *this;
	}


	BackgroundModeWidget& SetOpaque() {
		BackgroundMode = BM_Opaque;
		return *this;
	}


	BackgroundModeWidget& Set(int mode) {
		BackgroundMode = mode & 1;		// mask unwanted bits
		return *this;
	};


	void Get(int& mode) const {
		mode = BackgroundMode;
	};


	BackgroundModeWidget() { BackgroundMode = BM_Transparent; };


	BackgroundModeWidget(int mode) { Set(mode); };


	virtual ~BackgroundModeWidget() { };

}; // BackgroundModeWidget


// BackgroundColorWidget sets default color if current background mode is opaque

class EXPORT BackgroundColorWidget : public GraphicsObject {
	
	// GraphicsState interactions
	// uses:	
	// changes:	BackgroundColor [in GraphicsState]

private:

	RGBdata color;

	virtual void DrawDetails(GraphicsWindow& G) const;

public:

	virtual GraphicsObject* Clone() const {
		return new BackgroundColorWidget(*this);
	};


	BackgroundColorWidget& Set(byte r, byte g, byte b) {
		color.Set(r, g, b);

		return *this;
	};


	BackgroundColorWidget& Set(const RGBdata& thecolor) {
		color.Set(thecolor);

		return *this;
	};


	void Get(byte& r, byte& g, byte& b) const {
		color.Get(r, g, b);
	};


	void Get(short& r, short& g, short& b) const {
		color.Get(r, g, b);
	};


	void Get(long& r, long& g, long& b) const {
		color.Get(r, g, b);
	};


	void Get(RGBdata& thecolor) {
		color.Get(thecolor);
	};


	BackgroundColorWidget() : color() { };


	BackgroundColorWidget(byte r, byte g, byte b) { Set(r, g, b); };


	BackgroundColorWidget(const RGBdata& thecolor) { Set(thecolor); };


	virtual ~BackgroundColorWidget() { };

}; // BackgroundColorWidget


#endif // GRAPHICSWIDGET_H_

