// This may look like C code, but it is really -*- C++ -*-
// PIElDrawer - 
//                             R. Ansari  97-02
// LAL (Orsay) / IN2P3-CNRS  DAPNIA/SPP (Saclay) / CEA
#ifndef PIELDRW_H
#define PIELDRW_H

#include "pidrawer.h"

/*  ------------------- Classe PIElDrwMgr ------------------------  */
//  Classe avec gerant d une liste d elements a tracer 

class PIElDrwMgr
{
public:
  enum { PIDEL_Line = 1, PIDEL_Text = 2,
         PIDEL_Rect = 3, PIDEL_FRect = 4, 
         PIDEL_Circ = 5, PIDEL_FCirc = 6,
         PIDEL_Oval = 7, PIDEL_FOval = 8,
         PIDEL_Arc = 9,  PIDEL_FArc = 10,
         PIDEL_Arc3P = 11,  PIDEL_FArc3P = 12,
         PIDEL_Poly = 13, PIDEL_FPoly = 14,
	 PIDEL_Mark = 15, PIDEL_Arrow = 16,
         PIDEL_CText = 17  } ; 

		PIElDrwMgr();
  virtual	~PIElDrwMgr();

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

  // ---- Ajout de lignes
  inline int    ElAddLine(double x1, double y1, double x2, double y2, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Line, x1, y1, x2, y2, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddLine(double x1, double y1, double x2, double y2, 
			  PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Line, x1, y1, x2, y2, NULL, gatt, 0, fgsc) ); }  

  // ---- Ajout de fleches 
  inline int    ElAddArrow(double x1, double y1, double x2, double y2, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Arrow, x1, y1, x2, y2, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddArrow(double x1, double y1, double x2, double y2, 
			   PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Arrow, x1, y1, x2, y2, NULL, gatt, 0, fgsc) ); }  

  // ---- Ajout de marker 
  inline int    ElAddMarker(double x, double y, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Circ, x, y, 0, 0, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddMarker(double x, double y, PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Mark, x, y, 0, 0, NULL, gatt, 0, fgsc) ); }  

  // ---- Ajout de texte
  inline int    ElAddText(double x, double y, const char* s, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Text, x, y, 0, 0, s, gatt, 0, fgsc) ); }  
  inline int    ElAddText(double x, double y, const char* s, 
			  PIGraphicAtt const & gatt, unsigned long tpd, bool fgsc=false)
    { return( ElAdd(PIDEL_Text, x, y, 0, 0, s, gatt, tpd, fgsc) ); }  
  inline int    ElAddText(double x, double y, string const & s, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Text, x, y, 0, 0, s.c_str(), gatt, 0, fgsc) ); }  
  inline int    ElAddText(double x, double y, string const & s, 
			  PIGraphicAtt const & gatt, unsigned long tpd, bool fgsc=false)
    { return( ElAdd(PIDEL_Text, x, y, 0, 0, s.c_str(), gatt, tpd, fgsc) ); }  

  // ---- Ajout de texte composite avec exposant - indice
  inline int    ElAddCompText(double x, double y, string const& s, string const& s_up,
			      string const& s_dn, unsigned long tpd=0, bool fgsc=false)
    { PIGraphicAtt gatt; 
      return( ElAdd(x, y, s.c_str(), gatt, s_up.c_str(), s_dn.c_str(), NULL, tpd, fgsc) ); } 
  inline int    ElAddCompText(double x, double y, string const& s, PIGraphicAtt const & gatt,
			      string const& s_up, string const& s_dn, 
			      unsigned long tpd=0, bool fgsc=false)
    { return( ElAdd(x, y, s.c_str(), gatt, s_up.c_str(), s_dn.c_str(), NULL, tpd, fgsc) ); } 
  inline int    ElAddCompText(double x, double y, string const& s, PIGraphicAtt const & gatt,
			      string const& s_up, string const& s_dn, PIGraphicAtt const & attss,
			      unsigned long tpd=0, bool fgsc=false)
    { return( ElAdd(x, y, s.c_str(), gatt, s_up.c_str(), s_dn.c_str(), &attss, tpd, fgsc) ); } 
  

  // ---- Ajout de rectangles 
  inline int    ElAddRect(double x, double y, double dx, double dy, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Rect, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddRect(double x, double y, double dx, double dy, 
			  PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Rect, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  

  inline int    ElAddFRect(double x, double y, double dx, double dy, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_FRect, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddFRect(double x, double y, double dx, double dy, 
			   PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_FRect, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  

  // ---- Ajout de cercles
  inline int    ElAddCirc(double x, double y, double r, bool fgsc=false)
    { PIGraphicAtt gatt; 
      return( ElAdd(PIDEL_Circ, x, y, 0., 360., NULL, gatt, 0, fgsc, r) ); }  
  inline int    ElAddCirc(double x, double y, double r, 
			  PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Circ, x, y, 0., 360., NULL, gatt, 0, fgsc, r) ); }  

  inline int    ElAddFCirc(double x, double y, double r, bool fgsc=false)
    { PIGraphicAtt gatt; 
      return( ElAdd(PIDEL_FCirc, x, y, 0., 360., NULL, gatt, 0, fgsc, r) ); }  
  inline int    ElAddFCirc(double x, double y, double r, 
			   PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_FCirc, x, y, 0., 360., NULL, gatt, 0, fgsc, r) ); }  

  // ---- Ajout d' ovales
  inline int    ElAddOval(double x, double y, double dx, double dy, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Oval, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddOval(double x, double y, double dx, double dy, 
			  PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Oval, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  

  inline int    ElAddFOval(double x, double y, double dx, double dy, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_FOval, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  
  inline int    ElAddFOval(double x, double y, double dx, double dy, 
			   PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_FOval, x, y, dx, dy, NULL, gatt, 0, fgsc) ); }  

  // ---- Ajout d' arcs specifies par deux angles
  inline int    ElAddArc(double x, double y, double r, 
			 double a, double da, bool fgsc=false)
    { PIGraphicAtt gatt; 
      return( ElAdd(PIDEL_Arc, x, y, a, da, NULL, gatt, 0, fgsc, r) ); }  
  inline int    ElAddArc(double x, double y, double r, double a, double da, 
			 PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Arc, x, y, a, da, NULL, gatt, 0, fgsc, r) ); }  

  inline int    ElAddFArc(double x, double y, double r, 
			  double a, double da, bool fgsc=false)
    { PIGraphicAtt gatt; 
      return( ElAdd(PIDEL_FArc, x, y, a, da, NULL, gatt, 0, fgsc, r) ); }  
  inline int    ElAddFArc(double x, double y, double r, double a, double da, 
			  PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_FArc, x, y, a, da, NULL, gatt, 0, fgsc, r) ); }  

  // ---- Ajout d' arcs specifies par 3 points
  inline int    ElAddArc(double x1, double y1, double x2, double y2,
			 double x3, double y3, bool fgsc=false)
    { PIGraphicAtt gatt; double x[3], y[3]; 
      x[0] = x1; x[1] = x2; x[2] = x3; 
      y[0] = y1; y[1] = y2; y[2] = y3; 
      return( ElAdd(PIDEL_Arc3P, x, y, 3, gatt, fgsc) ); }  

  inline int    ElAddArc(double x1, double y1, double x2, double y2,
			 double x3, double y3, PIGraphicAtt const & gatt, bool fgsc=false)
    { double x[3], y[3]; 
      x[0] = x1; x[1] = x2; x[2] = x3; 
      y[0] = y1; y[1] = y2; y[2] = y3; 
      return( ElAdd(PIDEL_Arc3P, x, y, 3, gatt, fgsc) ); }  

  inline int    ElAddFArc(double x1, double y1, double x2, double y2,
			  double x3, double y3, bool fgsc=false)
    { PIGraphicAtt gatt; double x[3], y[3]; 
      x[0] = x1; x[1] = x2; x[2] = x3; 
      y[0] = y1; y[1] = y2; y[2] = y3; 
      return( ElAdd(PIDEL_FArc3P, x, y, 3, gatt, fgsc) ); }  

  inline int    ElAddFArc(double x1, double y1, double x2, double y2,
			  double x3, double y3, PIGraphicAtt const & gatt, bool fgsc=false)
    { double x[3], y[3]; 
      x[0] = x1; x[1] = x2; x[2] = x3; 
      y[0] = y1; y[1] = y2; y[2] = y3; 
      return( ElAdd(PIDEL_FArc3P, x, y, 3, gatt, fgsc) ); }  

  // ---- Ajout de polygones 
  inline int    ElAddPoly(vector<double>& x, vector<double>& y, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_Poly, x, y, gatt, fgsc) ); }  
  inline int    ElAddPoly(vector<double>& x, vector<double>& y, 
			  PIGraphicAtt const & gatt, bool fgsc=false)
    { return( ElAdd(PIDEL_Poly, x, y, gatt, fgsc) ); } 
 
  inline int    ElAddFPoly(vector<double>& x, vector<double>& y, bool fgsc=false)
    { PIGraphicAtt gatt; return( ElAdd(PIDEL_FPoly, x, y, gatt, fgsc) ); }  
  inline int    ElAddFPoly(vector<double>& x, vector<double>& y, 
			   PIGraphicAtt const & gatt, bool fgsc=false)

    { return( ElAdd(PIDEL_FPoly, x, y, gatt, fgsc) ); }  

  void               ElDel(int id);
  inline void        ElDelLast() { ElDel(mEn); }
  void               ElDelAll();

