/*

    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 MULTILINE_LABEL_ALIGN_CENTER_TEXT_LAYOUT       1
#define MULTILINE_LABEL_ALIGN_LEFT_TEXT_LAYOUT         2
#define MULTILINE_LABEL_ALIGN_RIGHT_TEXT_LAYOUT        3
#define MULTILINE_LABEL_ALIGN_SINGLE_LINE_TEXT_LAYOUT  4


/**
a paragraph of text
*/

class multiline_label :  public etichetta{

public:

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

  multiline_label();



  multiline_label(const multiline_label& other);

  multiline_label(const multiline_label* other);


  multiline_label& operator=(const multiline_label& other);

  virtual ~multiline_label();


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

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

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

  virtual std::vector < pair<std::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(std::string nw, int tipo);


  /**
   *add a new line to the tail of _lines_of_text
   *\param new_line the new line
   */

  virtual void add_line(etichetta new_line);


  virtual void add_line(etichetta* new_line);



  /**
   *add a new line in position <b>after</b> pos
   *\param new_line the new line
   */

  virtual void add_line(etichetta new_line, int pos);


  virtual void add_line(etichetta* new_line, int pos);


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


  /**
   *insert a new line to  _lines_of_text in posistion pos
   *\param new_line the new line
   *\param pos the position where to insert
   */

  virtual void insert_line(etichetta new_line, int pos);

  virtual void insert_line(etichetta* new_line, int pos);



  /**
   *delete line  from _lines_of_text in  posistion pos 
   *
   *\param  pos the position  where  to  delete  
   *
   *\param  reset_pointer_currline reset  _pointer_to_currline  to fit
   *into the _lines_of_text bonduaries
   */

  virtual void delete_line(int pos, bool reset_pointer_currline);


  /**
   *substitute  line  from _lines_of_text  in  posistion  pos with  nw
   *\param nw the new etichetta
   *\param pos the position where to make substituition
   */


  virtual void subst_line(etichetta* nw, int pos);


  virtual etichetta get_line_copy(int pos) throw (out_of_range);


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

  virtual void elimina(int where) throw (out_of_range){
    delete_line(where,true);
  };


  /**
   *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(std::string cosa, int tipo,int where) 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(std::string ricercata);


  /**
   *Elimina tutti gli apici.
   */
  virtual void elimina_apici(){};

  /**
   *Elimina tutti i pedici
   */
   virtual void elimina_pedici(){};


  /**
   *Elimina tutta l'etichetta
   */
  virtual void elimina();

  /**
   *\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 );


  
  virtual void phys_misura_as_a_whole(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(){return 0;};


  virtual unsigned int size_lines_of_text();

  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 std::string to_raw_string(){return "";};


  /**
   *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);


  virtual void set_cursor_position_abs(int line, int pos_in_vec, 
                                       string::size_type pos_in_string);

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

  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 insert_string_in_curr_pos(std::string str,int type);

  virtual void draw_cursor(bool draw);

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

  virtual bool cursor_to_coordinate(int& x, int& y){ return true;};

  virtual void reset_cursor_if_outside_limits();

  virtual void reset_pointer_to_currline();

  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 bool treat_as_a_whole();

  virtual bool treat_as_a_whole(bool nw);  


  float interline_space();

  float phys_interline_space();

  float visual_interline_space();

  int interline_space(int nw);

  virtual void pointer_to_currline(int nw);

  virtual  int pointer_to_currline();

  virtual  int pointer_to_currline_transl(int delta);
  

  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 std::vector<etichetta*> get_lines_text();

  virtual int layout_lines();

  virtual void layout_lines(int nw);

  virtual void increase_highlighted();

  virtual void decrease_highlighted();

  virtual void de_highlight();


  virtual void draw_negative(bool nw);

  virtual bool draw_negative();


  bool dump_label();

  virtual void merge_labels_amap();

protected:

  virtual void   draw_label_export();

  virtual bool ptr_line_less_lines_text();

  virtual bool ptr_line_is_last_line();


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

  virtual std::string costruct_plot_string(){return "";};


  virtual void format_paragraph();

  virtual void format_lines_align_right();

  virtual void format_lines_align_left();

  virtual void format_lines_align_center();

  void update_vec_str();

  void update_lines_of_text();


  float calculate_last_line_y(bool add_interline=true);


  vector <etichetta*> _lines_of_text;

  bool _treat_as_a_whole;

  int  _pointer_to_currline;

  int  _interline_space;

  int  _layout_lines;

  const static int _default_interline_space; 


};


