#ifndef __SHEET_H
#define __SHEET_H

#ifndef __STRINGS_H
#include <strings.h>
#endif

#ifndef __WINDOW_H
#include <window.h>
#endif

#ifndef __RELATION_H
class TCursor;
#endif

#ifndef __MASKFLD_H
class   TEdit_field;
#endif 


// @doc EXTERNAL

// @class TSheet | Classe per la definizione e la gestione degli sheet per le ricerche
//
// @base public | TScroll_window
class TSheet : public TScroll_window

// @author(:INTERNAL) Guido

// @access Privete Member
{
  // @ccost MAX_BUT | 8 | Numero massimo di bottoni
  enum { MAX_BUT = 8,
         // @ccost MAX_COL | 128 | Numero massimo di colonne
         MAX_COL = 128 };

  // @cmember Array di stringhe con il contenuto dello sheet
  TString_array _page;

  // @cmember Numero di colonne dello sheet
  byte _columns;
  // @cmember Dimensione di ogni colonna
  byte _size[MAX_COL];
  // @cmember Tipo di ogni colonne
  byte _type[MAX_COL];
  // @cmember Riga corrente
  long _curr;
  // @cmember Indice della prima riga visibile
  long _last_update;

  // @cmember Numero di righe visibili
  short _visible_rows;

  // @cmember Indica se e' possibile inserire un check (X di selezione) sulle righe sheet
  bool _checkable;
  // @cmember Indica se e attivata la gestione dei check delle righe
  bool _check_enabled;
  // @cmember Array di righe attivate
  TBit_array _checked;
  // @cmember Array di righe disabilitate
  TBit_array _disabled;

  // @cmember Handles dei bottoni presenti nella finestra
  WINDOW _button[MAX_BUT];
  // @cmember Tasto associato ad ogni bottone
  KEY _key[MAX_BUT];
  // @cmember Maschera di bit corrispondente ai bottoni standard
  byte _buttonmask;

  // @access Protected Member
protected:
  // @cmember Ritorna se il numero di colonne e' maggiore di 1
  bool head_on() const
  { return _columns > 1; }
  // @cmember Indica se esitono i bottoni in fondo
  bool buttons_on() const
  { return *_button != NULL_WIN; }
  // @cmember Ritorna il numero di righe visibili
  short visible_rows() const
  { return _visible_rows; }
  // @cmember Ritorna il numero di righe riservate ai bottoni
  virtual short reserved_rows() const;
  // @cmember Crea la pagina
  void build_page(long first = -1);

  // @cmember Converte le coordinate da logiche (caratteri) in coordinate fisiche (pixel)
  //          (vedi <mf TWindow::log2dev>)
  virtual PNT log2dev(long x, long y) const;
  // @cmember Gestisce l'handler della finestra (vedi <mf TWindow::handler>)
  virtual void handler(WINDOW win, EVENT* ep);
  // @cmember Gestisce la pressione del tasto (vedi <mf TWindow::on_key>)
  virtual bool on_key(KEY);
  // @cmember Fa' l'update della finestra (vedi <mf TWindow::update>)
  virtual void update();

  // @cmember Setta il numero della prima riga dello sheet
  void set_first(long n);
  // @cmember Ritorna se la riga <p n>-esima e' visibile
  bool is_visible(long n) const
  { return n >= first() && n < first()+visible_rows(); }

  // @cmember Calcola la larghezza totale dello sheet virtuale
  int width() const;
  // @cmember Converte il numero di riga <p n> assoluto nell'indice dell'array <p _page>
  int row_to_page(long n) const;
  // @cmember Converte il numero di riga <p n> assoluto nella coordinata y sulla finestra
  int row_to_win(long n) const;

  // @cmember Ritorna il numero della prima riga
  long first() const
  { return origin().y; }
  // @cmember Forza il ridisegno di una riga
  bool update_row(long n);
  // @cmember Permette di scriveiere in inverso la riga <p n>-esima
  void invert_row(long n);

  // @cmember Aggiunge una riga all'array di quelle visibile
  void set_row(const TToken_string& row, byte n);

  // @cmember Permette di riposizionare i bottoni all'interno della pagina
  virtual void repos_buttons() const;

  // @cmember Copia le righe nella pagina da visualizzare
  virtual void page_build(long first, byte num) pure;

  // @cmember Stampa lo sheet
  void print();

  // @access Public Member
public:
  // @cmember Costruttore
  TSheet(short x,short y,short dx,short dy,const char* title,const char* head,byte buttons = 0,long first = 0L,WINDOW parent = NULL_WIN);

  // @cmember Mostra la finestra (vedi <mf TWindow::open>)
  virtual void open();

  // @cmember Aggiunge un bottone nella finestra
  void add_button(short id, const char* caption, KEY key = K_ESC);

  // @cmember Ritorna il numero di elementi di <p _page>
  virtual long items() const pure;
  // @cmember Ritorna il contenuto di una riga
  virtual TToken_string& row(long s = -1);

  // @cmember Ritorna il numero della riga corrente
  long selected() const
  { return _curr; }
  // @cmember Seleziona una riga facendola diventare corrente
  void select(long n);
  
  // @cmember Ritorna il tipo della colonna <p c>-esima
  byte column_flag(int c) const
  { return _type[c]; }
  // @cmember Ritorna il tipo della colonna <p c>-esima (permette di modificarlo)
  byte& column_flag(int c)
  { return _type[c]; }

  // @cmember Ritorna se la riga <p n>-esima e' attivata
  bool checked(long n) const
  { return _checked[n]; }
  // @cmember Permette di attivare/disattivare una riga
  void check(long n, bool on = TRUE);
  // @cmember Permette di disattivare una riga (chiama <mf TSheet::check>)
  void uncheck(long n)
  { check(n, FALSE); }
  // @cmember Permette di abilitare (<p yn> = TRUE) o disabilitare (<p yn> = FALSE)
  //          la gestione dei check sullo sheet
  void enable_check(bool yn = TRUE)
  { _check_enabled = yn; }
  // @cmember Permette di disbilitare (<p yn> = FALSE) i check sullo sheet
  void disable_check()
  { enable_check(FALSE); }
  
  // @cmember Abilita/disabilita una riga
  void enable(long n = -1, bool on = TRUE);
  // @cmember Disabilita una riga (chiama <mf TSheet::enable>)
  void disable(long n = -1)
  { enable(n, FALSE); }
  // @cmember Ritorna se e' abilitata la riiga <p n>-esima
  bool enabled(long n) const
  { return !_disabled[n]; }
  // @cmember Ritorna se e' disabilitata la riiga <p n>-esima
  bool disabled(long n) const
  { return _disabled[n]; }
  
  // @cmember Ritrna se esiston elementi attivati nello sheet (TRUE se esitono)
  bool one_checked() const
  { return _checked.first_one() != -1; }
  // @cmember Ritorna il numero di elementi attivati (vedi <mf TBit_array::ones>)
  long checked() const
  { return _checked.ones(); }
};

