//	File:  shape1.h
//	Author:  M. Sebern
//	Date:  15-Jun-1995
//	Purpose:
//  	Declarations for "shape" class hierarchy.
//	Revision history:
//

#ifndef SHAPE1_H
#define SHAPE1_H

class Point
{
public:
	Point(): x(0.0), y(0.0) {}
	Point(double xval, double yval): x(xval), y(yval) {}
	Point(const Point& pt): x(pt.x), y(pt.y) { }
	double X() const { return x; }
	double Y() const { return y; }
	void X(double xval) { x = xval; }
	void Y(double yval) { y = yval; }
	Point& operator=(const Point& pt) { x = pt.x; y = pt.y; return *this; }
	friend ostream& operator<<(ostream& os, const Point& pt);
private:
	double	x;
	double	y;
};

class Shape
{
public:
	virtual void Draw() const = 0;
	virtual Shape* MakeCopy() const = 0;
	virtual ~Shape();
	int Num() const { return shape_num; }
	// Set up ostream for logging; defaults to cout.
	static ostream& Out() { return *outp; }
	static void Out(ostream& os) { outp = &os; }
protected:
	// For use by derived classes only:
	Shape();
	Shape& operator=(const Shape&);
private:
	int					shape_num;
	static int			shape_count;
	static ostream* 	outp;

	// Copy of Shapes not permitted.
	Shape(const Shape& s);
};

class Line: public Shape
{
public:
	Line();
	Line(const Point& p1, const Point& p2, double wid = 0.0);
	Line(const Line& ln);
	Line& operator=(const Line&);
	void P1(const Point& p1) { pt1 = p1; }
	void P2(const Point& p2) { pt2 = p2; }
	const Point P1() const { return pt1; }
	const Point P2() const { return pt2; }
	void Width(double w) { width = w; }
	double Width() const { return width; }
	virtual void Draw() const;
	virtual Shape* MakeCopy() const;
	~Line();
private:
	Point		pt1;
	Point		pt2;
	double	width;
};

class FancyLine: public Line
{
public:
	enum LineType { SOLID, DASHED, DOTTED };
	FancyLine();
	FancyLine(const Point& p1, const Point& p2,
				 LineType lt, double wid = 0.0);
	FancyLine(const FancyLine& ln);
	FancyLine& operator=(const FancyLine&);
	LineType Type() const { return line_type; }
	void Type(LineType lt) { line_type = lt; }
	virtual void Draw() const;
	virtual Shape* MakeCopy() const;
	~FancyLine();
private:
	LineType	line_type;
	static const char* line_type_names[];
};

class Circle: public Shape
{
public:
	Circle(const Point& c = Point(0,0),
			 double r = 0.0);
	Circle(const Circle& c);
	Circle& operator=(const Circle&);
	void Center(const Point& c) { center = c; }
	void Radius(double r) { radius = r; }
	Point Center() const { return center; }
	double Radius() const { return radius; }
	virtual void Draw() const;
	virtual Shape* MakeCopy() const;
	~Circle();
private:
	Point		center;
	double	radius;
};

class Rectangle: public Shape
{
public:
	Rectangle();
	Rectangle(const Point& p1, const Point& p2);
	Rectangle(const Rectangle& r);
	Rectangle& operator=(const Rectangle&);
	void P1(const Point& p1) { pt1 = p1; }
	void P2(const Point& p2) { pt2 = p2; }
	Point P1() const { return pt1; }
	Point P2() const { return pt2; }
	virtual void Draw() const;
	virtual Shape* MakeCopy() const;
	~Rectangle();
private:
	Point		pt1;
	Point		pt2;
};

#endif /* SHAPE1_H */

