/*

    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/>.
*/
#include <global.hpp>

#include <cairo/cairo.h>
#include <pango/pangocairo.h>
#include <cairo_t_singleton.hpp>
#include <glib.h>


#include <FL/Fl_Image.H>
#include <FL/Fl_Pixmap.H>
#include <FL/Fl.H>
#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Menu_Bar.H>
#include <FL/Fl_Menu_Item.H>
#include <FL/Fl_Toggle_Button.H>
#include <FL/Fl_Menu_Button.H>
#include <FL/Fl_Choice.H>
#include <FL/Fl_File_Chooser.H>
#include <FL/Fl_Light_Button.H>
#include <FL/Fl_Help_Dialog.H>
//#include <FL/Fl_PNG_Image.H>

#include <newton_integ.hpp>

#include <interfacce.hpp>
#include <legame.hpp>
#include <etichetta.hpp>
#include <multiline_label.hpp>
#include <multifont_label.hpp>
#include <paragraph_text.hpp>
#include <atomo.hpp>
#include <procedura.hpp>
#include <gruppo.hpp>
#include <immagine.hpp>
#include <bist_plugin.hpp>
#include <mol_canvas.hpp>


#include <util.hpp>

#include <finestra_pr.hpp>
#include <editor.hpp>
#include <bond_prop.hpp>
#include <string_prop.hpp>
#include <multiline_label_prop.hpp>
#include <paragraph_text_prop.hpp>

#include <matr.hpp>
#include <2D_vector.hpp>
#include <prefs.hpp>

#include <plot_window.hpp>

#include <pivot.xpm>

extern finestra_pr* MainWindow;

extern Preferences  __pref;

/****************mol_canvas*************************/


mol_canvas::mol_canvas(int X,int Y,int W,int H)
  :Fl_Widget(X,Y,W,H),
   _la_molecola(0),
   _x_pivot(w()/2),
   _y_pivot(h()/2),
   _action(ACT_NOTHING),
   _start_atom(0),
   _end_atom(0),
   _b_arrow_added(false),
   _x_arc_centr(0),
   _y_arc_centr(0),
   _arc_max_ax(0),
   _arc_min_ax(0),
   _b_bond_added(false),
   _x_added_atom(0),
   _y_added_atom(0),
   _b_construct_box(false),
   _pivot_xpm(pivot_xpm),
   _fixed_rotation_degree(0),
   _glue_mode(true)
{
  box(FL_ENGRAVED_BOX);
  color(FL_WHITE);

}


void mol_canvas::num_atom_chain(unsigned int nw){
  _num_atom_chain=nw;
}


void mol_canvas::orient_chain(float nw){
  _orient_chain=nw;
}


void mol_canvas::fixed_rotation_degree(float nw){
  _fixed_rotation_degree=nw;
}

void mol_canvas::add_immagine(immagine* imm){

#ifdef DEBUG
  std::cerr << "added: " << imm << endl; 
#endif

  _la_molecola=imm;
  _la_molecola->ruota();  
}

mol_canvas::~mol_canvas(){
#ifdef DEBUG
  cerr << "distrutto mol_canvas" << endl;
#endif
}


void mol_canvas::action(int nw){
  _action=nw;
}

int mol_canvas::action(){
  return _action;
}

bool mol_canvas::glue_mode(){
  return _glue_mode;
}

void mol_canvas::glue_mode(bool nw){
  _glue_mode=nw;
}

bool mol_canvas::toggle_glue_mode(){
  bool old=glue_mode();
  _glue_mode=!glue_mode();
  return old;
}


void mol_canvas::draw(){
  draw_box();
  
  if(__pref.getDrawGrid()){
    fl_color(0xdd,0xdd,0xdd);

    char dash[2]={__pref.get_tratteggio_legame(),0}; //preferenze 
    fl_line_style(FL_SOLID,1,dash);

    float incrx=__pref.getGridSpacing()  * __pref.getZoom();
    float incry=__pref.getGridSpacing()  * __pref.getZoom();


    int main_w=MainWindow->ritorna_mol_canvas()->window()->w();
    int main_h=MainWindow->ritorna_mol_canvas()->window()->h()-ALT_BUTT_TOP-HEIGHT_INF_BAR;


    for(float i=x();i<=w()+x();i+=incrx){
      if (i > 0 && i <= main_w){
	fl_line(static_cast<int>(rintf(i)), y(), static_cast<int>(rintf(i)), y() + h());
      }
     
    }
    
    for(float i=y();i<=h()+y();i+=incry){
      if (i > 0 && i <= main_h){
	fl_line(x(), static_cast<int>(rintf(i)), x()+w(), static_cast<int>(rintf(i)));
      }
    }
    
  }
  fl_line_style(0);


  if(_la_molecola){
    _la_molecola->disegna();
  }
  
  switch(_action){

  case ACT_DRAW_ARROW:
    if(_b_arrow_added){
      fl_color(255,0,0);
      fl_line(_x_mouse,_y_mouse,Fl::event_x(),Fl::event_y());
    }
    break;
  case ACT_DRAW_SINGLE_BOND:
    if(!_b_bond_added){
      draw_preview_bond(ACT_DRAW_SINGLE_BOND);
    }
    break;

  case ACT_DRAW_DOUBLE_BOND:
    
    if(!_b_bond_added){
      draw_preview_bond(ACT_DRAW_SINGLE_BOND);
    }
    break;


  case ACT_DRAW_TRIPLE_BOND:
    
    if(!_b_bond_added){
      draw_preview_bond(ACT_DRAW_TRIPLE_BOND);
    }
    break;

  case ACT_DRAW_BEZIER:
    if(_bezier_point.size()<4){
      for(unsigned int i=0;i<_bezier_point.size();i++){
	draw_point(_bezier_point[i].first,_bezier_point[i].second);
      }
    }

    break;


  case ACT_DRAW_ARC:
    if(_arc_max_ax){
      draw_point(_x_arc_centr,_y_arc_centr);
      fl_color(COMP_R_EV,COMP_G_EV,COMP_B_EV);
      /*
       fl_arc(_x_arc_centr, _y_arc_centr, abs(_arc_max_ax), 
	      abs(_arc_min_ax), 0, 360); 
      */
      /*
        proc_arc* agg=new proc_arc(0,
			     xc-dx_scroll, yc+h/2-dy_scroll,
			     xc+w-dx_scroll, yc+h/2-dy_scroll,
			     xc-dx_scroll, yc-dy_scroll,
			     xc+w-dx_scroll,  yc-dy_scroll,
			     xc-dx_scroll, yc+h-dy_scroll,
			     xc+w-dx_scroll, yc+h-dy_scroll,
			     0, 0, 0 ,
			     0, 0, 0,
			     1, 0);
      */

        fl_begin_line();
	fl_curve(_x_arc_centr, _y_arc_centr+_arc_min_ax/2, 
		 _x_arc_centr, _y_arc_centr, 
		 _x_arc_centr+_arc_max_ax,_y_arc_centr,
		 _x_arc_centr+_arc_max_ax, _y_arc_centr+_arc_min_ax/2);
	fl_end_line();
	
	fl_begin_line();
	
	fl_curve(_x_arc_centr, _y_arc_centr+_arc_min_ax/2, 
		 _x_arc_centr, _y_arc_centr+_arc_min_ax, 
		 _x_arc_centr+_arc_max_ax,_y_arc_centr+_arc_min_ax,
		 _x_arc_centr+_arc_max_ax, _y_arc_centr+_arc_min_ax/2);
	
	fl_end_line();


    }
    break;

  case ACT_SEL_ATOM:
  case ACT_SEL_BOX:
    if(_b_construct_box){
      _la_molecola->elimina_elem_selected();
      _la_molecola->elimina_legami_selected();
      fl_color(COMP_R_EV,COMP_G_EV,COMP_B_EV);
      fl_loop(_x_mouse, _y_mouse, 
	      _x_mouse+(Fl::event_x()-_x_mouse), _y_mouse,
	      _x_mouse+(Fl::event_x()-_x_mouse), _y_mouse+(Fl::event_y()-_y_mouse),
	      _x_mouse, _y_mouse+(Fl::event_y()-_y_mouse));
    }
    break;

  case ACT_DRAW_BOX:
    if(_b_construct_box){
      _la_molecola->elimina_elem_selected();
      _la_molecola->elimina_legami_selected();
      fl_color(COMP_R_EV,COMP_G_EV,COMP_B_EV);
      fl_loop(_x_mouse, _y_mouse, 
	      _x_mouse+(Fl::event_x()-_x_mouse), _y_mouse,
	      _x_mouse+(Fl::event_x()-_x_mouse), _y_mouse+(Fl::event_y()-_y_mouse),
	      _x_mouse, _y_mouse+(Fl::event_y()-_y_mouse));
    }
    break;


  case ACT_ROTATE_SELECTED:
    _pivot_xpm.draw(_x_pivot-_pivot_xpm.w()/2, _y_pivot-_pivot_xpm.h()/2);
    break;

  default:
    break;
  }


}

