#ifndef _CANVAS_H #define _CANVAS_H #include #include using namespace std; #include "tvector.h" #include "iterator.h" #include "canvascolor.h" #include "key.h" #include "point.h" class image; // forward decl class Shape; // forward decl // the class Box is used for the bounding-box of every shape // a Box is rectangular, specified by upper-left and lower-right // coordinates. A Box knows if a point is inside it, if it // intersects with another box, and overloads += for the union of two // boxes which is the smallest box containing both class Box { public: Box(int xul, int yul, int xlr, int ylr); Box(const Point& ul, const Point& lr); Box(); const Box& operator += (const Box& rhs); // union of two boxes Point getUL() const; // return upper-left point Point getLR() const; // return lower-right point double width() const; // return width double height() const; // return height string tostring() const; // stringized form bool contains(const Point& p) const; // true iff p in me bool intersects(const Box& b) const; // true iff b intersects me private: Point myLeft, myRight; }; Box operator + (const Box& lhs, const Box& rhs); // union ostream& operator << (ostream& os, const Box& b); // output class window; // the handle class that does all the work // The CanvasAble is in place for future development, it's // not used in the current implementatation althouth Keyable and // Mouseable inherit from it class CanvasAble { public: virtual ~CanvasAble() = 0; }; // unbuffered BaseCanvas class that does most of the work for drawing // and for the AnimatedCanvas class // // construct with width (x-direction) and height (y-direction) // and placement relative to the screen -- upper left corner is (0,0) // // functions are mostly self-explanatory, currently the coordinate system // has origin in upper-left, x increasing to the right, y increasing down // In the raw Canvas class, the color is set on the canvas, all subsequent // drawing is done in that color. Similarly, figures are drawn filled // or framed, as specified by calling SetFilled() or SetFramed() // for the entire canvas, default is Filled. // // Figures can be specified using int values for (x,y) or using Point objects // Point objects are preferred, points use double values for (x,y) which are // rounded off when actually drawing. At some future point the methods // that use ints may disappear, use Points class BaseCanvas { public: BaseCanvas(int w, int h, int x, int y); virtual ~BaseCanvas(); int height() ; int width() ; // drawing functions void Clear(); // erase canvas void SetColor(const color& c); // set color for all drawing void SetFrame(); // figures framed, not filled void SetFilled(); // figures filled, not framed void DrawPixel(int x, int y); // draw pixel at x,y void DrawPixel(const Point& p); // draw pixel at p void DrawLine (int x1, int y1, // draw line from (x1,y1) to (x2,y2) int x2, int y2); void DrawLine (const Point& p1, // draw line from p1 to p2 const Point& p2); void DrawRectangle (int x1, int y1, int x2, int y2); void DrawRectangle (const Point& p1, const Point& p2); void DrawCircle (int x, int y, int radius); void DrawCircle (const Point& center, int radius); void DrawEllipse (int x1, int y1, int x2, int y2); void DrawEllipse (const Point& p1, const Point& p2); void DrawTriangle (const Point& p1, const Point& p2, const Point& p3); void DrawPolygon (const void DrawString (const string& s, tvector& a, int numPoints); int x, int y, int fontsize=14); void DrawString (const string& s, const Point& p,int fontsize=14); void DrawPieWedge (const Point& p, int radius, double startRad, double endRad); void SetTitle(const string& s); void GetStringSize(int&w, int& h, const string& s); CanvasColor GetPixel(const Point& p) const; // use ImageShape to avoid the image class void DrawImage (image& im, int x, int y, double scale=1.0); void DrawImage (image& im, const Point& p, double scale=1.0); // end of drawing functions void Print(); void Process(); double ycoord(double d); // hooks for changing coord system Point ycoord(const Point& p); protected: enum Coord{top_origin, bottom_origin}; window * myWindow; int myCount; int myHeight; bool myFilled; Coord myCoords; CanvasColor myColor; static int ourCount; static const int BBARHEIGHT; // hook for making buttons void MakeBBar(); // not implemented }; // the AnimatedCanvas class is-a BaseCanvas, but it supports // double-buffered animation over a collection of Shapes // (see the Shape class hierarchy) // the basic mode of operation with an AnimatedCanvas is // // o construct Canvas // o add Shapes // o animate using runXXX(..) method // // It's best to add pointers to shapes, rather than shapes. Adding a Shape // directly will cause the shape to be cloned and then added, adding // a pointer doesn't clone the shape // // Shapes can be removed, the Shape()->id() method is used for identity // so a cloned shape can't be removed since it will have a different id // // the method run(n) or run(n,delay) runs the animation for n steps, where // a step is one cycle of asking all shapes to draw themselves. Specifying // a delay means animation pauses between cycles // // alternatively, runUntilEscape(delay) runs until the ESCAPE key is // pressed when the canvas has the focus. The delay is optional // // the getClick() method returns the point of the last mouse-click, if // coordinates are negative there was no last click // // the makeIterator function returns an Iterator for accessing all // shapes in an AnimatedCanvas class Button; class AnimatedCanvas : public BaseCanvas { public: AnimatedCanvas(int w, int h, int x, int y, bool isBuffered=true); ~AnimatedCanvas(); void repaint(); void addShape(Shape * s); // add shape, no cloning void addShape(Shape& s); // add shape after cloning void addShape(Button& b); // hooks for buttons, beta void addShape(Button * b); void removeShape(Shape * s); // remove shape using shape()->id() void removeShape(Shape& s); // cannot remove cloned shape void setBackground(image& im); // set background image void run(int steps,int pause=0); // run animation for steps with pause void runUntilEscape(int pause=0); // run until ESC pressed Point getClick(); IteratorRef * makeIterator(); protected: void poll(); tvector myShapes; tvector myDeadShapes; tvector myLiveShapes; int myShapeCount; int myButtonCount; image * myBackground; Point myClickPoint; Key myKey; bool myIsBuffered; bool myIsRunning; }; class Canvas : public AnimatedCanvas { public: Canvas(int w, int h, int x, int y) : AnimatedCanvas(w,h,x,y,false) { } }; #include "shapes.h" #endif