// This may look like C code, but it is really -*- C++ -*-
// Objets traceur qui peuvent etre attaches a un PIBaseWidget
//                             R. Ansari  97-98
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
#ifndef PIDRAWER_H
#define PIDRAWER_H

#include "pibwdggen.h"
#include "pigraphuc.h"

#include <list>
#if defined(__KCC__)
#include <list.h>
#endif

enum {
  kStdAxes     = 0x0001,
  kBoxAxes     = 0x0002,
  kTicks       = 0x0004,
  kIntTicks    = 0x0010,
  kExtTicks    = 0x0020,
  kMajTicks    = 0x0040,
  kMinTicks    = 0x0080,
  kLabels      = 0x1000,
  kGridOn      = 0x2000,
  kAxesDflt    = kStdAxes | kTicks | kLabels,       // Axes trace par defaut
  kAxesNone    = 0                                  // Pas de trace d axe  
};


class PIDrawer {
public:
                     PIDrawer();
  virtual           ~PIDrawer();

  virtual void       SetLimits(double xmin, double xmax, double ymin, double ymax,
                               int axrl=kAxeDirSame, int ayud=kAxeDirSame);

  virtual void       DrawAxes(PIGraphicUC* g);
  virtual void       SetAxesFlags(unsigned int flags=kAxesNone);
    
  virtual void       Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax); 
   
  virtual void       Refresh();      // Recalcule les limites et reaffiche
  virtual void       UpdateLimits();   // Calcule et change les limites  

  inline double      XMin() const {return xMin;}
  inline double      XMax() const {return xMax;}
  inline double      YMin() const {return yMin;}
  inline double      YMax() const {return yMax;}

  void                GetAxesConfig(int& xa, int& ya);
  inline unsigned int GetAxesFlags() { return(axesFlags); }
  
  inline PIGraphicUC*    GetGraphicUC() { return(mGrUC); }

  inline int          LimitsFixed() const {return limitsFixed;}
  inline void         FreeLimits() {limitsFixed = 0;}

// Changement des attributs graphiques
  virtual void       SetColAtt(PIColors fg=PI_NotDefColor, 
                               PIColors bg=PI_NotDefColor);
  virtual void       SetLineAtt(PILineAtt lat=PI_NotDefLineAtt);
  virtual void       SetFontAtt(PIFontSize fsz=PI_NotDefFontSize,
                                PIFontAtt fat=PI_NotDefFontAtt);
  virtual void       SetMarkerAtt(int sz=-1, PIMarker mrk=PI_NotDefMarker);
  virtual void       SetColMapId(CMapId cid=CMAP_OTHER);

  void               SelGraAtt(PIGraphicUC* g);

// Acces aux attributs graphiques
  inline PIColors    GetFgColAtt()  { return(mFCol); }
  inline PIColors    GetBgColAtt()  { return(mBCol); }
  inline PILineAtt   GetLineAtt()   { return(mLAtt); }
  inline PIFontSize  GetFontSz()    { return(mFSz);  }
  inline PIFontAtt   GetFontAtt()   { return(mFAtt); }
  inline int         GetMarkerSz()  { return(mMSz);  }
  inline PIMarker    GetMarker()    { return(mMrk);  } 
  inline CMapId      GetColMapId()  { return(mCmapid); }


//  --- Methode static ----
//  Calcul des Distances optimales des subdivisions 
  static void        BestTicks(double rmin,double rmax,int nticks,double& majt);

//  Les objets/methodes suivants devraient etre protected     
//  Pb avec acces depuis PIBaseWdgGen (Reza 11/07/97) 
  virtual  PIGraphicUC*  SetDrwWdg(PIBaseWdgGen* drw, int x0, int y0, int dx, int dy, PIGraphicGen* g);

//  Je declare en public a cause de cxx - Reza 11/07/97 
  struct DrwBWId { int id; PIBaseWdgGen* wdg; };
  