int mol_canvas::handle(int e){

  if(plugin()!=0 && plugin()->time_to_act()){
    plugin()->act(e);
    return 1;
  }


  //  editor* ed=dynamic_cast<editor*>(MainWindow);
  //static float trx=10;
  //  static float trxm=0.5;
  //static float angl=0.1;
  switch(e){
  case FL_PASTE:

    //std::cerr << Fl::event_text() << std::endl;
    return 1;

  case FL_LEAVE:
    redraw();
    return 1;

  case FL_FOCUS:
    redraw();
    return 1;

  case FL_UNFOCUS:
    redraw();
    return 1;
      
  case FL_KEYDOWN:
    switch(Fl::event_key()){
      
    case FL_Up:
      switch(_action){
      case ACT_SCALE_SELECTED:
        {
          if(Fl::event_ctrl()){
            _la_molecola->scale_label_of_atom_selected(1.01);
          }else{
            _la_molecola->scala_selected(1.01);
          }
          redraw();
          break;
        }

      case ACT_ROTATE_SELECTED:
        _la_molecola->ruota_selected(-mol_canvas::rotation_incr/2 ,_x_pivot,_y_pivot);
        redraw();
        break;


      default:
        set_action_translate_selected_push_handle();
        _la_molecola->trasla_selected(0,-1);
        fl_cursor(FL_CURSOR_DEFAULT);
        redraw();
      }
      
      return 1;
    case FL_Down:
      switch(_action){

      case ACT_SCALE_SELECTED:
        {
          if(Fl::event_ctrl()){
            _la_molecola->scale_label_of_atom_selected(0.99);
          }else{
            _la_molecola->scala_selected(0.99);
          }
          redraw();
          break;
        }

      case ACT_ROTATE_SELECTED:
        _la_molecola->ruota_selected(mol_canvas::rotation_incr/2 ,_x_pivot,_y_pivot);
        redraw();
        break;

      default:
        set_action_translate_selected_push_handle();
        _la_molecola->trasla_selected(0,1);
        fl_cursor(FL_CURSOR_DEFAULT);
        redraw();
        break;
      }
      
      return 1;

    case FL_Left:
      switch(_action){
      default:
        {
          set_action_translate_selected_push_handle();
          _la_molecola->trasla_selected(-1,0);
          fl_cursor(FL_CURSOR_DEFAULT);
          redraw();
          break;
        }

      }
      
      return 1;


    case FL_Right:
      switch(_action){
      default:
        {
          set_action_translate_selected_push_handle();
          _la_molecola->trasla_selected(1,0);
          fl_cursor(FL_CURSOR_DEFAULT);
          redraw();
          break;
        }

      }
      
      return 1;
    case GUI_KEY_ZOOM:
      zoom_center_to_mousepointer(mol_canvas::zoom_incr);
      return 1;
    case GUI_KEY_UNZOOM:
      zoom_center_to_mousepointer(-mol_canvas::zoom_incr);
      return 1;
    case GUI_KEY_GLUE_MODE:
      {
	toggle_glue_mode();
	redraw();
      }
      return 1;

      //DEBUG
   
    //  case 'e':
    //    {
    //      try{
    //        gruppo ring=create_ring(__pref.getBond_fixedlength(), 3,true);
    //        ring.trasla(50,50);
    //        _la_molecola->aggiungi_gruppo(ring);
    //        redraw();
    //      }catch (out_of_range){
    //        std::cerr<< "eccezione" << std::endl;
    //      }
    //      //        _la_molecola->PROVA_ISOMORPH();
    //      //        //_la_molecola->trasla(trx,0);
    //      //        redraw();
    //    }
    //    return 1;
    //    break;	

    // case 'l':
      // {
      //         spectra_plot::plot_window p;
      //         p.add_spike(3000,50);
      //         p.add_group(_la_molecola->ritorna_gruppo(0),3000,50);
      //         p.show();
      //         while(p.shown()){
      //           Fl::wait();
      //         }
      //}
      //return 1;
    
      //case 'y':
       // for(int i=0;i<7;i++){
       //   add_bezier_along_circle(_la_molecola->find_group_id(0), 200+i*100, 200, 50, 0, M_PI - i/4);
       //   add_bezier_along_circle(_la_molecola->find_group_id(0), 200+i*100, 300, 20+i*50, 0, M_PI-i/2);
       // }

       // add_bezier_along_circle(_la_molecola->find_group_id(0), 400, 200, 100, 0, M_PI/2);
       // add_bezier_along_circle(_la_molecola->find_group_id(0), 200, 200, 100, deg2rad(100),deg2rad(160));
       // add_bezier_along_circle(_la_molecola->find_group_id(0), 200, 200, 100, deg2rad(0),deg2rad(180));
       // add_bezier_along_circle(_la_molecola->find_group_id(0), 400, 400, 50, deg2rad(0),deg2rad(180));
       // add_bezier_along_circle(_la_molecola->find_group_id(0), 500, 400, 50, deg2rad(0),deg2rad(90));
       //       redraw();
       //return 1;
//     case 'q':
//       _la_molecola->ruota(120,120,angl);
//       redraw();
//       return 1;
//       break;
//     case 'w':
//       _la_molecola->ruota(120,120,-angl);
//       redraw();
//       return 1;
//       break;			 
//     case 'i':
//       cout << "i pressed" << endl;
//       _la_molecola->PROVA_TRASLA_MULTILINE();
//       redraw();
//       return 1;
//     case 'r':
//       {
// 	int dx_scr=(MainWindow->ritorna_mol_canvas())->x();
// 	int dy_scr=(MainWindow->ritorna_mol_canvas())->y();
// 	_la_molecola->paste(Fl::event_x()-dx_scr,Fl::event_y()-dy_scr);
// 	redraw();
// 	return 1;
//       }
//     case 's':
//       {

// 	return 1;
//       }	

//     case 'd':
//       if(_la_molecola->prova_click_atomo(&_start_atom,Fl::event_x(),Fl::event_y())>=0){
// 	cout << "iio_start_atom " <<  _start_atom << endl;
	
//       }
      

//       {
	
// 	float alfa=__pref.getBond_fixedangle();
// 	float length=__pref.getBond_fixedlength();
// 	_x_mouse=Fl::event_x();
// 	_y_mouse=Fl::event_y();
// 	_x_added_atom=_x_mouse+length*cos(alfa);
// 	_y_added_atom=_y_mouse+length*sin(alfa);

// 	genera_catena(10,M_PI/2);
	
// 	// _la_molecola->scale(0.99);
// 	redraw();
// 	return 1;
//       }
 
//       
    default:
      return 0;
    }

  case FL_MOUSEWHEEL:
    if(Fl::event_dy()!=0){

      if(_action == ACT_SCALE_SELECTED){
	float incr=mol_canvas::scale_incr;
	if(Fl::event_ctrl()){
	  incr*=2;
	}
	_la_molecola->scala_selected(Fl::event_dy()>0 ? 1 + incr : 1 - incr);
	redraw();
	return 1;
	
      }else if(_action == ACT_ROTATE_SELECTED){
	float incr=mol_canvas::rotation_incr;
	if(Fl::event_ctrl()){
	  incr*=4;
	}
	
	_la_molecola->ruota_selected(Fl::event_dy()>0 ? incr : -incr,_x_pivot,_y_pivot);
	redraw();
	return 1;

      }else if(Fl::event_ctrl()   ||
	       _action== ACT_ZOOM ||
	       _action== ACT_UNZOOM){
	if(Fl::event_dy()>0){
	  zoom_center_to_mousepointer(-mol_canvas::zoom_incr);
	}else{
	  zoom_center_to_mousepointer(mol_canvas::zoom_incr);
	  return 1;
	}

      }else{
	return 0;
      }
    }else{ // if dy ==0
      return 0;
    }
    case FL_DRAG:
    switch(_action){

    case ACT_TRANSL_CANVAS:
      {

        int dx=Fl::event_x()-_x_mouse;
        int dy=Fl::event_y()-_y_mouse;
        _x_mouse=Fl::event_x();
        _y_mouse=Fl::event_y();
        translate(dx, dy);
        dynamic_cast<editor*>(MainWindow)->redraw();
      }



      return 1;
    case ACT_SEL_ATOM:
    case ACT_SEL_BOX:
      {
        
        
      }
      redraw();
      return 1;

    case ACT_DRAW_BOX:
      {
        
        
      }
      redraw();
      return 1;

      
    case ACT_SCALE_SELECTED:
      {
      float dy=Fl::event_y()-_y_mouse;
      _y_mouse=Fl::event_y();
      _la_molecola->scala_selected(dy>0 ? 1.02 : 0.98);
      redraw();
      return 1;
      }

    case ACT_ROTATE_SELECTED:
      {
	//float dx=Fl::event_x()-_x_mouse;
	int dy=static_cast<int>(rintf(Fl::event_y()-_y_mouse));
	//	int dx=static_cast<int>(rintf(Fl::event_x()-_x_mouse));
        float ang_rot=mol_canvas::rotation_incr;
	if(dy<-2){
	  ang_rot=-ang_rot;
	  _x_mouse=Fl::event_x();
	  _y_mouse=Fl::event_y();
	}else if (dy >= -2 && dy <=2) {
	  ang_rot=0;
	}else{
	  _x_mouse=Fl::event_x();
	  _y_mouse=Fl::event_y();
	}
	_la_molecola->ruota_selected( ang_rot,_x_pivot,_y_pivot);

	redraw();
	return 1;
      }
    case ACT_3D_ROT:
      {
      int dy=static_cast<int>(rintf(Fl::event_y()-_y_mouse));
      int dx=static_cast<int>(rintf(Fl::event_x()-_x_mouse));
      float ang_rot=-0.05;
      
      if(dy<-2){
	ang_rot=-ang_rot;
	_x_mouse=Fl::event_x();
	_y_mouse=Fl::event_y();
      }else if (dy >= -2 && dy <=2) {
	ang_rot=0;
      }else{
	_x_mouse=Fl::event_x();
	_y_mouse=Fl::event_y();
      }
      _la_molecola->rotate_selected_3d(true, ang_rot);
      
      ang_rot=-0.05;
      if(dx<-2){
	ang_rot=-ang_rot;
	_x_mouse=Fl::event_x();
	_y_mouse=Fl::event_y();
      }else if (dx >= -2 && dx <=2) {
	ang_rot=0;
      }else{
	_x_mouse=Fl::event_x();
	_y_mouse=Fl::event_y();
      }
      
      _la_molecola->rotate_selected_3d(false, ang_rot);
      
      redraw();
      return 1;
      }
    case ACT_TRANSLATE_SELECTED:
      {
	
	int dx=Fl::event_x()-_x_mouse;
	int dy=Fl::event_y()-_y_mouse;
	_x_mouse=Fl::event_x();
	_y_mouse=Fl::event_y();
	_la_molecola->trasla_selected(dx,dy);
	

        if(glue_mode()){
	  
          test_and_glue_objects();
        }

	redraw();
	return 1;
      }
    case ACT_DRAW_SINGLE_BOND:
    case ACT_DRAW_DOUBLE_BOND:
    case ACT_DRAW_TRIPLE_BOND:
      if(_la_molecola->prova_click_atomo(&_end_atom,Fl::event_x(),Fl::event_y())<0 ){
	_la_molecola->elimina_elem_selected();
	_la_molecola->elimina_legami_selected();
	_end_atom=0;
      }


      redraw();
     return 1;

    case ACT_DRAW_ARROW:
      redraw();
      return 1;
      

    case ACT_DRAW_ARC:
      {
	_arc_max_ax=Fl::event_x()-_x_arc_centr;
	_arc_min_ax=Fl::event_y()-_y_arc_centr;
	redraw();
	return 1;
      }

    case ACT_EDIT_CONTROL_POINT_CURVES:
      {
        
        int dx=Fl::event_x()-_x_mouse;
        int dy=Fl::event_y()-_y_mouse;
        _x_mouse=Fl::event_x();
        _y_mouse=Fl::event_y();
        _la_molecola->translate_control_points(dx, dy);
        redraw();
      }
      return 1;
    }
    
 
  case FL_RELEASE:

    switch(_action){
    case ACT_TRANSL_CANVAS:
      _action=ACT_SEL_ATOM;
      break;
    case ACT_SEL_ATOM:
      if(_b_construct_box){
	_b_construct_box=false;
        
	_la_molecola->aggiungi_se_dentro_bb(_x_mouse, _y_mouse, 
					    Fl::event_x()-_x_mouse , 
					    Fl::event_y()-_y_mouse);
      }
      break;
    case ACT_SEL_BOX:
      {
        int lux=(_x_mouse < Fl::event_x() ? _x_mouse : Fl::event_x());
        int luy=(_y_mouse < Fl::event_y() ? _y_mouse : Fl::event_y());
        int rbx=(_x_mouse > Fl::event_x() ? _x_mouse : Fl::event_x());
        int rby=(_y_mouse > Fl::event_y() ? _y_mouse : Fl::event_y());

        int w=rbx - lux;
        int h=rby - luy;
        
        _la_molecola->aggiungi_se_dentro_bb(lux, luy, w, h);

        _b_construct_box=false;
        _action=ACT_SEL_ATOM;
      }
      return 1;

    case ACT_DRAW_BOX:
      {
        if(_b_construct_box){
          reg_modified();
          int lux=(_x_mouse < Fl::event_x() ? _x_mouse : Fl::event_x());
          int luy=(_y_mouse < Fl::event_y() ? _y_mouse : Fl::event_y());
          int rbx=(_x_mouse > Fl::event_x() ? _x_mouse : Fl::event_x());
          int rby=(_y_mouse > Fl::event_y() ? _y_mouse : Fl::event_y());
          attract_mouse_to_magnetic_point(&lux,&luy);
          attract_mouse_to_magnetic_point(&rbx,&rby);
          _la_molecola->create_new_box(lux, luy, rbx, rby);
        }
        _b_construct_box=false;
      }
      return 1;
    

    case ACT_TRANSLATE_SELECTED:
      {
        fl_cursor(FL_CURSOR_DEFAULT);
        _x_mouse=0;
        _y_mouse=0;
        editor* ed=dynamic_cast<editor*>(MainWindow);
        _action=ed->get_button_value_as_action();
        //_action=ACT_SEL_ATOM;
      }
      break;
    case ACT_DRAW_SINGLE_BOND:
      if(_x_mouse>0 && 
         _y_mouse>0){
        return aggiungi_nuovo_legame(LEGAME_SINGOLO);
      }else{
        return 1;
      }
    case ACT_DRAW_DOUBLE_BOND:
      if(_x_mouse>0 && 
         _y_mouse>0){
        return aggiungi_nuovo_legame(LEGAME_DOPPIO);
      }else{
        return 1;
      }
    case ACT_DRAW_TRIPLE_BOND:
      if(_x_mouse>0 && 
         _y_mouse>0){
        return aggiungi_nuovo_legame(LEGAME_TRIPLO);
      }else{
        return 1;
      }
    case ACT_DRAW_ARROW:
      if(_b_arrow_added){
	reg_modified();
	int mag_x=Fl::event_x();
	int mag_y=Fl::event_y();
	//testing magnetic
	attract_mouse_to_magnetic_point(&mag_x,&mag_y);

	_la_molecola->crea_freccia_nuova(_x_mouse, _y_mouse,
					 mag_x,mag_y);
	_b_arrow_added=false;
      }
      
      return 1;
    case ACT_DRAW_ARC:
      if(_arc_max_ax){
	reg_modified();
	_la_molecola->crea_ellisse_nuova(_x_arc_centr,_y_arc_centr, _arc_max_ax, _arc_min_ax);
	_arc_max_ax=0;
	redraw();
      }
      return 1;
    case ACT_ROTATE_SELECTED:
      fl_cursor(FL_CURSOR_DEFAULT);
      return 1;
    case ACT_EDIT_CONTROL_POINT_CURVES:
      _la_molecola->unset_selected_control_points();
      _action=ACT_SEL_ATOM;
      return 1;
    }

    return 1;


  case FL_PUSH:
    {
     
        /*
        _la_molecola->PROVA_TRASLA_MULTILINE();
        return 1;
        */
        if(action()==ACT_NOTHING){
          return 0;
        }
      
        if(Fl::event_button()==FL_RIGHT_MOUSE){
          reg_modified();
          int fl_event_x=Fl::event_x();
	  int fl_event_y=Fl::event_y();

	  if(!_la_molecola->cambia_prop_atomo(fl_event_x, fl_event_y)){
	     _la_molecola->cambia_prop_legami(fl_event_x, fl_event_y);
	  } 

	  if(_la_molecola->cambia_prop_bezier(fl_event_x, fl_event_y)){
	   
          }else if(_la_molecola->cambia_prop_frecce(fl_event_x, fl_event_y)){
	  
          }else if(_la_molecola->cambia_prop_arc(fl_event_x, fl_event_y)){

          }else if(_la_molecola->change_prop_box(fl_event_x, fl_event_y)){

          }else if(_la_molecola->cambia_prop_etichetta(fl_event_x, fl_event_y)){
	  
          }else{

          }

        }else if(Fl::event_button()==FL_MIDDLE_MOUSE){
          switch(_action){
          case ACT_SCALE_SELECTED:
            _x_mouse=Fl::event_x();
            _y_mouse=Fl::event_y();
            return 1;

          case ACT_ROTATE_SELECTED:
            _x_pivot=Fl::event_x();
            _y_pivot=Fl::event_y();
            redraw();
            return 1;
	  case ACT_FLIP_VER:
	    _la_molecola->copy_flip(Fl::event_x(),Fl::event_y(),false);
	    return 1;
	    
	  case ACT_FLIP_HOR:
	    _la_molecola->copy_flip(Fl::event_x(),Fl::event_y());
	    return 1;
          }
        }else{ // left mouse button pressed
          //editor* ed=dynamic_cast<editor*>(MainWindow);
          
          if(Fl::event_key(FL_Shift_L)){
            _action=ACT_TRANSL_CANVAS;
            _x_mouse=Fl::event_x();
            _y_mouse=Fl::event_y();
            redraw();
            
          }else{
            switch(_action){
            case ACT_ZOOM:
	      zoom_center_to_mousepointer(mol_canvas::zoom_incr);
              return 1;
	    case ACT_UNZOOM:
	      zoom_center_to_mousepointer(-mol_canvas::zoom_incr);
              return 1;

            case ACT_FLIP_VER:
              _la_molecola->flip(Fl::event_x(),Fl::event_y(),false);
              return 1;

            case ACT_FLIP_HOR:
              _la_molecola->flip(Fl::event_x(),Fl::event_y());
              return 1;
            case ACT_PASTE:
              {
                reg_modified();
                int dx_scr=(MainWindow->ritorna_mol_canvas())->x();
                int dy_scr=(MainWindow->ritorna_mol_canvas())->y();
                _la_molecola->paste(Fl::event_x()-dx_scr,Fl::event_y()-dy_scr);
                redraw();
              }
              return 1;	  
            case ACT_DRAW_CHAIN:
              {
                if(_num_atom_chain>1){
                  reg_modified();
                  /*
                    int dx=(MainWindow->ritorna_mol_canvas())->x();
                    int dy=(MainWindow->ritorna_mol_canvas())->y();
                  */
                  if(_la_molecola->prova_click_atomo(&_start_atom,Fl::event_x(),Fl::event_y())>=0){
                    
                    //cout << "_start_atom " <<  _start_atom << endl;
                  }else{
                    float alfa=__pref.getBond_fixedangle();
                    float length=scale_z(__pref.getBond_fixedlength()); //*__pref.getZoom();
                    _x_mouse=Fl::event_x();
                    _y_mouse=Fl::event_y();

                    //testing magnetic
                    attract_mouse_to_magnetic_point(&_x_mouse,&_y_mouse);
		
                    _x_added_atom=static_cast<int>(rintf(_x_mouse+length*cos(alfa)));
                    _y_added_atom=static_cast<int>(rintf(_y_mouse+length*sin(alfa)));
		
                  }
                  genera_catena(_num_atom_chain,_orient_chain);
                  redraw();
                }
                return 1;
              }

            case ACT_FIXED_ROTATION:
              reg_modified();
              _x_pivot=Fl::event_x();
              _y_pivot=Fl::event_y();
              _la_molecola->ruota_selected(_fixed_rotation_degree,_x_pivot,_y_pivot);
              redraw();
              return 1;

            case ACT_DRAW_ORB:
              {
                reg_modified();
                int cntx=Fl::event_x();
                int cnty=Fl::event_y();

	    

                //testing magnetic
                attract_mouse_to_magnetic_point(&cntx,&cnty);

                float wo=scale_z(10);
                float ho=scale_z(20);
                vector< pair<float,float> > punti;
                pair<float,float> primo(cntx,cnty);
                punti.push_back(primo);

                primo.first=cntx-wo;
                primo.second=cnty+ho;
                punti.push_back(primo);

                primo.first=cntx+wo;
                primo.second=cnty+ho;
                punti.push_back(primo);

                primo.first=cntx+0.001;
                primo.second=cnty;
                punti.push_back(primo);

	    
                _la_molecola->crea_bezier_nuova(punti);

                punti[1].second=cnty-ho;
                punti[2].second=cnty-ho;

                _la_molecola->crea_bezier_nuova(punti);

                redraw();
                return 1;
              }
            case ACT_SCALE_SELECTED:
              reg_modified();
              return 1;
	  
            case ACT_ROTATE_SELECTED:
              fl_cursor(FL_CURSOR_NS);
              _x_mouse=Fl::event_x();
              _y_mouse=Fl::event_y();
              reg_modified();
              return 1;

            case ACT_TRANSLATE_SELECTED:
              set_action_translate_selected_push_handle();
              reg_modified();
              return 1;
            case ACT_DRAW_SINGLE_BOND:
            case ACT_DRAW_DOUBLE_BOND:
            case ACT_DRAW_TRIPLE_BOND:
              {
                reg_modified();
                int dx=(MainWindow->ritorna_mol_canvas())->x();
                int dy=(MainWindow->ritorna_mol_canvas())->y();
                _b_bond_added=false;
                if(_la_molecola->prova_click_atomo(&_start_atom,Fl::event_x(),Fl::event_y())>=0){
                  //cout << "_start_atom " <<  _start_atom << endl;
                  _y_mouse=static_cast<int>(rintf(_start_atom->pos_y()+dy));
                  _x_mouse=static_cast<int>(rintf(_start_atom->pos_x()+dx));
                }else{
                  int x=Fl::event_x();
                  int y=Fl::event_y();
                  bool exists=false;
                  if(!_la_molecola->check_click_bond(x,y,exists,true)){    
                    _x_mouse=Fl::event_x();
                    _y_mouse=Fl::event_y();
                    
                    //testing magnetic
                    attract_mouse_to_magnetic_point(&_x_mouse,&_y_mouse);
                  }else{
                    _x_mouse=-1;
                    _y_mouse=-1;
                    

                  }
                }
                
                redraw();
              }
              return 1;

            case ACT_DRAW_ARROW:
              _x_mouse=Fl::event_x();
              _y_mouse=Fl::event_y();
              //testing magnetic
              attract_mouse_to_magnetic_point(&_x_mouse,&_y_mouse);
              _b_arrow_added=true;
              return 1;

            case ACT_DRAW_BEZIER:
              //	  cout << "_bezier_point " << _bezier_point.size() << endl;
              if(_bezier_point.size()<3){
                //cout << "kk"<< endl;
                pair<float,float> punti;
                int mag_x=Fl::event_x();
                int mag_y=Fl::event_y();
                //testing magnetic
                attract_mouse_to_magnetic_point(&mag_x,&mag_y);
	    
                punti.first=mag_x;
                punti.second=mag_y;
                _bezier_point.push_back(punti);
              }else{
                reg_modified();
                pair<float,float> punti;

                int mag_x=Fl::event_x();
                int mag_y=Fl::event_y();
                //testing magnetic
                attract_mouse_to_magnetic_point(&mag_x,&mag_y);
	    
                punti.first=mag_x;
                punti.second=mag_y;

                _bezier_point.push_back(punti);
                _la_molecola->crea_bezier_nuova(_bezier_point);
                _bezier_point.erase(_bezier_point.begin(),_bezier_point.end());

              }
              redraw();
              return 1;

            case ACT_DRAW_ARC:
              {
                int mag_x=Fl::event_x();
                int mag_y=Fl::event_y();
                //testing magnetic
                attract_mouse_to_magnetic_point(&mag_x,&mag_y);
                _x_arc_centr=mag_x;
                _y_arc_centr=mag_y;
              }
              return 1;
	  
            case ACT_DRAW_ETICH:
              {
                reg_modified();
                int dx=(MainWindow->ritorna_mol_canvas())->x();
                int dy=(MainWindow->ritorna_mol_canvas())->y();
                int mag_x=Fl::event_x();
                int mag_y=Fl::event_y();
                //testing magnetic
                attract_mouse_to_magnetic_point(&mag_x,&mag_y);
	    

                //etichetta* dummy=new multifont_label();
                //etichetta* dummy=new multiline_label();
                etichetta* dummy=new paragraph_text;
                dummy->x(descale(mag_x-dx));
                dummy->y(descale(mag_y-dy));
                _la_molecola->elimina_legami_selected();
                _la_molecola->elimina_elem_selected();

                _la_molecola->add_etich(dummy);
                _la_molecola->aggiungi_elem_selected(ETICHETTA,NO_VALID_GROUP,
                                                     _la_molecola->numero_etichetta()-1);
                _la_molecola->highlight_selected();
                //multiline_label_prop p(_la_molecola->ritorna_punt_etich(_la_molecola->numero_etichetta()-1) );

                paragraph_text_prop p(_la_molecola->ritorna_punt_etich(_la_molecola->numero_etichetta()-1) );
                p.show();
                while(p.shown()){
                  Fl::wait();
                }

                _la_molecola->elimina_legami_selected();
                _la_molecola->elimina_elem_selected();
                break;
              }
              return 1;
            case ACT_DRAW_BOX:
              
              _x_mouse=Fl::event_x();
              _y_mouse=Fl::event_y();
              _b_construct_box=true;
              return 1;


            case ACT_SEL_BOX:
              _x_mouse=Fl::event_x();
              _y_mouse=Fl::event_y();
              _b_construct_box=true;
              return 1;
	  
            case ACT_SEL_ATOM:
              {
		if(Fl::event_clicks()==1 && Fl::event_button()==FL_LEFT_MOUSE){
		  if(d_click_bond()){
		    Fl::event_is_click(0);
		  }
		  
		}else{
		  bool has_hitted=false;
		  bool no_incremental_sel=true;
		  bool exists;

		  if(_la_molecola->check_control_point_procedura_under_mouse(Fl::event_x(), 
									     Fl::event_y())){ 
		    // procedura control points editing
		    
		    //fl_cursor(FL_CURSOR_MOVE);
		    _x_mouse=Fl::event_x();
		    _y_mouse=Fl::event_y();
		    reg_modified();
		    
		    _action=ACT_EDIT_CONTROL_POINT_CURVES;
		  }else{
		    if(_la_molecola->check_exists_in_elem_selected(Fl::event_x(), 
								   Fl::event_y(),exists)){
		      set_action_translate_selected_push_handle();
		    }else{
		      
		      if(Fl::event_key(FL_Control_L)){
			no_incremental_sel=false;
		      }
		      
		      has_hitted=_la_molecola->prova_click(Fl::event_x(), 
							   Fl::event_y(),
							   exists,
							   no_incremental_sel);
		      
		      
		      if(!has_hitted){
			_x_mouse=Fl::event_x();
			_y_mouse=Fl::event_y();
			_b_construct_box=true;
                      _action=ACT_SEL_BOX;
		      }
		    }
		  }
                }
		  break;
              }
            case ACT_SEL_GROUP:
              {
                bool exists=true;
                if(_la_molecola->check_exists_in_elem_selected(Fl::event_x(), 
                                                               Fl::event_y(),exists)){
                  set_action_translate_selected_push_handle();
                }else{
                  bool incremental=false;

                  if(Fl::event_key(FL_Control_L)){
                    incremental=true;
                  }
                  
                  if(!_la_molecola->click_gruppo(Fl::event_x(), 
                                                 Fl::event_y(), !incremental)){
                    _la_molecola->check_click_etichetta(Fl::event_x(),
                                                        Fl::event_y(),exists, !incremental);
                  }
                }
              }
              return 1;
            case ACT_KILL:
              reg_modified();
              bool dummy;
              _la_molecola->prova_click(Fl::event_x(), 
                                        Fl::event_y(),
                                        dummy,true);
	  
              _la_molecola->cancella_elementi_selected();
              _la_molecola->elimina_elem_selected();
              _la_molecola->elimina_legami_selected();
	  
            }
            return 1;
          }
          return 1;
        }
      
    }
  default:
    return Fl_Widget::handle(e);
    break;
   
  }
}



