/*

    Bist: a chemical drawing tool
    Copyright (C) 2008 Valerio Benfante

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/*


PROCEDURA := 'ARC' APRI
			ID_PROC SEP POSX SEP POSY SEP WIDTH SEP HEIGHT
			SEP  STRANGL SEP ENDANGL SEP COLORE SEP COLORE
			SEP COLORE SEP XPIVOT SEP YPIVOT SEP ANGOLOROT
			SEP SPESSORE SEP DASH
		   CHIUDI |
	     'ARROW' APRI
			ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
			SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
			SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
			DASH SEP NUMPUNTE
		   CHIUDI |
	     'BEZIER' APRI
			ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
			SEP POSX SEP POSY SEP POSX SEP POSY
			SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
			SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
			DASH SEP NUMPUNTE
		      CHIUDI


*/

#define PROC_BEZIER_OFFSETT_TANGENT_FOR_ARROW 0.08


/**
 *Questa classe rappresenta una procedura generica ovvero un disegno che
 *non e' una molecola.
 */

class procedura: public disegnabile, public genitore,
		 public selezionabile, public identificabile,
                 public write_native{

public:
  procedura(int tipo)
    :_tipo(tipo)
  {

  }

  procedura(const procedura& altra);

  procedura(const procedura* other);

  procedura()
   :_tipo(0)
  {
  }


  /**
   *distruttore
   */

  virtual ~procedura();

 /**
  *\return true se altro ha lo stesso id di quest'istanza
  **/

  bool operator==(procedura* altro);

  virtual void init()=0;

  virtual int id()=0;
  virtual int id_gruppo();

  virtual float w()=0;
  virtual float visual_w()=0;
  virtual float phys_w()=0;
  virtual float h()=0;
  virtual float visual_h()=0;
  virtual float phys_h()=0;
  virtual float posx()=0;
  virtual float visual_posx()=0;
  virtual float phys_posx()=0;
  virtual float posy()=0;
  virtual float visual_posy()=0;
  virtual float phys_posy()=0;

  virtual void trasla(float dx, float dy)=0;
  virtual void phys_translate(float dx, float dy)=0;


  virtual float xpivot()=0;
  virtual float ypivot()=0;
  virtual float angolorot()=0;

  virtual int cr()=0;
  virtual int cb()=0;
  virtual int cg()=0;


  /**
   *
   *\param x ascissa dell'angolo in alto a sinistra della bounding box
   *\param y ordinata dell'angolo in alto a sinistra della bounding box
   *\param w larghezza della bounding box
   *\param h altezza della bounding box
   *\return  true se  l'oggetto e'  dentro la  bounding  box specificata
   *false altrimenti.
   */

  virtual bool dentro_bb(float x, float y, float w , float h){
    if(posx()>x && posx()<x+w &&
       posy()>y && posy()<y+h){
      return true;
    }else{
      return false;
    }
  }



  virtual void arrows_points(std::vector<float>& x,
                             std::vector<float>& y)=0;



  /*

         +--------------->
         |       ld
         |        +-----+
         |        |     |
         |        +-----+ ru
        \ /
         V
  */



  virtual void get_bounding_box(std::pair<float,float>& ld,
                                std::pair<float,float>& ru)=0;

  virtual void get_phys_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru)=0;

  virtual void get_visual_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru)=0;


  /**
   *
   *\param posx_m ascissa del puntatore
   *\param posy_m ordinata del puntatore
   *\return l'id di questo oggetto se il mouse si trova all'interno della
   *sua bounding box, -1 altrimenti.
   */
  virtual int sotto_mouse(int posx_m, int posy_m)=0;

  /**
   *check if a control point of this procedura has been hitted by mouse
   *\return the id of the procedura hitted -1 if no one has been hitted
   */

  virtual int control_point_under_mouse(int posx_m, int posy_m)=0;


  virtual void unset_edit_control_point()=0;

  virtual void control_point_transl(float dx, float dy)=0;

  virtual void id(int nw)=0;
  virtual void w(float nw)=0;
  virtual void h(float nw)=0;
  virtual void posx(float nw)=0;
  virtual void posy(float nw)=0;

  virtual void xpivot(float nw)=0;
  virtual void ypivot(float nw)=0;
  virtual void angolorot(float nw)=0;

  virtual void cr(int nw)=0;
  virtual void cb(int nw)=0;
  virtual void cg(int nw)=0;

  virtual int tipo(){
    return _tipo;
  }




