#ifndef rect_h
#define rect_h

#undef Rect
#define Rect nrn_Rect

class Requisition;
class Canvas;
class Allocation;
class Extension;
class Hit;
class Brush;
class Color;

class Appear: public Glyph {
  protected:
    Appear(const Color* color = NULL, const Brush* brush = NULL);

  public:
    virtual ~Appear();
    const Color* color() const {
        return color_;
    }
    void color(const Color*);
    const Brush* brush() const {
        return brush_;
    }
    void brush(const Brush*);
    static const Color* default_color();
    static const Brush* default_brush();

  private:
    const Color* color_;
    const Brush* brush_;
    static const Color* dc_;
    static const Brush* db_;
};

#if defined(__MWERKS__)
#undef Rect
#define Rect ivoc_Rect
#endif

class Rect: public Appear {
  public:
    Rect(Coord left,
         Coord bottom,
         Coord width,
         Coord height,
         const Color* c = NULL,
         const Brush* b = NULL);
    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);
    virtual void draw(Canvas*, const Allocation&) const;
    virtual void pick(Canvas*, const Allocation&, int depth, Hit&);

    Coord left() const, right() const, top() const, bottom() const;
    Coord width() const, height() const;
    void left(Coord), bottom(Coord);
    void width(Coord), height(Coord);

  private:
    Coord l_, b_, w_, h_;
};

#if defined(__MWERKS__)
#undef Line
#define Line ivoc_Line
#endif

class Line: public Appear {
  public:
    Line(Coord dx, Coord dy, const Color* color = NULL, const Brush* brush = NULL);
    Line(Coord dx,
         Coord dy,
         float x_align,
         float y_align,
         const Color* color = NULL,
         const Brush* brush = NULL);
    virtual ~Line();

    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);
    virtual void draw(Canvas*, const Allocation&) const;
    virtual void pick(Canvas*, const Allocation&, int depth, Hit&);

  private:
    Coord dx_, dy_;
    float x_, y_;
};

class Circle: public Appear {
  public:
    Circle(float radius, bool filled = false, const Color* color = NULL, const Brush* brush = NULL);
    virtual ~Circle();

    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);
    virtual void draw(Canvas*, const Allocation&) const;

  private:
    float radius_;
    bool filled_;
};

class Triangle: public Appear {
  public:
    Triangle(float side, bool filled = false, const Color* color = NULL, const Brush* brush = NULL);
    virtual ~Triangle();

    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);
    virtual void draw(Canvas*, const Allocation&) const;

  private:
    float side_;
    bool filled_;
};

#if defined(__MWERKS__)
#undef Rectangle
#define Rectangle ivoc_Rectangle
#endif

class Rectangle: public Appear {
  public:
    Rectangle(float height,
              float width,
              bool filled = false,
              const Color* color = NULL,
              const Brush* brush = NULL);
    virtual ~Rectangle();

    virtual void request(Requisition&) const;
    virtual void allocate(Canvas*, const Allocation&, Extension&);
    virtual void draw(Canvas*, const Allocation&) const;

  private:
    float height_;
    float width_;
    bool filled_;
};

inline Coord Rect::left() const {
    return l_;
}
inline Coord Rect::right() const {
    return l_ + w_;
}
inline Coord Rect::bottom() const {
    return b_;
}
inline Coord Rect::top() const {
    return b_ + h_;
}
inline Coord Rect::width() const {
    return w_;
}
inline Coord Rect::height() const {
    return h_;
}

inline void Rect::left(Coord x) {
    l_ = x;
}
inline void Rect::bottom(Coord x) {
    b_ = x;
}
inline void Rect::width(Coord x) {
    w_ = (x > 0) ? x : 1.;
}
inline void Rect::height(Coord x) {
    h_ = (x > 0) ? x : 1.;
}

#endif
