/**************************************************************************** ** COPYRIGHT (C): 1997 Cay S. Horstmann. All Rights Reserved. ** PROJECT: Practical OO Development with C++ and Java ** FILE: shapes18.cpp ** PURPOSE: test MI shapes in chapter 18 ** VERSION 1.0 ** PROGRAMMERS: Cay Horstmann (CSH) ** RELEASE DATE: 3-15-97 (CSH) ** UPDATE HISTORY: ****************************************************************************/ /* Project: GUI Application Add files shapes18.cpp \PracticalOOBook\cpplib\graphics.cpp Additional include directory: \PracticalOOBook\cpplib */ #include "setup.h" #include "graphics.h" #include "math.h" class Point; class Shape { public: Shape(); Shape(Color); virtual void plot(Graphics& g) const; virtual ~Shape() {} private: Color _color; }; /*-------------------------------------------------------------*/ class Point : public Shape { public: Point(int xx =0, int yy =0, Color c = Color::black); virtual void plot(Graphics& gc) const; int x() const; int y() const; #ifdef PRACTICALOO_COMPILER_UNREASONABLY_INSISTS_ON_COMPARISON_OPERATORS_FOR_VECTORS bool operator<(const Point& b) const { return _x < b._x || _x == b._x && _y < b._y; } bool operator==(const Point& b) const { return _x == b._x && _y == b._y; } #endif private: int _x; int _y; }; /*-------------------------------------------------------------*/ class Polygon : public Shape { public: Polygon() {} Polygon(int, Color); Point corner(int) const; void set_corner(int, Point); virtual void plot(Graphics& gc) const; private: #ifndef PRACTICALOO_MUST_USE_ALLOCATOR vector _corners; #else vector > _corners; #endif }; /*-------------------------------------------------------------*/ class Text : public Shape, public string { public: Text(Point, string, Color); void plot(Graphics& gc) const; private: Point _start; }; /*-------------------------------------------------------------*/ class TrafficSign : public Text, public Polygon { public: TrafficSign(Point c, int nvert, string t); void plot(Graphics& gc) const; }; /*-------------------------------------------------------------*/ void paint(Graphics& g) { #ifndef PRACTICALOO_MUST_USE_ALLOCATOR vector a; #else vector > a; #endif a.push_back(new Point(100, 100, Color::blue)); a.push_back(new Text(Point(150, 150), "Hello", Color::green)); TrafficSign* sign = new TrafficSign(Point(200, 200), 8, "Stop"); *sign += "!"; // it is a string :-) a.push_back((Polygon*)sign); // but it isn't a shape :-( for (int j = 0; j < a.size(); j++) a[j]->plot(g); } /*-------------------------------------------------------------*/ Shape::Shape() : _color(Color::blue) {} /*.............................................................*/ Shape::Shape(Color c) : _color(c) {} /*.............................................................*/ void Shape::plot(Graphics& g) const { g.setColor(_color); } /*-------------------------------------------------------------------------*/ Point::Point(int xx, int yy, Color c) : Shape(c), _x(xx), _y(yy) {} /*.............................................................*/ void Point::plot(Graphics& g) const { Shape::plot(g); g.drawOval(_x - 2, _y - 2, 5, 5); } /*.............................................................*/ inline int Point::x() const { return _x; } /*.............................................................*/ inline int Point::y() const { return _y; } /*-------------------------------------------------------------------------*/ Text::Text(Point p, string t, Color c) : string(t), Shape(c), _start(p) {} /*.............................................................*/ void Text::plot(Graphics& g) const { Shape::plot(g); FontMetrics fm = g.getFontMetrics(); int xw = fm.stringWidth(*this); g.drawString(*this, _start.x() - xw / 2, _start.y()); } /*-------------------------------------------------------------------------*/ Polygon::Polygon(int n, Color c) : Shape(c), _corners(n) {} /*.............................................................*/ Point Polygon::corner(int i) const { return _corners[i]; } /*.............................................................*/ void Polygon::set_corner(int i , Point p) { _corners[i] = p; } /*.............................................................*/ void Polygon::plot(Graphics& g) const { Shape::plot(g); for (int i = 0; i < _corners.size(); i++) { int j = (i + 1) % _corners.size(); Point p = _corners[i]; Point q = _corners[j]; g.drawLine(p.x(), p.y(), q.x(), q.y()); } } /*-------------------------------------------------------------------------*/ TrafficSign::TrafficSign(Point p, int nvert, string t) : Text(p, t, Color::red), Polygon(nvert, Color::black) { // nvert calls to set_corner const int RAD = 50; for (int i = 0; i < nvert; i++) { double angle = (1 + 2 * i) * M_PI / nvert; set_corner(i, Point(p.x() + RAD * cos(angle), p.y() + RAD * sin(angle))); } } /*.............................................................*/ void TrafficSign::plot( Graphics& gc ) const /* PURPOSE: plot this shape RECEIVES: gc - graphics context */ { Polygon::plot(gc); Text::plot(gc); }