protected:
  int _tipo;
  //vector < pair <float,float> > _vertici;
  static const float  _tolerance_hit_control_point;
};


/**
 *Questa classe rappresenta un cerchio o ellisse
 */

class proc_arc : public procedura{

public:

  proc_arc();

  /**
   *Costruttore di copia dal puntatore
   */

  proc_arc(const proc_arc* altro);

  proc_arc(int id,float xst, float yst,
	   float xen, float yen,
	   float x1, float y1,
	   float x2, float y2,
	   float x3, float y3,
	   float x4, float y4,
	   int cr, int cb, int cg ,
	   float xpiv, float ypiv, float anglrot,
	   int spess, int tratt);

  virtual  ~proc_arc();



  virtual int sotto_mouse(int posx_m, int posy_m);

  virtual int control_point_under_mouse(int posx_m, int posy_m);

  virtual void unset_edit_control_point();

  virtual void control_point_transl(float dx, float dy);

  /**
   *Inizializza l'oggetto,  costruendo i vertici, il  metodo disegna() la
   *richiama automaticamente.
   */

  virtual void init();


  /*ritorna i valori*/

  virtual int id();

  virtual float posx();
  virtual float visual_posx();
  virtual float phys_posx();

  virtual float posy();
  virtual float visual_posy();
  virtual float phys_posy();

  virtual float w();
  virtual float visual_w();
  virtual float phys_w();

  virtual float h();
  virtual float visual_h();
  virtual float phys_h();

  virtual float xstart();
  virtual float visual_xstart();
  virtual float phys_xstart();

  virtual float ystart();
  virtual float visual_ystart();
  virtual float phys_ystart();

  virtual float xend();
  virtual float visual_xend();
  virtual float phys_xend();

  virtual float yend();
  virtual float visual_yend();
  virtual float phys_yend();

  virtual float x1();
  virtual float y1();

  virtual float visual_x1();
  virtual float visual_y1();

  virtual float phys_x1();
  virtual float phys_y1();

  virtual float x2();
  virtual float y2();

  virtual float visual_x2();
  virtual float visual_y2();

  virtual float phys_x2();
  virtual float phys_y2();

  virtual float x3();
  virtual float y3();

  virtual float visual_x3();
  virtual float visual_y3();

  virtual float phys_x3();
  virtual float phys_y3();

  virtual float x4();
  virtual float y4();

  virtual float visual_x4();
  virtual float visual_y4();


  virtual float phys_x4();
  virtual float phys_y4();



  virtual  int cr();
  virtual int cb();
  virtual int cg();
  virtual float xpivot();
  virtual float ypivot();
  virtual float angolorot();
  virtual int spessore();
  virtual int dash();
  /*setta i valori*/

  virtual void id(int nw);
  virtual void posx(float nw);
  virtual void posy(float nw);
  virtual void w(float nw);
  virtual void h(float nw);


  virtual void xstart(float nw);
  virtual void ystart(float nw);

  virtual void xend(float nw);
  virtual void yend(float nw);

  virtual void x1(float nw);
  virtual void y1(float nw);

  virtual void x2(float nw);
  virtual void y2(float nw);

  virtual void x3(float nw);
  virtual void y3(float nw);

  virtual void x4(float nw);
  virtual void y4(float nw);


  virtual void cr(int nw);
  virtual void cb(int nw);
  virtual void cg(int nw);
  virtual void xpivot(float nw);
  virtual void ypivot(float nw);
  virtual void angolorot(float nw);
  virtual void spessore(int nw);
  virtual void dash(int nw);
  /**
   *Disegna l'oggetto PARAMETRI DA DEFINIRE!!!!!!
   */

  virtual void disegna();


  virtual void trasla(float dx, float dy);

  virtual void phys_translate(float dx, float dy);

  /**
   *Scala l'oggetto
   *
   *\param sc il fattore di scala
   */

  virtual void scale(float sc);

  /**
   *Ruota l'oggetto in senso orario.
   *
   *\param angl l'angolo di rotazione in gradi in senso antiorario
   */

  virtual void ruota(float xpiv, float ypiv, float angl);


  virtual bool dentro_bb(float x, float y, float w , float h);


  virtual void arrows_points(std::vector<float>& x,
                             std::vector<float>& y){}



  virtual void get_bounding_box(std::pair<float,float>& ld,
                                std::pair<float,float>& ru);