void mol_canvas::test_and_glue_objects(){
  atomo* sel_1=NULL;
  atomo* sel_2=NULL;
  atomo* hook_1=NULL;
  atomo* hook_2=NULL;

  

  if(_la_molecola->check_selected_group_bond_coincidence(&sel_1 , &sel_2,
                                                         &hook_1, &hook_2)){
    if(sel_1!=NULL && sel_2!=NULL && hook_1!=NULL && hook_2!=NULL){
      glue_bonds(sel_1,sel_2,hook_1,hook_2);
      redraw();
    }
  }else if(_la_molecola->check_selected_group_atom_coincidence(&sel_1, &hook_1)){

    if(sel_1!=NULL && hook_1!=NULL){ //found hook
      glue_vertices(sel_1,hook_1);
      redraw();
    }
  }

}


void mol_canvas::glue_bonds(atomo* sel_1,atomo* sel_2,
			    atomo* hook_1,atomo* hook_2){
    
    _la_molecola->elimina_elem_selected();
    _la_molecola->elimina_legami_selected();
    
    std::pair<float,float> v_sel_1(sel_1->pos_x(),
				   sel_1->pos_y());

    std::pair<float,float> v_sel_2(sel_2->pos_x(),
				   sel_2->pos_y());

    std::pair<float,float> v_hook_1(hook_1->pos_x(),
				    hook_1->pos_y());

    std::pair<float,float> v_hook_2(hook_2->pos_x(),
				    hook_2->pos_y());

    std::pair<float,float> l1=bidimensional_vector::diff(v_sel_1,v_sel_2);
    std::pair<float,float> l2=bidimensional_vector::diff(v_hook_1,v_hook_2);

    float scale_f=bidimensional_vector::magn(l2)/bidimensional_vector::magn(l1);

    float dprod=bidimensional_vector::dot_product(l1,l2);

    if(dprod<0){
      std::swap(sel_1,sel_2);
    }
    
    sel_1->etich(hook_1->etich());
    sel_2->etich(hook_2->etich());


    gruppo* sel_grp=dynamic_cast<gruppo*>(sel_1->ritorna_genitore());
    gruppo* hook_grp=dynamic_cast<gruppo*>(hook_1->ritorna_genitore());
    sel_grp->scale(scale_f);

    int sel_grp_id =sel_grp->id();
    int hook_grp_id=hook_grp->id();
    

    hook_grp->rimappa_da((*(sel_grp->fin_atom()-1)).id()+1,0);


   
    //translate
    float dx_sel_1=hook_1->pos_x() - sel_1->pos_x();
    float dy_sel_1=hook_1->pos_y() - sel_1->pos_y();
    sel_grp->trasla(dx_sel_1, dy_sel_1);
    

    std::vector<int> first_neighbors_hook_1;
    std::vector<int> first_neighbors_bond_type_hook_1;

    vector<legame>::iterator beg_b=hook_1->primo_leg();
    vector<legame>::iterator end_b=hook_1->ultimo_leg();
    while(beg_b!=end_b){

      if((*beg_b).id_atomo()!=hook_2->id()){
	first_neighbors_hook_1.push_back((*beg_b).id_atomo());
	first_neighbors_bond_type_hook_1.push_back((*beg_b).tipo_legame());
      }
      beg_b++;
      
    }

    std::vector<int> first_neighbors_hook_2;
    std::vector<int> first_neighbors_bond_type_hook_2;

    beg_b=hook_2->primo_leg();
    end_b=hook_2->ultimo_leg();


    
    while(beg_b!=end_b){
      if((*beg_b).id_atomo()!=hook_1->id()){
	first_neighbors_hook_2.push_back((*beg_b).id_atomo());
	first_neighbors_bond_type_hook_2.push_back((*beg_b).tipo_legame());
      }

      beg_b++;

    }

    std::vector<GruppoLink> links;

    for(unsigned int i=0;i<first_neighbors_hook_1.size();i++){
      GruppoLink tmp;
      tmp._first=sel_1->id();
      tmp._second=first_neighbors_hook_1[i];
      tmp._bondtype=first_neighbors_bond_type_hook_1[i];
      links.push_back(tmp);
    }


    for(unsigned int i=0;i<first_neighbors_hook_2.size();i++){
      GruppoLink tmp;
      tmp._first=sel_2->id();
      tmp._second=first_neighbors_hook_2[i];
      tmp._bondtype=first_neighbors_bond_type_hook_2[i];
      links.push_back(tmp);
    }
    
    

    int h_id1=hook_1->id();
    int h_id2=hook_2->id();


    gruppo g_linked=link_groups(sel_grp, hook_grp,links);
    g_linked.purge_atom(h_id1);
    g_linked.purge_atom(h_id2);

    g_linked.rimappa_da(0,0);
    _la_molecola->aggiungi_gruppo(g_linked);
    _la_molecola->remove_gruppo_id(sel_grp_id);
    _la_molecola->remove_gruppo_id(hook_grp_id);


}
void mol_canvas::glue_vertices(atomo* sel, atomo* hook){


    _la_molecola->elimina_elem_selected();
    _la_molecola->elimina_legami_selected();
    sel->etich(hook->etich());
    
    gruppo* sel_grp=dynamic_cast<gruppo*>(sel->ritorna_genitore());
    gruppo* hook_grp=dynamic_cast<gruppo*>(hook->ritorna_genitore());
    int sel_grp_id=sel_grp->id();
    int hook_grp_id=hook_grp->id();
    
    
    hook_grp->rimappa_da((*(sel_grp->fin_atom()-1)).id()+1,hook->id());

    float dx_sel=hook->pos_x() - sel->pos_x();
    float dy_sel=hook->pos_y() - sel->pos_y();
    sel_grp->trasla(dx_sel, dy_sel);
    std::vector<int> first_neighbors_hook;
    std::vector<int> first_neighbors_bond_type;

    vector<legame>::iterator beg_b=hook->primo_leg();
    vector<legame>::iterator end_b=hook->ultimo_leg();

    while(beg_b!=end_b){
      first_neighbors_hook.push_back((*beg_b).id_atomo());
      first_neighbors_bond_type.push_back((*beg_b).tipo_legame());
      beg_b++;
      
    }


    std::vector<GruppoLink> links;

    for(unsigned int i=0;i<first_neighbors_hook.size();i++){
      GruppoLink tmp;
      tmp._first=sel->id();
      tmp._second=first_neighbors_hook[i];
      tmp._bondtype=first_neighbors_bond_type[i];
      links.push_back(tmp);
    }

    int h_id=hook->id();


    // for(unsigned int i=0;i<links.size();i++){
    //   std::cerr << links[i]._first << " con " << links[i]._second << std::endl;
    // }


    gruppo g_linked=link_groups(sel_grp, hook_grp,links);
    
    //g_linked.trasla(100,100);
    g_linked.purge_atom(h_id);


    g_linked.rimappa_da(0,0);

    _la_molecola->aggiungi_gruppo(g_linked);
    _la_molecola->remove_gruppo_id(sel_grp_id);
    _la_molecola->remove_gruppo_id(hook_grp_id);

}



