//	File:		shape1.cpp
//	Author:	M. Sebern
//	Date:		15-Jun-1995
//	Purpose:
//		Implementation of "shape" class hierarchy.

#include <iostream.h>
#include <assert.h>
#include "shape1.h"

// Point
ostream& operator<<(ostream& os, const Point& pt)
{
	os << "(" << pt.x << "," << pt.y << ")";
	return os;
}

// Shape
int Shape::shape_count = 0;
ostream* Shape::outp = &cout;

Shape::~Shape()
{
	Out() << "Destroying Shape " << shape_num << endl;
}

Shape::Shape()
{
	shape_num = ++shape_count;
	Out() << "Constructing Shape " << shape_num << " ... ";
}

Shape::Shape(const Shape& s)
{
	// Private: should not be called
	shape_num = ++shape_count;
	Out() << "Copy Shape " << shape_num << " from " << s.shape_num << " ... ";
}

Shape& Shape::operator=(const Shape& s)
{
	Out() << "Assign Shape " << Num() << " from " << s.Num();
	if (this == &s) Out() << " (self)";
	Out() << endl;
	return *this;
}

// Line
Line::Line()
{
	Out() << "Construct default Line from " << pt1 << " to " << pt2 << endl;
}

Line::Line(const Point& p1, const Point& p2, double wid)
	: pt1 (p1), pt2(p2), width (wid)
{
	Out() << "Construct Line from " << P1() << " to " << P2() << endl;
}

Line::Line(const Line& ln)
	: pt1 (ln.pt1), pt2(ln.pt2)
{
	Out() << "Copy Line {" << Num() << "} from {" << ln.Num() << "}" << endl;
}

Line& Line::operator=(const Line& ln)
{
	Out() << "Assign Line " << Num() << " from " << ln.Num();
	if (this == &ln)
	{
		Out() << " (self)" << endl;
	}
	else
	{
		Out() << " ... ";
		Shape::operator=(ln);
		pt1 = ln.pt1;
		P2(ln.P2());	// Alternate form.
	}
	return *this;
}

void Line::Draw() const
{
	Out() << "Draw Line {" << Num() << "} from " << P1() << " to " << P2() << endl;
}

Shape* Line::MakeCopy() const
{
	Shape*	pshape = new Line(*this);
	Out() << "... MakeCopy Line" << endl;
	return pshape;
}

Line::~Line()
{
	Out() << "Destroy Line ... ";
}


// FancyLine
const char* FancyLine::line_type_names[] =
	{ "Solid", "Dashed", "Dotted" };

FancyLine::FancyLine() : line_type(SOLID)
{
	Out() << "Construct default FancyLine from " << P1() << " to " << P2() << endl;
}

FancyLine::FancyLine(const Point& p1,
							const Point& p2,
							LineType lt,
							double wid)
	: Line(p1,p2,wid), line_type(lt)
{
	Out() << " ... Construct FancyLine from " << P1() << " to " << P2();
	Out() << ", type = " << line_type_names[Type()] << endl;
}

FancyLine::FancyLine(const FancyLine& ln)
	: Line(ln), line_type(ln.Type())
{
	Out() << "... Copy FancyLine {" << Num() << "} from {" << ln.Num() << "}" << endl;
}

FancyLine& FancyLine::operator=(const FancyLine& ln)
{
	Out() << "Assign FancyLine " << Num() << " from " << ln.Num();
	if (this == &ln)
	{
		Out() << " (self)" << endl;
	}
	else
	{
		Out() << " ... ";
		Line::operator=(ln);
		Type(ln.Type());
	}
	return *this;
}

void FancyLine::Draw() const
{
	Out() << "Draw FancyLine {" << Num() << "} from " << P1() << " to " << P2();
	Out() << ", type = " << line_type_names[Type()] << endl;
}

Shape* FancyLine::MakeCopy() const
{
	Shape*	pshape = new FancyLine(*this);
	Out() << "... MakeCopy FancyLine" << endl;
	return pshape;
}

FancyLine::~FancyLine()
{
	Out() << "Destroy FancyLine ... ";
}

// Circle
Circle::Circle(const Point& c, double r)
	: center(c), radius(r)
{
	Out() << "Construct Circle: center = " << Center() << ", radius = " << Radius() << endl;
}

Circle::Circle(const Circle& c)
	: center(c.Center()), radius(c.Radius())
{
	Out() << "Copy Circle {" << Num() << "} from {" << c.Num() << "}" << endl;
}

void Circle::Draw() const
{
	Out() << "Draw Circle {" << Num() << "} at " << Center() << ", radius " << Radius() << endl;
}

Shape* Circle::MakeCopy() const
{
	Shape*	pshape = new Circle(*this);
	Out() << "... MakeCopy Circle" << endl;
	return pshape;
}

Circle::~Circle()
{
	Out() << "Destroy Circle ... ";
}

// Rectangle

Rectangle::Rectangle()
{
	Out() << "Construct default Rectangle from " << P1() << " to " << P2() << endl;
}

Rectangle::Rectangle(const Point& p1, const Point& p2) : pt1(p1), pt2(p2)
{
	Out() << "Construct Rectangle from " << P1() << " to " << P2() << endl;
}

Rectangle::Rectangle(const Rectangle& r) : pt1(r.pt1), pt2(r.pt2)
{
	Out() << "Copy Rectangle {" << Num() << "} from {" << r.Num() << "}" << endl;
}

void Rectangle::Draw() const
{
	Out() << "Draw Rectangle {" << Num() << "} from " << P1() << " to " << P2() << endl;
}

Shape* Rectangle::MakeCopy() const
{
	Shape*	pshape = new Rectangle(*this);
	Out() << "... MakeCopy Rectangle" << endl;
	return pshape;
}

Rectangle::~Rectangle()
{
	Out() << "Destroy Rectangle ... ";
}