  virtual void get_phys_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);

  virtual void get_visual_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);

  virtual void write_native_format(std::ostream& stream, std::string indent);

protected:

  float minima_x();
  float minima_y();

  int _id;


  float _xstart;
  float _ystart;
  float _xend;
  float _yend;
  float _x1;
  float _y1;
  float _x2;
  float _y2;
  float _x3;
  float _y3;
  float _x4;
  float _y4;


  int _cr;
  int _cb;
  int _cg;

  float _xpivot;
  float _ypivot;
  float _angolorot;

  int _spessore;
  int _dash;

  
  enum control_point_edit{none, start, end, ru, lu, lb, rb};

  control_point_edit _edited_cp;

  /**
   *La bounding box viene scalata di questa quantita'
   */

  static const float scala_bb;

};


/**
 *Questa classe rappresenta una freccia
 */

class proc_arrow : public procedura{

public:
  /**
   * Costruttore di default riempie i membri con spazzatura
   */

  proc_arrow();



  /**
   *Costruttore di copia dal puntatore
   */

  proc_arrow(const proc_arrow* altro);

  /**
   *
   *Costruisce loggetto freccia.
   *\param id id della procedura la identifica univocamente
   *\param posx ascissa dell arco
   *\param posy ordinata dell arco
   *
   *\param eposx ascissa della punta della freccia
   *\param eposy ordinata della punta della freccia
   *\param cr componente rossa del colore della procedura
   *\param cg componente verde del colore della procedura
   *\param cb componente blu del colore della procedura
   *\param xpiv ascissa dell'asse di rotazione.
   *\param ypiv ordinata dell'asse di rotazione
   *\param anglrot l'angolo di  rotazione dell'oggetto in radianti ed in
   *senso orario
   *\param spess spessore in px della "penna"
   *\param tratt lunghezza del tratteggio (nota: 0 nessun tratteggio).
   *\param punte numero di punte delle freccie, puo' assumere i valori:
   *
   *<ul>
   *
   *<li> ARR_NO_PUNT nessuna punta
   *
   *<li> ARR_OMOL_PUNT  scissione omolitica
   *
   *<li> ARR_ETEROL_PUNT   scissione eterolitica
   *
   *</ul>
   *
   */

  proc_arrow(int id,float posx, float posy,
	     float eposx,float eposy,
	     int cr, int cb, int cg ,
	     float xpiv, float ypiv, float anglrot,
	     int spess, int tratt, int punte,
	     float arr_w, float arr_h, float arr_gap);

  /**
   *Costruttore
   */


  virtual ~proc_arrow();



  virtual int sotto_mouse(int posx_m, int posy_m);
  virtual int control_point_under_mouse(int posx_m, int posy_m);
  virtual void unset_edit_control_point();
  virtual void control_point_transl(float dx, float dy);
  virtual void init();

  /*ritorna i valori*/

  virtual  int id();

  virtual float posx();
  virtual float visual_posx();
  virtual float phys_posx();

  virtual float posy();
  virtual float visual_posy();
  virtual float phys_posy();

  virtual float eposx();
  virtual float visual_eposx();
  virtual float phys_eposx();


  virtual float eposy();
  virtual float visual_eposy();
  virtual float phys_eposy();

  virtual float w();
  virtual float visual_w();
  virtual float phys_w();

  virtual float h();
  virtual float visual_h();
  virtual float phys_h();

  virtual int cr();
  virtual int cb();
  virtual int cg();
  virtual float xpivot();
  virtual float ypivot();
  virtual float angolorot();
  virtual int spessore();
  virtual int dash();
  virtual int punte();

  float arr_w();
  float arr_h();
  float arr_gap();



  /*setta i valori*/

  virtual void id(int nw);
  virtual void posx(float nw);
  virtual void posy(float nw);
  virtual void eposx(float nw);
  virtual void eposy(float nw);
  virtual void w(float nw);
  virtual void h(float nw);
  virtual void cr(int nw);
  virtual void cb(int nw);
  virtual void cg(int nw);
  virtual void xpivot(float nw);
  virtual void ypivot(float nw);
  virtual void angolorot(float nw);
  virtual void spessore(int nw);
  virtual void dash(int nw);
  virtual void punte(int nw);

  void arr_w(float nw);
  void arr_h(float nw);
  void arr_gap(float nw);

  virtual bool dentro_bb(float x, float y, float w , float h);

