/*

    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 ET_TYPE_NOT_VALID   -1
#define ET_STR               0
#define ET_APICE             1
#define ET_PEDICE            2

/**
Questa classe rappresenta una stringa di testo dell'imagine
*/

class etichetta :  public disegnabile, public genitore , public selezionabile{

public:

  /**
   *Costruttore di default, riempie i valori con immondizia.
   */

  etichetta();


  etichetta(const etichetta* other);

  etichetta(const etichetta& altro);




  etichetta& operator=(const etichetta& altro);

  virtual ~etichetta();



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

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

  /**
   *\return una copia delle stringhe che compongono questa etichetta
   */

  virtual vector < pair<string,int> > vec_str();


  /**
   *Aggiunge un elemento al vettore
   *
   *\param nw la nuova etichetta
   *\param tipo il tipo si stringa: puo' assumere i valori:
   *
   *<ul>
   *<li>ET_STR
   *<li>ET_APICE
   *<li>ET_PEDICE
   *</ul>
   */

  virtual void aggiungi(string nw, int tipo);


  /**
   *insert the string "nw" of type  "type" in positipn "pos". If pos >
   *_vec_str.size() then the sring is appended.
   *
   */
  virtual void insert(string nw, int type, int pos, bool reset_cur=true);

  /**
   *Elimina la stringa in una certa posizione.
   *
   *\param where l'elemento da eliminare.
   */

  virtual void elimina(int where, bool reset_cur=true) throw (out_of_range);


  /**
   *sostituisci la stringa in una certa posizione.
   *
   *\param cosa la nuova stringa
   *\param tipo il tipo si strinag (apice pedice o normale)
   *\param where l'elemento da eliminare.
   */

  virtual void sostituisci(string cosa, int tipo,
                           int where, bool reset_cur=true) throw (out_of_range);




  /**
   *Elimina la prima stringa uguale a ricercata.
   *
   *\param ricercata  l'elemento da eliminare.
   *\return 0  se la stringa non e' stata trovata 1 altrimenti.
   */

  virtual int elimina(string ricercata, bool reset_cur=true);


  /**
   *Elimina tutti gli apici.
   */
  virtual void elimina_apici(bool reset_cur=true);

  /**
   *Elimina tutti i pedici
   */
   virtual void elimina_pedici(bool reset_cur=true);


  /**
   *Elimina tutta l'etichetta
   */
  virtual void elimina(bool reset_cur=true);

  
  virtual void subst_vec_str(std::vector < std::pair<std::string,int> > nw);


  /**
   *\return  il tipo di  font (<em>vedi  le fltk  per il  significato da
   *attribuire a questo intero</em).
   */
  virtual int font();

  /**
   *\return La dimensione  del font (in pixel) restituisce  in realta, o
   *phys_dim o visual_dim a secondo se plotter e' un puntatore valido.
   */

  virtual int dim();


  virtual int phys_dim();


  
  /**
   *\return La dimensione del font (in pixel) tenuto conto dello zoom
   */

  virtual int visual_dim();


  /**
   *Imposta la dimensione del font (in pixel).
   *\param La nuova dimensione.
   */

  virtual void dim(int nw);



  /**
   *\return L'ascissa dell'etichetta  (corrispondente all'angolo in alto
   *a sinistra dalla prima lettera della stringa).
   */

  virtual float x();

  /**
   *\return L'ascissa dell'etichetta  zoomata (corrispondente all'angolo in alto
   *a sinistra dalla prima lettera della stringa)
   */

  virtual float visual_x();

  virtual float phys_x();
  

  /**
   *\return L'ordinata dell'etichetta  (corrispondente all'angolo in alto
   *a sinistra dalla prima lettera della stringa).
   */

  virtual float y();


  /**
   *\return L'ordinata dell'etichetta zoomata  (corrispondente all'angolo in alto
   *a sinistra dalla prima lettera della stringa).
   */

  virtual float visual_y();

  virtual float phys_y();

  /*setta i valori*/

  /**
   *Imposta il valore del font dell'etichetta.
   *\param Il nuovo font.
   */
  virtual void font(int nw);


  /**
   *Imposta l'ascissa dell'etichetta (corrispondente all'angolo in alto
   *a sinistra dalla prima lettera della stringa).
   *\param La nuova ascissa.
   */

  virtual void x(float nw);


  /**
   *Imposta l'ordinata dell'etichetta (corrispondente all'angolo in alto
   *a sinistra dalla prima lettera della stringa).
   *\param La nuova ordinata.
   */

  virtual void y(float nw);

  
  /**
   *Misura l'altezza e la larghezza di questa etichetta
   *\param altris l'altezza dell'etichetta
   *\param larris la larghezza dell'etichetta
   */

  virtual void misura(float& altris,float& larris );


  
  /**
   *Misura l'altezza e la larghezza di questa etichetta tenendo conto dello zoom
   *\param altris l'altezza dell'etichetta
   *\param larris la larghezza dell'etichetta
   */

  virtual void visual_misura(float& altris,float& larris );



  virtual void phys_misura(float& altris,float& larris );


  /**
   *\return l'altezza di questa etichetta
   */
  
  virtual float h();
  /**
   *\return l'altezza di questa etichetta tenuto conto del fattore di zoom
   */
  
  virtual float visual_h();

  virtual float phys_h();


  /**
   *\return la larghezza di questa etichetta
   */
  
  virtual float w();

  


  /**
   *\return la larghezza di questa etichetta tenuto conto del fattore di zoom
   */
  
  virtual float visual_w();

  virtual float phys_w();

  /**
   *Ritorna la lunghezza del vettore contenente le stringhe
   */

  virtual int size_str();


  virtual void disegna();

