// tools.cpp -- TGraphTool and derived class implementations

#include "tools.h"

// ===========================================================
// TGraphTool
// ===========================================================

// Default constructor
TGraphTool::TGraphTool()
  : startPt(0, 0),
    endPt(0, 0)
{
  pen = new TGraphPen(TColor::Black);
  brush = new TGraphBrush(TColor::White);
}

// Alternate constructor
TGraphTool::TGraphTool(TPoint p1, TPoint p2,
  TColor penColor, TColor brushColor)
  : startPt(p1),
    endPt(p2)
{
  pen = new TGraphPen(penColor);
  brush = new TGraphBrush(brushColor);
}

IMPLEMENT_ABSTRACT_STREAMABLE(TGraphTool);

// Destructor
TGraphTool::~TGraphTool()
{
  delete pen;
  delete brush;
}

// Offset starting and ending points by passed amounts to
// account for scoller thumb position
void
TGraphTool::OffsetPoints(long xofs, long yofs)
{
  startPt.x += (int)xofs;
  startPt.y += (int)yofs;
  endPt.x += (int)xofs;
  endPt.y += (int)yofs;
}

// Read object from stream
void*
TGraphTool::Streamer::Read(ipstream& is, uint32) const
{
  COLORREF penColor, brushColor;

  is >> GetObject()->startPt.x;
  is >> GetObject()->startPt.y;
  is >> GetObject()->endPt.x;
  is >> GetObject()->endPt.y;
  is >> penColor;
  is >> brushColor;
  GetObject()->pen = new TGraphPen(TColor(penColor));
  GetObject()->brush = new TGraphBrush(TColor(brushColor));
  return GetObject();
}

// Write object to stream
void
TGraphTool::Streamer::Write(opstream& os) const
{
  os << GetObject()->startPt.x;
  os << GetObject()->startPt.y;
  os << GetObject()->endPt.x;
  os << GetObject()->endPt.y;
  os << GetObject()->pen->GetColor();
  os << GetObject()->brush->GetColor();
}

// Insert tool's attributes into dc.
void
TGraphTool::SelectAttributes(TDC& dc)
{
  dc.SelectObject(*pen);
  dc.SelectObject(*brush);
}

// Restore old DC and delete the current Pen and Brush
void
TGraphTool::DeselectAttributes(TDC& dc)
{
  dc.RestorePen();
  dc.RestoreBrush();
}

// Change tool's pen color
void
TGraphTool::SetPenColor(TColor color)
{
  delete pen;
  pen = new TGraphPen(color);
}

// Change tool's brush color
void
TGraphTool::SetBrushColor(TColor color)
{
  delete brush;
  brush = new TGraphBrush(color);
}

// Implement == operator for TGraphTool objects
// Required by array template that holds image
int
TGraphTool::operator== (const TGraphTool& tool)
{
  return &tool == this;
}

// ===========================================================
// TLine
// ===========================================================

// Return pointer to TLine object clone
TGraphTool *
TLine::Clone()
{
  return new TLine(startPt, endPt,
    GetPen()->GetColor(), GetBrush()->GetColor());
}

IMPLEMENT_STREAMABLE1(TLine, TGraphTool);

// Read object from stream
void*
TLine::Streamer::Read(ipstream& is, uint32) const
{
  ReadBaseObject((TGraphTool *)GetObject(), is);
  // Nothing else to read for a TLine object,
  // but if TLine declared its own data members,
  // you would read them here.
  return GetObject();
}

// Write object to stream
void
TLine::Streamer::Write(opstream& os) const
{
  WriteBaseObject((TGraphTool *)GetObject(), os);
  // Nothing else to write for a TLine object
  // but if TLine declared its own data members,
  // you would write them here.
}

// Draw a TLine object
void TLine::Draw(TDC& dc)
{
  SelectAttributes(dc);
  dc.MoveTo(startPt);
  dc.LineTo(endPt);
  DeselectAttributes(dc);
}

// ===========================================================
// TEllipse
// ===========================================================

// Return pointer to TEllipse object clone
TGraphTool *
TEllipse::Clone()
{
  return new TEllipse(startPt, endPt,
    GetPen()->GetColor(), GetBrush()->GetColor());
}

IMPLEMENT_STREAMABLE1(TEllipse, TGraphTool);

// Read object from stream
void*
TEllipse::Streamer::Read(ipstream& is, uint32) const
{
  ReadBaseObject((TGraphTool *)GetObject(), is);
  return GetObject();
}

// Write object to stream
void
TEllipse::Streamer::Write(opstream& os) const
{
  WriteBaseObject((TGraphTool *)GetObject(), os);
}

// Draw a TEllipse object
void
TEllipse::Draw(TDC& dc)
{
  SelectAttributes(dc);
  dc.Ellipse(startPt, endPt);
  DeselectAttributes(dc);
}

// ===========================================================
// TRectangle
// ===========================================================

// Return pointer to TRectangle object clone

TGraphTool *
TRectangle::Clone()
{
  return new TRectangle(startPt, endPt,
    GetPen()->GetColor(), GetBrush()->GetColor());
}

IMPLEMENT_STREAMABLE1(TRectangle, TGraphTool);

// Read object from stream
void*
TRectangle::Streamer::Read(ipstream& is, uint32) const
{
  ReadBaseObject((TGraphTool *)GetObject(), is);
  return GetObject();
}

// Write object to stream
void
TRectangle::Streamer::Write(opstream& os) const
{
  WriteBaseObject((TGraphTool *)GetObject(), os);
}

// Draw a TRectangle object
void
TRectangle::Draw(TDC& dc)
{
  SelectAttributes(dc);
  dc.Rectangle(startPt, endPt);
  DeselectAttributes(dc);
}