 /**
   *Disegna l'oggetto PARAMETRI DA DEFINIRE!!!!!!
   */

  virtual void disegna();


  virtual void trasla(float dx, float dy);

  virtual void phys_translate(float dx, float dy);

  /**
   *Scala l'oggetto
   *
   *\param sc il fattore di scala
   */

  virtual void scale(float sc);

  /**
   *Ruota l'oggetto in senso orario.
   *
   *\param angl l'angolo di rotazione in gradi in senso antiorario
   */

  virtual void ruota(float xpiv, float ypiv, float angl);


  virtual void arrows_points(std::vector<float>& x,
                              std::vector<float>& y);


  virtual void get_bounding_box(std::pair<float,float>& ld,
                                std::pair<float,float>& ru);

  virtual void get_phys_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);

  virtual void get_visual_bounding_box(std::pair<float,float>& ld,
                                       std::pair<float,float>& ru);

  virtual void write_native_format(std::ostream& stream, std::string indent);
protected:


  void calculate_equilibrium_arrows(vector<float>& x, vector<float>& y);


  /**
   *Disegna la seconda freccia di un equibrio.
   */

  void disegna_equilibrio();


  int _id;
  float _posx;
  float _posy;
  float _eposx;
  float _eposy;

  int _cr;
  int _cb;
  int _cg;

  float _xpivot;
  float _ypivot;
  float _angolorot;

  int _spessore;
  int _dash;
  int _punte;

  float _arr_w;
  float _arr_h;
  float _arr_gap;


  enum control_point_edit{none, beg, end};

  control_point_edit _edited_cp;

};


/*

    'BEZIER' APRI
			ID_PROC SEP POSX SEP POSY SEP POSX SEP POSY
			SEP POSX SEP POSY SEP POSX SEP POSY
			SEP COLORE SEP COLORE SEP COLORE SEP XPIVOT
			SEP YPIVOT SEP ANGOLOROT SEP SPESSORE SEP
			DASH SEP NUMPUNTE
		      CHIUDI
*/



/**
 *Questa classe rappresenta una curva di bezier
 */


class proc_bezier : public procedura {

public:
  /**
   * Costruttore di default riempie i membri con spazzatura
   */

  proc_bezier();

  /**
   *Costruttore di copia da puntatore
   */

  proc_bezier(const proc_bezier* altro);

  /**
   *
   *Costruisce l'oggetto freccia.
   *\param id id della procedura, la identifica univocamente
   *\param ix ascissa del punto di partenza della curva
   *\param iy ordinata del punto di partenza della curva
   *
   *\param tan1x ascissa della prima tangente.
   *\param tan1y ordinata della prima tangente.
   *
   *\param tan2x ascissa della seconda tangente.
   *\param tan2y ordinata della seconda tangente.
   *
   *\param ex ascissa del punto di arrivo della curva
   *\param ex ordinata del punto di arrivo della curva
   *
   *\param cr componente rossa del colore della procedura
   *\param cg componente verde del colore della procedura
   *\param cb componente blu del colore della procedura
   *\param xpiv ascissa dell'asse di rotazione.
   *\param ypiv ordinata dell'asse di rotazione
   *\param anglrot l'angolo di rotazione in radianti ed in senso orario
   *\param spess spessore in px della "penna"
   *\param tratt lunghezza del tratteggio (nota: 0 nessun tratteggio).
   *\param punte numero di punte delle freccie, puo' assumere i valori:
   *
   *<ul>
   *
   *<li> ARR_NO_PUNT nessuna punta
   *
   *<li> ARR_OMOL_PUNT  scissione omolitica
   *
   *<li> ARR_ETEROL_PUNT   scissione eterolitica
   *
   *</ul>
   *
   */

  proc_bezier(int id,float ix, float iy,
	      float tang1x, float tang1y,
	      float tang2x, float tang2y,
	      float ex, float ey,
	      int cr, int cb, int cg ,
	      float xpiv, float ypiv, float anglrot,
	      int spess, int tratt, int punte,
	      float arr_w, float arr_h, float arr_gap);

  /**
   *Costruttore
   */


  virtual ~proc_bezier();



  virtual int sotto_mouse(int posx_m, int posy_m);
  virtual int control_point_under_mouse(int posx_m, int posy_m);
  virtual void unset_edit_control_point();
  virtual void control_point_transl(float dx, float dy);
  virtual bool dentro_bb(float x, float y, float w , float h);

  virtual void arrows_points(std::vector<float>& x,
                             std::vector<float>& y);


