#ifndef _DrawObject_H_
#define _DrawObject_H_

#include "DrawWidget.h"

//=====================================================================

/** 
    A simple class which requires the use of a DrawWidget to draw itself.
    All graphics items need to be derived from this class.
    
    All positions in these objects are specified in world coordinates as 
    opposed to pixel coordinates.  The draw method takes as an argument
    a pointer to a DrawWidget object.  That allows the world to pixel 
    coordinate functions to be accessed for that particular widget.
 */
class DrawObject {

 protected:

  /// The object's red component (ranges from 0-255)
  uchar red;
  /// The object's green component (ranges from 0-255)
  uchar green;
  /// The object's blue component (ranges from 0-255)
  uchar blue;

  // Is the object filled?
  bool filled;

public:
  /** Default constructor
      @par _red Red color component (range: 0-255)
      @par _green Green color component (range: 0-255)
      @par _blue Blue color component (range: 0-255)
      @par _filled Whether the object is filled or not
   */
  DrawObject(uchar _red, uchar _green, uchar _blue, bool _filled);

  /** The draw method that must be overridden by any derived class
      @par dw Pointer to a DrawWidget object
  */
   virtual void draw(DrawWidget * dw) = 0;
};

//=====================================================================

/**
   Draw a circle.  This can be an ellipse if the width and height are
   not the same.
 */
class DrawObjectCircle : public DrawObject {

 protected:
  /// The center of the circle in x
  float x;
  /// The center of the circle in y
  float y;
  /// The width of the circle
  float w;
  /// The height of the circle
  float h;

 public:
  /**
     Constructor specifying the center, width and height
     @par _x X component of circle's center in world coordinates
     @par _y Y component of circle's center in world coordinates
     @par _w width of circle in world coordinates
     @par _h height of circle in world coordinates
     @par _red Red color component (range: 0-255)
     @par _green Green color component (range: 0-255)
     @par _blue Blue color component (range: 0-255)
     @par _filled Whether the object is filled or not
  */
  DrawObjectCircle(float _x, float _y, float _w, float _h, 
		   uchar _red=0, uchar _green=0, uchar _blue=0,
		   bool _filled=false);

  /**
     Constructor specifying the center and radius
     @par _x X component of circle's center in world coordinates
     @par _y Y component of circle's center in world coordinates
     @par _r radius of circle in world coordinates
     @par _red Red color component (range: 0-255)
     @par _green Green color component (range: 0-255)
     @par _blue Blue color component (range: 0-255)
     @par _filled Whether the object is filled or not
  */

  DrawObjectCircle(float _x, float _y, float _r,
		   uchar _red=0, uchar _green=0, uchar _blue=0,
		   bool _filled=false);

  /// Destructor
  virtual ~DrawObjectCircle() {}

  /** Draw the circle
      @par dw Pointer to a DrawWidget object
  */
  virtual void draw(DrawWidget * dw);
};


//=====================================================================

/**
   Draw a rectangle.
 */
class DrawObjectRectangle : public DrawObject {

 protected:
  /// The center of the rectangle in x
  float x;
  /// The center of the rectangle in y
  float y;
  /// The width of the rectangle
  float w;
  /// The height of the rectangle
  float h;

 public:
  /**
     Constructor specifying the center, width and height
     @par _x X component of rectangle's center in world coordinates
     @par _y Y component of rectangle's center in world coordinates
     @par _w width of rectangle in world coordinates
     @par _h height of rectangle in world coordinates
     @par _red Red color component (range: 0-255)
     @par _green Green color component (range: 0-255)
     @par _blue Blue color component (range: 0-255)
     @par _filled Whether the object is filled or not
  */
  DrawObjectRectangle(float _x, float _y, float _w, float _h, 
		      uchar _red=0, uchar _green=0, uchar _blue=0,
		      bool _filled=false);

  /// Destructor
  virtual ~DrawObjectRectangle() {}

  /** Draw the rectangle
      @par dw Pointer to a DrawWidget object
  */
  
  virtual void draw(DrawWidget * dw);
};

//=====================================================================

/**
   Draw a bitmapped image.  Stores a local copy of the image buffer
*/
class DrawObjectImage : public DrawObjectRectangle {

  /// Pointer to the image buffer
  uchar * rgb_image;
  /// Width of the image
  uint columns;
  /// Height of the image
  uint rows;

 public:
  /**
     Constructor specifying the center, width and height
     @par _x X component of image's center in world coordinates
     @par _y Y component of image's center in world coordinates
     @par _w width of image in world coordinates
     @par _h height of image in world coordinates
     @par _rgb_image Pointer to an RGB character buffer 
     @par _columns Width of rgb_image
     @par _rows Height of rgb_image
   */
  DrawObjectImage(float _x, float _y, float _w, float _h,
		  uchar * _rgb_image, uint _columns, uint _rows);

  /// Destructor
  virtual ~DrawObjectImage();

  /**
     Draw the image
     @par dw Pointer to a DrawWidget object
  */
  virtual void draw(DrawWidget * dw);
};

//=====================================================================

/**
   Draw a line.
*/
class DrawObjectLine : public DrawObject {
  
 protected:
  /// The x component of the first point in world coordinates
  float x1;
  /// The y component of the first point in world coordinates
  float y1;
  /// The x component of the second point in world coordinates
  float x2;
  /// The y component of the second point in world coordinates
  float y2;

  /**
     Numerical value for style.  See the FLTK constants for values.  
     Default is 0
  */
  int style;
  /// Width of line
  int width;

 public:
  /**
     Constructor specifying the center, width and height
     @par _x1 X component of first point
     @par _y1 Y component of first point
     @par _x2 X component of second point
     @par _y2 Y component of second point
     @par _red Red color component (range: 0-255)
     @par _green Green color component (range: 0-255)
     @par _blue Blue color component (range: 0-255)
     @par _style Style of line (default is 0)
     @par _width Width of line (default is 1)
  */
  DrawObjectLine(float _x1, float _y1, float _x2, float _y2, 
		 uchar _red=0, uchar _green=0, uchar _blue=0,
		 int _style=0,int _width=1); 

  /// Destructor
  virtual ~DrawObjectLine() {}
  /**
     Draw the line
     @par dw Pointer to a DrawWidget object
  */
  virtual void draw(DrawWidget * dw);
};

//=====================================================================

/** 
    Draw text.
*/
class DrawObjectText: public DrawObject {

 protected:
  /// The text to print
  char * text;

  /// X component of starting point 
  float x;
  
  /// Y component of starting point
  float y;

  /// Font ID
  int font_id;
  
  /// Font size
  int font_size;

 public:
  /**
     Constructor specifying the lower left corner of the text
     @par _text The text to display
     @par _x X component of starting point in world coordinates
     @par _y Y component of starting point in world coordinates
     @par _red Red color component (range: 0-255)
     @par _green Green color component (range: 0-255)
     @par _blue Blue color component (range: 0-255)
     @par _font_id Numerical ID of the font (FLTK values)
     @par _font_size Font size
   */
  DrawObjectText(const char * _text, float _x, float _y,
		 uchar _red=0, uchar _green=0, uchar _blue=0,
		 int _font_id=0,int _font_size=14);

  /// Destructor
  virtual ~DrawObjectText() {}

  /**
     Draw the line
     @par dw Pointer to a DrawWidget object
  */
  virtual void draw(DrawWidget * dw);
};

#endif