void mol_canvas::draw_preview_bond(int tip){
  
  //#define LENGHT_BOND 15.0f
  
  /**
   *Angolo legame in radianti
   */
  
  //#define ANGL_BOND  .26179938779914943653f

  fl_color(COMP_R_EV,COMP_G_EV,COMP_B_EV);
  float length=static_cast<float>(__pref.getBond_fixedlength() * __pref.getZoom()); //LENGHT_BOND;
  float angl=static_cast<float>(__pref.getBond_fixedangle()); //ANGL_BOND;


  
  switch(tip){
  case ACT_DRAW_DOUBLE_BOND:
  case ACT_DRAW_SINGLE_BOND:
  case ACT_DRAW_TRIPLE_BOND:
    {
      

      std::vector<int> pos_calc=preview_bond_calc_w_springs(_x_mouse, 
                                                            _y_mouse);

      if(pos_calc.size()==4 && 
         similar_to<int>(Fl::event_y()-_y_mouse,0,__pref.get_sensib_leg()) && 
         similar_to<int>(Fl::event_x()-_x_mouse ,0,__pref.get_sensib_leg())){
        int dx=(MainWindow->ritorna_mol_canvas())->x();
        int dy=(MainWindow->ritorna_mol_canvas())->y();
        _x_added_atom=pos_calc[2]+dx;
        _y_added_atom=pos_calc[3]+dy;
	fl_line(pos_calc[0]+dx, pos_calc[1]+dy, pos_calc[2]+dx, pos_calc[3]+dy);


      }else{
        float alfa_l=atan2(static_cast<float>(Fl::event_y()-_y_mouse),
                           static_cast<float>(Fl::event_x()-_x_mouse)
                           );
        int alfa_i=static_cast<int>(rintf(alfa_l/angl));
        
        alfa_l=alfa_i*angl;
        _x_added_atom=static_cast<int>(_x_mouse+rintf(length*cos(alfa_l)));
        _y_added_atom=static_cast<int>(_y_mouse+rintf(length*sin(alfa_l)));
        
        if(_end_atom==0){
          fl_line(_x_mouse, _y_mouse, _x_added_atom, _y_added_atom);
        }else{
          int dx_scr=(MainWindow->ritorna_mol_canvas())->x();
          int dy_scr=(MainWindow->ritorna_mol_canvas())->y();
          fl_line(_x_mouse, _y_mouse, 
                  static_cast<int>(rintf(_end_atom->pos_x()+dx_scr)),
                  static_cast<int>(rintf(_end_atom->pos_y()+dy_scr)));
        }
      }
      break;
    }
  }
  
}