  /**
   *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 radianti in senso orario
   *\param xpivot ascissa relativa all'asse di rotazione
   *\param ypivot ordinata relativa all'asse di rotazione
   *
   */

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

  /**
   *Trasla l'oggetto.
   *
   *\param dx entita' dello spostamento lungo l'ascissa
   *\param dy entita' dello spostamento lungo l'ordinata
   */

  virtual void trasla(float dx, float dy);


  virtual void phys_translate(float dx, float dy);


  virtual bool dentro_bb(float x_bb, float y_bb, float w_bb , float h_bb);

  /**
   *
   *\param posx_m ascissa del puntatore
   *\param 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);


  /**
   *etichetta -> string raw conversion
   */
  virtual string to_raw_string();


  /**
   *set cursor pos
   */
  
  virtual void set_cursor_position(int pos_in_vec, string::size_type pos_in_string);

  
  virtual void set_cursor_position(std::pair<int,string::size_type> pos);

  /**
   *set cursor position to the nth char (nth==limit);
   *\return the type of the label (i.e. super or subscript or normal string)
   */

  virtual int  set_cursor_position(int limit);


  virtual void go_to_end_of_label();

  virtual void go_to_end_of_line();

  virtual void go_to_start_of_label();

  virtual void go_to_start_of_line();

  virtual int get_cursor_position(std::pair<int,string::size_type>* pos);


  virtual void draw_cursor(bool draw);
  virtual bool draw_cursor();

  /**
   *\return true if the address passed as parameter contain valid coordinates
   */

  virtual bool cursor_to_coordinate(int& x, int& y);

  virtual void reset_cursor_if_outside_limits(bool second_pos_not_end=false);


  virtual bool cursor_one_step_fwd(int &curr_type);


  virtual bool cursor_one_step_back(int &curr_type);

  virtual bool check_if_type_etic(int typ) throw (out_of_range);


  virtual bool check_if_type_etic(int typ,int pos) throw (out_of_range);


  virtual bool check_if_type_etic_next_chunk(int equal,bool &res_next_exist);

  virtual bool check_if_type_etic_previous_chunk(int equal,bool &res_prev_exist);

  virtual int type_etic_at_cur_pos();

  virtual void delete_char_curr_pos(bool before);

  virtual void insert_string_in_curr_pos(std::string str,int type);

  virtual void manage_sub_super(int check, int troublesome,std::string car);

  virtual bool manage_add_sub_super_next_normal_str(int type);

  virtual bool manage_add_sub_next_super(int type);

  virtual void insert_char_in_curr_pos(char add, int type);

  virtual void break_string_at_cur_pos(int breaking_type);

  virtual void break_sub_super(int me, int type_to_insert,bool is_after);

  virtual void break_sub_or_super(int me, int type_to_insert);

  virtual void break_normal_str(int type_to_insert);

  virtual bool break_and_split_normal_str(etichetta** left , etichetta** right);



  virtual bool can_highlight();

  virtual bool can_highlight(bool nw);


  virtual void draw_negative(bool nw);

  virtual bool draw_negative();


  /**
   *Costruisce una stringa da passare alle plotlib
   */

  virtual string costruct_plot_string();


  virtual float get_pango_baseline(int type=ET_STR);

  virtual float get_fltk_baseline();
  virtual float get_fltk_phys_baseline();

  virtual float get_pango_logical_y();
  virtual float get_pango_ink_y();

  virtual void melt_similar(int start);

protected:

  virtual void measure_as_pango_layout(std::vector < std::pair<std::string,int> > vec,
                                       float &w, float &h, int until=-1);

  virtual float check_pango_max_between_sub_sup(std::vector < std::pair<std::string,int> > vec, 
                                                unsigned int pos);
  virtual void get_pango_logical_sizes(std::string st, int type, 
                                       float& w_logical, float& h_logical,
                                       float& lbearing , float& ascent, float& descent);

  virtual void get_pango_ink_sizes(std::string st, int type, 
				   float& w_ink, float& h_ink,
				   float& lbearing , float& ascent, float& descent);



  virtual void get_pango_logical_rectangle(std::string st, int type, 
                                           PangoRectangle* rect);

  virtual void get_pango_ink_rectangle(std::string st, int type, 
				       PangoRectangle* rect);



  virtual float get_pango_logical_y(std::string st, int type);
  virtual float get_pango_ink_y(std::string st, int type);



  virtual void draw_pango_string(std::string st,int x, int y, int type);

  virtual void draw_pango_sub_superscript(std::string st, int hparent,
                                             int x ,int y, int type);

  virtual void   draw_label_onscreen();

  virtual void   draw_label_export();

  virtual bool merge_with_previous_if_equal(bool reset_cur=true) throw (out_of_range);


  virtual void merge_orphan_pedic_apic(int from, int type, bool& has_merged);

  virtual void delete_orphan_pedic_apic(int from,int type);

  virtual void clean_string_after_delete();


  virtual int switch_APIC_PEDIC(int what);




  int _cr;
  int _cg;
  int _cb;

  int _allineamento;

  std::vector < std::pair<std::string,int> > _vec_str;

  int _font;
  int _dim;

  float _x;
  float _y;

  /**
   *Offset verticale dell'etichetta
   */

  int _v_offset;

  
  /**
   *Contiene la  posizione nel vettore delle stringhe  in _pos.first e
   *la posizione all'interno della stringa in _pos.second
   *
   * pos_first e'  la posizione  dne vettore dove  si sta  scrivendo e
   * pod.second  quella  all'interno  del  vettore dove  si  andra'  a
   * scrivere
   */
  std::pair<int,string::size_type> _cursor_pos;


  bool _draw_cursor;

  bool _draw_negative;

  bool _can_highlight;

};


