/*

    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/>.
*/

#define ACT_NOTHING                   -1
#define ACT_SEL_ATOM                   0
#define ACT_SEL_GROUP                  1
#define ACT_SEL_BOX                    2
#define ACT_DELETE_SELECTED            3
#define ACT_KILL                       4
#define ACT_DRAW_SINGLE_BOND           5
#define ACT_DRAW_DOUBLE_BOND           6
#define ACT_DRAW_TRIPLE_BOND           7
#define ACT_DRAW_ARROW                 8
#define ACT_DRAW_BEZIER                9
#define ACT_DRAW_ARC                  10
#define ACT_DRAW_ETICH                11
#define ACT_TRANSLATE_SELECTED        12
#define ACT_ROTATE_SELECTED           13
#define ACT_SCALE_SELECTED            14
#define ACT_DRAW_ORB                  15
#define ACT_DRAW_LIBRARY              16
#define ACT_FIXED_ROTATION            17
#define ACT_DRAW_CHAIN                18
#define ACT_FLIP_HOR                  19
#define ACT_FLIP_VER                  20
#define ACT_COPY                      21
#define ACT_PASTE                     22
#define ACT_3D_ROT                    23
#define ACT_ZOOM                      24
#define ACT_UNZOOM                    25
#define ACT_EDIT_CONTROL_POINT_CURVES 26
#define ACT_TRANSL_CANVAS             27
#define ACT_DRAW_BOX                  28



#define GUI_KEY_ZOOM                      '+'
#define GUI_KEY_UNZOOM                    '-'
#define GUI_KEY_GLUE_MODE                 'g'

/**
 *Questa classe rappresenta il widget sul quale si disegnano le cose
 */

class mol_canvas: public Fl_Widget {
  
public:
  mol_canvas(int X,int Y,int W,int H); 

  virtual ~mol_canvas();

  void add_immagine(immagine* imm);

  void action(int nw);
  int action();


  /**
   *Stabilisce di quanto ruotare gli elementi (in radianti)
   */
  void fixed_rotation_degree(float nw);



  void num_atom_chain(unsigned int nw);


  void orient_chain(float nw);

  bool glue_mode();
  void glue_mode(bool nw);
  bool toggle_glue_mode();

  /**
   *Cambia lo zoom globale e ridisegna la canvas
   *\param entity l'entita' dello zoom
   *\param traslx traslazione per le x
   *\param trasly traslazione per le y
   */
  void zoom(float entity, int traslx, int trasly);


  void zoom_center_to_mousepointer(float entity);

  /**
   *check if bond is double-clicked
   *\return true if doubleclicked
   */

  bool d_click_bond();


  /**
   *check if atom is double-clicked
   *\return true if doubleclicked
   */

  bool d_click_atom();


  /**
   *translate canvas
   *
   */
  void translate(int dx,int dy);


  /**
   *Registra  all'editor che  l'immagine e'  stata modificata  e  che e'
   *necessario un backup  in editor::_immagini per permettere operazioni
   *di undo.  <p><b>Va chiamata  ogni volta che l'immagine e' modificata
   *e si vuole che l'utente possa tornare indietro.</b></p>
   */

  void reg_modified();


  void rotation_pivot_pos(int x, int y);

  enum test_glue_what {
    NONE,
    ATOMS,
    PARALLEL_BOND
  };

protected:

  void test_and_glue_objects();

  void glue_vertices(atomo* sel, atomo* hook);

  void glue_bonds(atomo* sel_1,atomo* sel_2,
		  atomo* hook_1,atomo* hook_2);

  /*
   *\return l'indirizzo del plugin attuale
   */
  
  bist_plugin* plugin();

  /**
   *Genera  una catena  di n  atomi agganciandola  eventualmente  ad una
   *molecola preesistente
   *
   *\param n_carb numero di carboni aggiunti formanti la catena
   *
   *\param orient angolo di sviluppo della catena
   */

  void genera_catena(unsigned int n_carb, float orient);

  
  /**
   *Disegna una preview per il legame
   *
   *\param tip il tipo di legame
   */
  void draw_preview_bond(int tip);


  std::vector<int> preview_bond_calc_w_springs(int x_c, int y_c);

  /**
   *Aggiunge il legame alla classe immagine col tipo specificato: questo
   *metodo va usato solo all'interno del metodo handle.
   */

  int aggiungi_nuovo_legame(int tipo);


  virtual void draw();

  virtual int handle(int e);



  void set_action_translate_selected_push_handle();




  immagine* _la_molecola;
  
  int _x_mouse;
  int _y_mouse;


  int _x_pivot;
  int _y_pivot;

  /**
   *Cosa deve fare?
   */
  int _action;


  vector< pair<float,float> > _bezier_point;


  /**
   *Atomo di  partenza del legame zero  se il legame inizia  da un atomo
   *nuovo
   */

  atomo* _start_atom;


 /**
  *Atomo di  arrivo del legame zero  se il legame inizia  da un atomo
   *nuovo
   */

  atomo* _end_atom;






  /**
   *true se la freccia deve disegnare il punto di arrivo false altrimenti
   */

  bool _b_arrow_added;
  




  /**
   *centro dell'ellisse (ascissa)
   */

   int _x_arc_centr;



  /**
   *centro dell'ellisse (ordinata)
   */

   int _y_arc_centr;


  /**
   *Raggio maggiore dell'ellisse
   */

  int _arc_max_ax;


  /**
   *Raggio maggiore dell'ellisse
   */

  int _arc_min_ax;

  /**
   *Tiene conto dei punti settati per costruire un ellisse.
   */

  //vector< pair<float,float> > _arc_point;



  /**
   *true se il legame e' stato aggiunto false altrimenti
   */

  bool _b_bond_added;



  /**
   *x dell'atomo del nuovo legame
   */

  int  _x_added_atom;

  /**
   *y dell'atomo del nuovo legame
   */

  int _y_added_atom;


  /**
   *true se si deve disegnare la box false altrimenti
   */

  bool _b_construct_box;



  
  int _dx_added_atom;
  int _dy_added_atom;

  Fl_Pixmap _pivot_xpm;

  float _fixed_rotation_degree;
  
  /**
   *numero di atomi di una catena alchilica da aggiungere
   */

  unsigned int _num_atom_chain;

  /**
   *Orientazione degli atomi da aggiungere
   */

  float  _orient_chain;


  bool   _glue_mode;

  const static float rotation_incr;
  const static float zoom_incr;
  const static float scale_incr;


};