void mol_canvas::genera_catena(unsigned int n_carb, float orient){
  _la_molecola->elimina_elem_selected();
  _la_molecola->elimina_legami_selected();  

  //  cout << "iio" << _start_atom << endl;
  float alfa=__pref.getBond_fixedangle();
  float length=scale_z(__pref.getBond_fixedlength());

  if(_start_atom){
  
    bool sopra=true;
    float xpiv=_start_atom->pos_x();
    float ypiv=_start_atom->pos_y();
    float x_addtmp= static_cast<int>(rintf(_start_atom->pos_x()));
    float y_addtmp= static_cast<int>(rintf(_start_atom->pos_y()));

    
    for(unsigned int i=0;i<n_carb;i++){
      x_addtmp+=static_cast<int>(length*cos(alfa));
      y_addtmp+=static_cast<int>(length*sin(alfa));

      float x=x_addtmp-xpiv;
      float y=y_addtmp-ypiv;
      float xp=x*cos(orient)+y*sin(orient);
      float yp=y*cos(orient)-x*sin(orient);
      
      _x_added_atom=static_cast<int>(rintf(xp+xpiv));
      _y_added_atom=static_cast<int>(rintf(yp+ypiv));

      
      if(sopra){
	alfa-=__pref.getBond_fixedangle()*2;
	sopra=false;
      }else{
	alfa+=__pref.getBond_fixedangle()*2;
	sopra=true;
      }


      _start_atom=_la_molecola->crea_legame_nuovo(_start_atom, 
						  _x_added_atom, 
						  _y_added_atom,  
						  LEGAME_SINGOLO);
    }
    _start_atom=0;
  }else{

    float x= _x_added_atom-_x_mouse;
    float y=_y_added_atom-_y_mouse;
    float xp=x*cos(orient+alfa*2)+y*sin(orient+alfa*2);
    float yp=y*cos(orient+alfa*2)-x*sin(orient+alfa*2);
    
    _x_added_atom=static_cast<int>(rintf(xp+_x_mouse));
    _y_added_atom=static_cast<int>(rintf(yp+_y_mouse));
    
    
    _start_atom=_la_molecola->crea_legame_nuovo(_x_mouse, _y_mouse, 
						_x_added_atom, _y_added_atom, 
						LEGAME_SINGOLO);
    genera_catena(n_carb-2, orient);
  }

}