protected:
  friend class PIBaseWdgGen;
  virtual void       Attach(PIBaseWdgGen*, int id);
  virtual void       Detach(PIBaseWdgGen*, int id);

  void CalcTicks();

  void DrawHTicks(PIGraphicUC* g, double y, double tickUp, double tickDown, double xBeg, double xStep);
  void DrawVTicks(PIGraphicUC* g, double x, double tickLeft, double tickRight, double yBeg, double yStep);
  void DrawHLabels(PIGraphicUC* g, double y, double xBeg, double xStep, int just=0);
  void DrawVLabels(PIGraphicUC* g, double x, double yBeg, double yStep, int just=0);
  void DrawGrid(PIGraphicUC* g);

  
  double xMin, xMax, yMin, yMax;  // Valeurs en unites user
  int xW0, yW0, xWd, yWd;        // Origine/largeur ds la fenetre de trace
  bool   aXdir, aYdir;           // Sens des axes horiz, vertical 
  int aXFlg, aYFlg;

  double xFirstMajTick, xFirstMinTick;
  double yFirstMajTick, yFirstMinTick;
  double xMajTickStep, xMinTickStep;
  double yMajTickStep, yMinTickStep;
  double xMajTickLen,  xMinTickLen;
  double yMajTickLen,  yMinTickLen;
  
  int limitsFixed;
  unsigned int axesFlags;
  
  PIBaseWdgGen* mBWdg;
  PIGraphicUC* mGrUC;

  list<DrwBWId>  mBWdgList;
  bool mDndfg;

//  Gestion d attributs graphiques associes a chaque drawer
  PIColors           mFCol, mBCol;
  PILineAtt          mLAtt;
  PIFontSize         mFSz;
  PIFontAtt          mFAtt;
  int                mMSz;
  PIMarker           mMrk;  
  CMapId             mCmapid;
  
};


//  Classe avec gestion d une liste d elements a tracer 

class PIElDrawer : public PIDrawer 
{
public:
  enum { PIDEL_Line = 1, PIDEL_Text = 2,
         PIDEL_Rect = 3, PIDEL_FRect = 4, 
         PIDEL_Circ = 5, PIDEL_FCirc = 6 } ; 

                     PIElDrawer();
  virtual           ~PIElDrawer();

  virtual void	     SetTitles(const char* tt=NULL, const char* tb=NULL);
  virtual void       SetTitles(string const & tt, string const & tb);

  virtual void       Draw(PIGraphicUC* g, double xmin, double ymin, double xmax, double ymax); 

  inline int         ElAddLine(PIGrCoord x1, PIGrCoord y1, PIGrCoord x2, PIGrCoord y2, 
                               PIColors c=PI_NotDefColor)
    { return( ElAdd(PIDEL_Line, x1, y1, x2, y2, NULL, c) ); }  
  inline int         ElAddText(PIGrCoord x, PIGrCoord y, const char* s, PIColors c=PI_NotDefColor)
    { return( ElAdd(PIDEL_Text, x, y, 0, 0, s, c) ); }  
  inline int         ElAddRect(PIGrCoord x, PIGrCoord y, PIGrCoord dx, PIGrCoord dy, 
                               PIColors c=PI_NotDefColor)
    { return( ElAdd(PIDEL_Rect, x, y, dx, dy, NULL, c) ); }  
  inline int         ElAddFRect(PIGrCoord x, PIGrCoord y, PIGrCoord dx, PIGrCoord dy,
                               PIColors c=PI_NotDefColor)
    { return( ElAdd(PIDEL_FRect, x, y, dx, dy, NULL, c) ); }  
  inline int         ElAddCirc(PIGrCoord x, PIGrCoord y, PIGrCoord r, PIColors c=PI_NotDefColor)
    { return( ElAdd(PIDEL_Circ, x, y, r, r, NULL, c) ); }  
  inline int         ElAddFCirc(PIGrCoord x, PIGrCoord y, PIGrCoord r, PIColors c=PI_NotDefColor)
    { return( ElAdd(PIDEL_FCirc, x, y, r, r, NULL, c) ); }  

  void               ElDel(int id);
  void               ElDelAll();

protected:
  int                ElAdd(int typ, PIGrCoord x, PIGrCoord y, PIGrCoord dx, PIGrCoord dy, 
                           const char* s, PIColors c=PI_NotDefColor);
#ifdef __DECCXX
public:
#endif
  struct DrwEl{
    int eid, etyp;
    PIGrCoord ex,ey;
    PIGrCoord edx,edy;
    string es;
    PIColors col;
  };
#ifdef __DECCXX
protected:
#endif
  typedef list<DrwEl> DrwElList;

  DrwElList mElist;
  int mEn;

  string titleT, titleB;       // Titre Haut - Bas

};

#endif
