#ifndef _OBJECTS_H_
#define _OBJECTS_H_


#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <string>

using namespace std;


//forward declaration
class Window;
class Line;
class Text;
class GraphicalObject;


typedef enum lineStyle_t{
  SOLID, 
  DASHED, 
  DOUBLE_DASHED
};

typedef struct ObjectNode
{
  struct ObjectNode *prevnode;
  struct ObjectNode *nextnode;
  GraphicalObject *g;
};

typedef ObjectNode* ObjectNode_p;


class ObjectList
{
  friend class window;
 protected:
  ObjectNode *sentinel ;
  ObjectNode *cursor  ;
  int count;
 public:
  ObjectList();
  ~ObjectList();

  bool ObjectList::isLast();
  bool ObjectList::isFirst();
  void ObjectList::first();
  void ObjectList::last();
  void ObjectList::next();
  void ObjectList::prev();

  GraphicalObject* getObject();
  int addObject(GraphicalObject *g);
  int deleteObject(); 
};
      
// a use of inheritance--all the graphical objects are subclasses
// of GraphicalObject

class GraphicalObject 
{
 protected:
  string title;
  string scolor;
  int left;
  int top;
  int width;     // in the case of line this will be treated as x2
  int height;    // in the case of line this will be treated as y2
 public:
  virtual void setTitle(string s) {title=s;}
  virtual void setLeft(int x) {left = x; } 
  virtual void setTop(int y) {top = y; } // = 0; 
  virtual void setWidth(int w) {width = w;} // 0 ;
  virtual void setHeight(int h) {height = h; } // = 0 ;
  virtual int draw(Window *w) = 0;
  void setColor(string s);
   
  string getColor() { return (string)scolor; }
  string getTitle() { return (string)title; }
  int getLeft() { return (int)left; }
  int getTop() { return (int)top; }
  int getWidth() { return (int)width; }
  int getHeight() { return (int)height ; }


};


/*  Class: Window  */
class Window : public GraphicalObject{
  friend class Line;
  friend class Text;
 protected:
  ObjectList *list; 
  GtkWidget *drawing_area;
  GtkWidget *gtkwindow; 
 public:
  Window();
  Window(string);
  Window(string, int left, int top, int width , int height ); 
  ~Window() {};

  /* over written methods */
  void setLeft(int x); 
  void setTop(int y);
  void setWidth(int w);
  void setHeight(int h);
  void setTitle(string s);
  /* this one needs to be defined here 
     as draw is declared as abstract, 
     Otherwise the compiler complains */
  int draw(Window *w) {}

  /* window specific methods */
  int addObject(GraphicalObject *g);
  void show();
};



/*  Class : LINE */  
class Line : public GraphicalObject {
  friend class Window;
 protected:
  lineStyle_t lineStyle;
 public:
  /* constructors & destructors */
  Line();
  Line(string s);
  Line(string s, string c);
  Line(string s, string c, lineStyle_t style);
  Line(string c, lineStyle_t style);
  ~Line();  

  /*overwritten methods */
  int draw(Window *w);

  /* Line specific methods */
  void setX1 (int x) { setLeft(x);}
  void setY1 (int x) { setTop(x);}
  void setX2 (int x) { setWidth(x);}
  void setY2 (int x) { setHeight(x);}
  void setLineStyle (lineStyle_t style);
  lineStyle_t getLineStyle ();
  int getX1 () { return getLeft();}
  int getY1 () { return getTop();}
  int getX2 () { return getWidth();}
  int getY2 () { return getHeight();}
};


/*    Class : Text     */
class  Text: public GraphicalObject {
  friend class Window;
 public:
  /* constructors & destructors */
  Text();
  Text(string text);
  Text(string text, string color); 
  ~Text() {}  

  /*overwritten functions */
  int getWidth();
  int draw(Window *w);

  /* Text specific functions */
  string getText() { return getTitle(); }
  void setText(string s);
};


/* other functions defined in objects.cc */
void destroy( GtkWidget *widget, gpointer data );
static gboolean configure_event( GtkWidget *widget, GdkEventConfigure *event );
static gint expose_event (GtkWidget *widget, GdkEventExpose *event);

#endif