int mol_canvas::aggiungi_nuovo_legame(int tipo){

  if(!_b_bond_added){
    _la_molecola->elimina_elem_selected();
    _la_molecola->elimina_legami_selected();
    //float dx=Fl::event_x()-_x_mouse;
    //float dy=Fl::event_y()-_y_mouse;
    int dx_scr=(MainWindow->ritorna_mol_canvas())->x();
    int dy_scr=(MainWindow->ritorna_mol_canvas())->y();
    //float lung_att=sqrt( pow(static_cast<float>(dx),2)+
    //			 pow(static_cast<float>(dy),2)  );
    //float length=static_cast<float>(__pref.getBond_fixedlength()); //LENGHT_BOND;
	
    if(_start_atom){
      if(_end_atom){
	_la_molecola->crea_legame_nuovo(_start_atom, _end_atom, tipo);
      }else{
	_la_molecola->crea_legame_nuovo(_start_atom, 
					_x_added_atom-dx_scr, _y_added_atom-dy_scr,  
					tipo); 
      }
    }else{
      if(_end_atom){
	_la_molecola->crea_legame_nuovo(_end_atom, 
					_x_mouse-dx_scr, _y_mouse-dy_scr,  
					tipo); 
      }else{
	_la_molecola->crea_legame_nuovo(_x_mouse, _y_mouse, 
					_x_added_atom, _y_added_atom, tipo);
      }
    }
    _start_atom=0;
    _end_atom=0;
    _b_bond_added=true;
    redraw();
  }
  return 1;


}