  virtual void get_bounding_box(std::pair<float,float>& ld,
                                std::pair<float,float>& ru);



  virtual void get_phys_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);

  virtual void get_visual_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);



  virtual  void init();

  /*ritorna i valori*/
  virtual float posx();
  virtual float visual_posx();
  virtual float phys_posx();

  virtual float posy();
  virtual float visual_posy();
  virtual float phys_posy();

  virtual int   id();
  virtual float ix();
  virtual float visual_ix();
  virtual float phys_ix();

  virtual float iy();
  virtual float visual_iy();
  virtual float phys_iy();

  virtual float tan1x();
  virtual float visual_tan1x();
  virtual float phys_tan1x();

  virtual float tan1y();
  virtual float visual_tan1y();
  virtual float phys_tan1y();

  virtual float tan2x();
  virtual float visual_tan2x();
  virtual float phys_tan2x();


  virtual float tan2y();
  virtual float visual_tan2y();
  virtual float phys_tan2y();

  virtual float ex();
  virtual float visual_ex();
  virtual float phys_ex();

  virtual float ey();
  virtual float visual_ey();
  virtual float phys_ey();

  virtual float w();
  virtual float visual_w();
  virtual float phys_w();

  virtual float h();
  virtual float visual_h();
  virtual float phys_h();


  virtual int cr();
  virtual int cb();
  virtual int cg();
  virtual float xpivot();
  virtual float ypivot();
  virtual float angolorot();
  virtual int spessore();
  virtual int dash();
  virtual int punte();

  float arr_w();
  float arr_h();
  float arr_gap();



  /*setta i valori*/

  virtual void id(int nw);

  virtual void ix(float nw);
  virtual void iy(float nw);
  virtual void tan1x(float nw);
  virtual void tan1y(float nw);
  virtual void tan2x(float nw);
  virtual void tan2y(float nw);
  virtual void ex(float nw);
  virtual void ey(float nw);

  virtual void posx(float nw){} //da fare
  virtual void posy(float nw){} //da fare

  virtual void w(float){} //da fare
  virtual void h(float){} //da fare
  virtual void cr(int nw);
  virtual void cb(int nw);
  virtual void cg(int nw);
  virtual void xpivot(float nw);
  virtual void ypivot(float nw);
  virtual void angolorot(float nw);
  virtual void spessore(int nw);
  virtual void dash(int nw);
  virtual void punte(int nw);


  void arr_w(float nw);
  void arr_h(float nw);
  void arr_gap(float nw);


 /**
   *Disegna l'oggetto PARAMETRI DA DEFINIRE!!!!!!
   */

  virtual void disegna();


  virtual void trasla(float dx, float dy);


  virtual void phys_translate(float dx, float dy);

  /**
   *Scala l'oggetto
   *
   *\param sc il fattore di scala
   */

  virtual void scale(float sc);

  /**
   *Ruota l'oggetto in senso orario.
   *
   *\param angl l'angolo di rotazione in gradi in senso antiorario
   */

  virtual void ruota(float xpiv, float ypiv, float angl);

  virtual void write_native_format(std::ostream& stream, std::string indent);

protected:
  /**
   *correct arrow for bezier
   *\param true if arrow is at the end of th e cureve false otherwise
   */
  std::pair<float,float> correct_arrow_ps(bool end_curve);


 /**
   *La bounding box viene scalata di questa quantita'
   */

  static const float scala_bb;

  int _id;
  float _ix;
  float _iy;
  float _tan1x;
  float _tan1y;
  float _tan2x;
  float _tan2y;
  float _ex;
  float _ey;


  int _cr;
  int _cb;
  int _cg;

  float _xpivot;
  float _ypivot;
  float _angolorot;

  int _spessore;
  int _dash;
  int _punte;

  float _arr_w;
  float _arr_h;
  float _arr_gap;


  enum control_point_edit{none, beg, tan1, tan2, end};

  control_point_edit _edited_cp;

};


/**
 *box proc type
 */

enum box_type { //values matches the ones defined in grammar file
  NORMAL=0,
  SHADOWED=1
};


class BoxProc: public procedura{

public:

  BoxProc();

  /**
   *Costruttore di copia da puntatore
   */

  BoxProc(const BoxProc* altro);

