/*

    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 PARAGRAPH_TEXT_ALIGN_CENTER_TEXT_LAYOUT       1
#define PARAGRAPH_TEXT_ALIGN_LEFT_TEXT_LAYOUT         2
#define PARAGRAPH_TEXT_ALIGN_RIGHT_TEXT_LAYOUT        3
#define PARAGRAPH_TEXT_ALIGN_SINGLE_LINE_TEXT_LAYOUT  4


/**
a paragraph of text
*/

class paragraph_text :  public etichetta{

public:

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

  paragraph_text();



  paragraph_text(const paragraph_text& other);

  paragraph_text(const paragraph_text* other);


  paragraph_text& operator=(const paragraph_text& other);

  virtual ~paragraph_text();


  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(multifont_label new_line);


  virtual void add_line(multifont_label* new_line);



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

  virtual void add_line(multifont_label new_line, int pos);


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


  /**
   *insert the string "nw" of type  "type" in position "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 position pos
   *\param new_line the new line
   *\param pos the position where to insert
   */

  virtual void insert_line(multifont_label new_line, int pos);

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



  /**
   *delete line  from _lines_of_text in  position 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  position  pos with  nw
   *\param nw the new etichetta
   *\param pos the position where to make substituition
   */


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

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

  virtual void elimina(int where) 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(std::string cosa, int tipo,int where) throw (out_of_range){};




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

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


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

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


  /**
   *
   *
   *\param nw new dimension
   *\param ptr_line which line of this paragraph passing NULL means current
   *\param ptr_line_child which sublabel of this line passing NULL means current
   *\return old dim
   */

  virtual int  dim_child(int nw,int* ptr_line=NULL, int* ptr_line_child=NULL);


  /**
   *\param nw new font
   *\param ptr_line which line of this paragraph passing NULL means current
   *\param ptr_line_child which sublabel of this line passing NULL means current
   *\return old dim
   */


  virtual int font_child(int nw,int* ptr_line=NULL, int* ptr_line_child=NULL);
  virtual int cr_child(int nw,int* ptr_line=NULL, int* ptr_line_child=NULL);
  virtual int cg_child(int nw,int* ptr_line=NULL, int* ptr_line_child=NULL);
  virtual int cb_child(int nw,int* ptr_line=NULL, int* ptr_line_child=NULL);

  virtual void color_child(int cr, int cg, int cb,
                          int* ptr_line=NULL, int* ptr_line_child=NULL);




  /**
   *Query for characteristic
   *\param cr,cg,cb,font,dim pass NULL to ignore in query
   *\param ptr_line which line of this paragraph passing NULL means current
   *\param ptr_line_child which sublabel of this line passing NULL means current
   */


  virtual void query_child(int* cr, int* cg, int* cb,
                           int* font, int* dim,
                           int* ptr_line=NULL, int* ptr_line_child=NULL);

  /**
   *
   *
   *\param nw new dimension
   *\param ptr_line which line of this paragraph passing NULL means current
   *\param ptr_line_child which sublabel of this line passing NULL means current
   *\return old dim
   */

  virtual bool  highlight_child(bool nw,int* ptr_line=NULL, int* ptr_line_child=NULL);



  virtual void highlight_current_line();



  virtual void dehighlight_current_line();


  /*       
            ld
	      +-------+
     	      |       |
	      |       |
	      +-------+ 
                       ru
   */


  virtual bool highlight_under_bounding_box(std::pair<float,float> ld,
					    std::pair<float,float> ru);

  virtual bool some_highlighted();

  virtual bool invert_highlight_child_and_shift_cursor(bool fwd=true);



  /**
   *
   *\return true if whished_ptr_line and whished_ptr_line_child do not
   *trepasses theirs bonduaries false otherwise
   */

  virtual bool set_ptrline_to_modify_children(int* whished_ptr_line,
                                              int* whished_ptr_line_child,
                                              int* saved_ptr_line,
                                              int* saved_ptr_line_child,
                                              int* act_ptr_line,
                                              int* act_ptr_line_child);


  /**
   *\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 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 cursor_one_step_up(int &curr_type);

  virtual bool cursor_one_step_down(int &curr_type);

  virtual void delete_char_curr_pos(bool before);

  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 std::vector<multifont_label*> 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 update_highligted_text();

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


  virtual etichetta get_label_copy_from_coordinate(int ptrline,
                                                   int ptrline_child) throw (out_of_range);


  virtual int calculate_no_chars_before_abs_cur_pos(int line,
                                                    int line_child,
                                                    std::pair<int,string::size_type> cpos_c);

  virtual bool check_if_abs_pos_legal(int ptrline, int ptrline_child,
                                      int cpos_f,int cpos_s);


  virtual void calculate_curpos_until_limit(unsigned int ptrline,
                                            unsigned int& line,
                                            std::pair<int,string::size_type>& cpos,
                                            int limit);


  bool dump_label();

  /**
   *\return true if has more
   */



protected:

  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_center();

  void update_vec_str();

  void update_lines_of_text();


  float calculate_last_line_y(bool add_interline=true);


  vector <multifont_label*> _lines_of_text;

  int  _pointer_to_currline;

  int  _interline_space;

  int  _layout_lines;


  const static int _default_interline_space;


};