void mol_canvas::reg_modified(){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  //_la_molecola->elimina_elem_selected();
  //_la_molecola->elimina_legami_selected();
  ed->register_images_undo(_la_molecola);
  _la_molecola=MainWindow->ritorna_immagine();
}


bist_plugin* mol_canvas::plugin(){
  editor* ed=dynamic_cast<editor*>(MainWindow);
  if(ed!=0){
    return ed->actual_plugin();
  }else{
    return 0;
  }
  
}

void mol_canvas::zoom(float entity,int traslx, int trasly){
  float nwzoom=__pref.getZoom()+entity;
   if(nwzoom>0 && 
      static_cast<int>(rintf(__pref.getPageWidth()*nwzoom)) > 30 &&
      static_cast<int>(rintf(__pref.getPageHeight()*nwzoom)) > 30){
     __pref.setZoom(__pref.getZoom()+entity);
  
     resize(x(),y(),
	    static_cast<int>(rintf(__pref.getPageWidth()*__pref.getZoom())),
	    static_cast<int>(rintf(__pref.getPageHeight()*__pref.getZoom())));
     
    //if(w() > parent()->w() || h() > parent()->h()){
     position(x()+traslx,y()+trasly);
      //}else{
      //position(parent()->x(),parent()->y());
      //}
  
    redraw();
    parent()->redraw();
   }
}