  /**
   *
   *\param id box id 
   *\param cr red component for pen color
   *\param cg green component for pen color
   *\param cb blue component for pen color
   *\param xpiv unused
   *\param ypiv unused
   *\param anglrot unused
   *\param thick pen thickness 
   *\param dash 
   *<pre>
   *
   *  (ld_x,ld_y)                     
   *            +-------------------+           
   *            |                   |           
   *            |                   |           
   *            |                   |           
   *            |                   |           
   *            |                   |           
   *            |                   |           
   *            |                   |           
   *            +-------------------+           
   *                      (ru_x,ru_y)  
   *</pre>
   *
   */

  BoxProc(int id,float ld_x, float ld_y,
          float ru_x, float ru_y,
          int cr, int cb, int cg ,
          float xpiv, float ypiv, float anglrot,
          int thick, int dash, box_type type);



  /**
   *destructor
   */

  virtual ~BoxProc();


  virtual void init();

  virtual int id();


  virtual float w();
  virtual float visual_w();
  virtual float phys_w();
  virtual float h();
  virtual float visual_h();
  virtual float phys_h();
  virtual float posx();
  virtual float visual_posx();
  virtual float phys_posx();
  virtual float posy();
  virtual float visual_posy();
  virtual float phys_posy();
  virtual   int spessore();
  virtual   int dash();

  virtual float ld_x();
  virtual float ld_y();

  virtual float ru_x();
  virtual float ru_y();

  virtual float phys_ld_x();
  virtual float phys_ld_y();

  virtual float phys_ru_x();
  virtual float phys_ru_y();

  virtual float visual_ld_x();
  virtual float visual_ld_y();

  virtual float visual_ru_x();
  virtual float visual_ru_y();

  


  virtual float xpivot();
  virtual float ypivot();
  virtual float angolorot();

  virtual int cr();
  virtual int cb();
  virtual int cg();


  box_type b_type();

  virtual bool dentro_bb(float x, float y, float w , float h);
  virtual void arrows_points(std::vector<float>& x,
                             std::vector<float>& y){};



  /*

         +--------------->
         |       ld
         |        +-----+
         |        |     |
         |        +-----+ ru
        \ /
         V
  */



  virtual void get_bounding_box(std::pair<float,float>& ld,
                                std::pair<float,float>& ru);

  virtual void get_phys_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);

  virtual void get_visual_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru);


  /**
   *
   *\param posx_m ascissa del puntatore
   *\param posy_m ordinata del puntatore
   *\return l'id di questo oggetto se il mouse si trova all'interno della
   *sua bounding box, -1 altrimenti.
   */
  virtual int sotto_mouse(int posx_m, int posy_m);

  /**
   *check if a control point of this BoxProc has been hitted by mouse
   *\return the id of the BoxProc hitted -1 if no one has been hitted
   */

  virtual int control_point_under_mouse(int posx_m, int posy_m);


  virtual void unset_edit_control_point();

  virtual void control_point_transl(float dx, float dy);

  virtual void id(int nw);
  virtual void w(float nw);
  virtual void h(float nw);
  virtual void posx(float nw);
  virtual void posy(float nw);

  virtual void ld_x(float nw);
  virtual void ld_y(float nw);

  virtual void ru_x(float nw);
  virtual void ru_y(float nw);

  virtual void xpivot(float nw);
  virtual void ypivot(float nw);
  virtual void angolorot(float nw);

  virtual void spessore(int nw);
  virtual void dash(int nw);

  virtual void cr(int nw);
  virtual void cb(int nw);
  virtual void cg(int nw);

  void b_type(box_type type);

  virtual void disegna();
  virtual void scale(float sc);
  virtual void ruota(float xpiv, float ypiv,float angl);
  virtual void trasla(float dx, float dy);
  virtual void phys_translate(float dx, float dy);

  virtual void write_native_format(std::ostream& stream, std::string indent="");

  const static int shadow_thickness_factor;
protected:
  /*
  (_ld.first,_ld.second)
            +-------------------+
            |                   |
            |                   |
            |                   |
            |                   |
            |                   |
            |                   |
            |                   |
            +-------------------+
                      (_ru.first,_ru.second)
  */


  int _id;

  std::pair<float,float> _ld;
  std::pair<float,float> _ru;
  
  int _cr;
  int _cg;
  int _cb;

  float _xpivot;
  float _ypivot;
  float _angolorot;

  int _thickness;
  int _dash;

  box_type   _box_type;

  enum control_point_edit{none, ld, ru};
  control_point_edit _edited_cp;
};