protected:
  int                ElAdd(int typ, double x, double y, double dx, double dy, 
                           const char* s, PIGraphicAtt const & att,
			   unsigned long txtposdir, bool fgsc, double r=0.);
  int		     ElAdd(double x, double y, const char* s, PIGraphicAtt const & att, 
			   const char* s_up, const char* s_dn, PIGraphicAtt const * gass, 
			   unsigned long tpd, bool fgsc);

  int                ElAdd(int typ, vector<double>& x, vector<double>& y, 
			   PIGraphicAtt const & att, bool fgsc);
  int                ElAdd(int typ, double* x, double* y, int n,
			   PIGraphicAtt const & att, bool fgsc);

  struct TxtEl {
    string txt;
    unsigned long txtpd;
    string* txt_up;
    string* txt_dn;
    PIGraphicAtt* attss;
  };

  struct DrwEl{
    int eid, etyp;
    double ex,ey,er;
    double edx,edy;
    PIGraphicAtt gatt;
    TxtEl* es;
    PIGrCoord* xpol;
    PIGrCoord* ypol;
    int npol;
    bool scc;  // true -> normalized coordinates ( 0..1 )
  };

  typedef list<DrwEl> DrwElList;
  DrwElList mElist;
  int mEn;
  
};

/*  ------------------- Classe PIElDrawer ------------------------  */
// Classe de Drawer capable de gerer une liste d'elements a tracer