void mol_canvas::zoom_center_to_mousepointer(float entity){
  float x_t=(Fl::event_x()-x());
  float y_t=(Fl::event_y()-y());
  float x_t_z_offset=(Fl::event_x()-x())*abs(entity)/__pref.getZoom();
  float y_t_z_offset=(Fl::event_y()-y())*abs(entity)/__pref.getZoom();
  zoom(entity,
       static_cast<int>(rintf(x_t)),
       static_cast<int>(rintf(y_t)));
  if(entity<0){
    position(static_cast<int>(rintf(x()+x_t_z_offset-x_t)),
	     static_cast<int>(rintf(y()+y_t_z_offset-y_t)));
  }else{
    position(static_cast<int>(rintf(x()-x_t_z_offset- x_t)),
	     static_cast<int>(rintf(y()-y_t_z_offset- y_t)));
  }
  parent()->redraw();
}

void mol_canvas::set_action_translate_selected_push_handle(){
  fl_cursor(FL_CURSOR_MOVE);
  _x_mouse=Fl::event_x();
  _y_mouse=Fl::event_y();
  reg_modified();
  _action=ACT_TRANSLATE_SELECTED;
}



bool mol_canvas::d_click_atom(){
  atomo* clicked=NULL;
  int res= _la_molecola->prova_click_atomo(&clicked,Fl::event_x(), Fl::event_y());

  if(clicked!=NULL){
    std::vector<atomo*> children=clicked->get_all_children();
    if(children.size()>1){
      bidimensional_vinculated_particle b;
      b.k_spring(10);
      pair<float,float> center(clicked->pos_x(),
                               clicked->pos_y());
      b.add_center(center);
      for(unsigned int i=0;i<children.size();i++){
        pair<float,float> tmp(children[i]->pos_x(),children[i]->pos_y());
        b.add_particle(tmp);
      }
      std::vector<float> start_position;
      start_position.push_back(children[0]->pos_x());
      start_position.push_back(children[0]->pos_y());
      
      b.pos(start_position);
      std::vector<float> pp=b.pos();
    
      atomo* nw_atm=_la_molecola->crea_legame_nuovo(clicked,pp[0], 
                                                    pp[1], LEGAME_SINGOLO);
      
      while(b.update()){
        redraw();
        Fl::check();
        pp=b.pos();
        nw_atm->pos_x(static_cast<int>(rintf(pp[0])));
        nw_atm->pos_y(static_cast<int>(rintf(pp[1])));
        
      }
    
      
    }
  }
 
  return res;
}


bool  mol_canvas::d_click_bond(){
  bool res=false;
  reg_modified();
  bool dummy;
  _la_molecola->elimina_elem_selected();
  _la_molecola->elimina_legami_selected();

  res=_la_molecola->check_click_bond(Fl::event_x(), Fl::event_y(), dummy, true);

  _la_molecola->shift_type_bond_selected();

  _la_molecola->elimina_elem_selected();
  _la_molecola->elimina_legami_selected();
  return res;
}


void mol_canvas::translate(int dx,int dy){
  x(x()+dx);
  y(y()+dy);
}



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

  std::vector<int> res;
  atomo* clicked=NULL;
  _la_molecola->prova_click_atomo(&clicked,x_c, y_c);

  if(clicked!=NULL){
    res.push_back(static_cast<int>(rintf(clicked->pos_x())));
    res.push_back(static_cast<int>(rintf(clicked->pos_y())));
    std::vector<atomo*> children=clicked->get_all_children();
    if(children.size()>1){
      bidimensional_vinculated_particle b;
      b.k_spring(10);
      pair<float,float> center(clicked->pos_x(),
                               clicked->pos_y());
      b.add_center(center);
      for(unsigned int i=0;i<children.size();i++){
        pair<float,float> tmp(children[i]->pos_x(),children[i]->pos_y());
        b.add_particle(tmp);
      }
      std::vector<float> start_position;
      start_position.push_back(children[0]->pos_x());
      start_position.push_back(children[0]->pos_y());
      
      b.pos(start_position);
      std::vector<float> pp=b.pos();

      //atomo* nw_atm=_la_molecola->crea_legame_nuovo(clicked,pp[0], 
      //                                              pp[1], LEGAME_SINGOLO);
      
      while(b.update()){
        //redraw();
        //Fl::check();
        pp=b.pos();
        //nw_atm->pos_x(static_cast<int>(rintf(pp[0])));
        //nw_atm->pos_y(static_cast<int>(rintf(pp[1])));
      }
    
      res.push_back(static_cast<int>(rintf(pp[0])));
      res.push_back(static_cast<int>(rintf(pp[1])));
    }
  }
 
  return res;
}

void mol_canvas::rotation_pivot_pos(int x, int y){
  _x_pivot=x;
  _y_pivot=y;
}

const float mol_canvas::rotation_incr=0.01;
const float mol_canvas::zoom_incr=0.1;
const float mol_canvas::scale_incr=0.1;