// @class TArray_sheet | Classe per la gestione degli sheet i cui dati sono
//                       forniti da un array di stringhe
//
// @base public | TSheet
class TArray_sheet : public TSheet
// @author(:INTERNAL) Guido

// @access Private Member
{
  // @cmember Contenuto dell'array di cui costruire lo sheet
  TString_array _data;

  // @access Protected Member
protected:
  // @cmember Costruisce la pgaina (vedi <mf TSheet::page_build>)
  virtual void page_build(long first, byte num);
  // @cmember Ritorna il contenuto dell'elemento <p n>-esimo
  TToken_string& data(long n)
  { return _data.row((int)n); }

  // @access Public Member
public:
  // @cmember Costruttore
  TArray_sheet(short x, short y, short dx, short dy, const char* caption, const char* head, byte buttons = 0, WINDOW parent = NULL_WIN);
  // @cmember Ritorna il numero degli elemnti dello sheet
  virtual long items() const 
  { return _data.items(); }
  // @cmember Ritorna il contenuto dello sheet
  TString_array& rows_array() 
  { return _data; }
  // @cmember Aggiunge un elemento allo sheet
  long add(const TToken_string& s);
  // @cmember Aggiunge un elemento (passato per indirizzo) allo sheet
  long add(TToken_string* s);
  // @cmember Inserisce un elemento nella posizione
  long insert(const TToken_string& s, long n);
  // @cmember Ritorna la riga <p s>-esima dell'array
  virtual TToken_string& row(long s = -1) 
  { return (s < 0) ? data(selected()) : data(s); }
  // @cmember Azzera l'array dello sheet
  bool destroy(int i = -1);
};


// @class TCursor_sheet | Classe per la gestione di uno sheet i cui dati
//                        sono prelevati da un <c TCursor>
//
// @base public | TSheet
class TCursor_sheet : public TSheet
// @author(:INTERNAL) Guido

// @access Private Member
{
  // @cmember Array di <c TRecfield>
  TArray _fields;
  // @cmember Numero del records collegato al cursore
  long _records;

  // @cmember Cursore da cui prelevare i dati
  TCursor* _cursor;

  // @access Protected Member
protected:  // TSheet
  // @cmember Costruisce la pgaina (vedi <mf TSheet::page_build>)
  virtual void page_build(long first, byte rows);
  
  // @access Public Member
public: // TSheet
  // @cmember Ritorna il numero dei records del cursore
  virtual long items() const 
  { return _records; }
  
  // @cmember Lancia la finestra con lo sheet
  virtual KEY run();

  // @access Public Member
public:
  // @cmember Ritorna il cursore
  TCursor* cursor() const
  { return _cursor; }

  // @cmember Costruttore
  TCursor_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons = 0);
  // @cmember Distruttore
  virtual ~TCursor_sheet() 
  {}                     
};


// @class TBrowse_sheet | Classe per la gestione degli sheet legati ad un
//                        cursore del campo della maschera
//
// @base public | TCursor_sheet
class TBrowse_sheet : public TCursor_sheet
// @author(:INTERNAL) Guido

// @access Private Member
{
  // @cmember Campi collegati ai campi editabili (vedi <c TEdit_field>)
  TEdit_field* const _field;
  // @cmember Riga selezionata
  int _sel;

  // @access Protected Member
protected:
  // @cmember Gestisce l'handler della finestra (vedi <mf TWindow::handler>)
  virtual void handler(WINDOW win, EVENT* ep);
  // @cmember Ritorna il numero di righe riservate
  virtual short reserved_rows() const;
  // @cmember Permette di riposizionare i bottoni nella finestra
  virtual void repos_buttons() const;
  // @cmember Gestisce la pressione del tasto (vedi <mf TWindow::on_key>)
  virtual bool on_key(KEY k);
  // @cmember Ritorna il campo a cui si riferisce lo sheet
  TEdit_field& field() 
  { return *_field; }

  // @access Public Member
public:
  // @cmember Costruttore
  TBrowse_sheet(TCursor* cursor, const char* fields, const char* title, const char* head, byte buttons, TEdit_field* f, TToken_string* siblings = NULL);
  // @cmember Distruttore
  virtual ~TBrowse_sheet()
  {}
  // @cmember ???
  virtual KEY run();
};


#endif