class PIElDrawer : public PIDrawer 
{
public:
                     PIElDrawer(bool fgclip=true);
  virtual           ~PIElDrawer();

//   Methode de decodage des options
  virtual int        DecodeOptionString(vector<string> & opt, bool rmdecopt=true);
//   Texte d'aide des options disponibles
  virtual void	     GetOptionsHelpInfo(string& info);

  virtual void       DrawAxes(PIGraphicUC* g); // Trace d'axes avec label axe X,Y

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

// Renvoie une distance au point x,y 
// 0: au(x) point(s) le(s) plus proche(s) ... 1  au bord xmin/xmax , ymin/ymax
// La methode par defaut calcule la distance normalisee au point ((xmin+xmax)/2,(ymin+ymax)/2)
  virtual double     GetDistanceToPoint(double x, double y);

  inline void        ConfigureAxeTicks(int ntickx=0, int nticky=0, 
				       double majtl=0., double mintl=0.)
     { axeDr.ConfigureTicks(ntickx, nticky, majtl, mintl); }
  inline void        ConfigureAxeAutoFontSize(double fszf=0.)
     { axeDr.ConfigureAutoFontSize(fszf); }

  inline PIElDrwMgr& ElDrwMgr()    { return eltsMgr; }

  inline void        SetTitles(string tt, string tb)   { titleT = tt;  titleB = tb; }
  inline void        SetTitles(string tt, string tb, PIGraphicAtt const& att) 
                        { titleT = tt;  titleB = tb; titleAtt = att; }
  inline void        ShowTitles(bool fg=true) { showTitles = fg; }

  inline void        SetAxesLabels(string xl, string yl) { xLabel = xl;  yLabel = yl; }
  inline void        SetAxesLabels(string xl, string yl, PIGraphicAtt const& att) 
                        { xLabel = xl;  yLabel = yl; labelAtt = att; }
  inline void        ShowAxesLabels(bool fg=true) { showAxesLabels = fg; }

// -- Pour compatibilite avec l'interface precedente , Reza 08/2002 
  inline void        ElDel(int id) { eltsMgr.ElDel(id); }
  inline void        ElDelLast()   { eltsMgr.ElDelLast(); }
  inline void        ElDelAll()    { eltsMgr.ElDelAll(); }
  
  inline int	     ElAddText(double x, double y, const char* s)
                                   { return eltsMgr.ElAddText(x, y, s); }

protected:
  PIElDrwMgr eltsMgr;
  string titleT, titleB;       // Titre Haut - Bas
  PIGraphicAtt titleAtt;       // Attributs graphiques de trace de titre
  bool showTitles;             // Affichage des titres si true
  string xLabel, yLabel;       // Label x, label y
  PIGraphicAtt labelAtt;       // Attributs graphiques de trace de label d'axes
  bool showAxesLabels;         // Affichage des labels d'axes si true
  bool fgClip;                 // Si true, appel a PIGraphicUC::Clip() ds Draw()
  PIAxes axeDr;                // Trace d'axes
};


#endif
