#ifndef __MASK_H
#define __MASK_H

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

#ifndef __MASKFLD_H
#include <maskfld.h>
#endif

class TSheet_field; 

// @doc EXTERNAL

// @type MASK_HANDLER | Funzione per gestire i tasti speciali all'interno di una maschera.
typedef bool (*MASK_HANDLER)(TMask& mask, KEY key);

// @enum Modalita' di utilizzo della maschera corrente
enum TMaskmode {
  NO_MODE,         // @emem Nessun modo
  MODE_INS ,       // @emem Modalita' di inserimento dati
  MODE_MOD ,       // @emem Modalita' di modifca dati
  MODE_VIS ,       // @emem Modalita' di visualizzaione dati
  MODE_QUERY,      // @emem Modalita' di richiesta chiave
  MODE_QUERYINS }; // @emem Modalita' di richiesta chiave e inserimento dati

// @class TMask | Classe per la gestione delle maschere video
//
// @base public | TWindow
class TMask : public TWindow
{
  // @author:(INTERNAL) Guido

  // @access Private Member

  // @ccost MAX_PAGES | 12 | Massimo numero di pagine nella maschera
  enum { MAX_PAGES = 12 };
  // @cmember Windows delle pagine
  WINDOW _pagewin[MAX_PAGES+1];
  // @cmember Windows per pgup/pgdn
  WINDOW _pagepag[MAX_PAGES];
  // @cmember Windows di numeri pagina
  WINDOW _pagetag[MAX_PAGES];

  // @cmember Numero di pagine della maschera
  int _pages;
  // @cmember Pagina corrente
  int _page;

  // @cmember Controlla le pagine abilitate
  TBit_array _enabled;
  // @cmember Modalita' di utilizzo della maschera
  int _mode;
  // @cmember Numero di campi della maschera
  TArray _field;

  // @cmember Primo controllo che deve ricevere il focus
  int _first_focus;
  // @cmember Controllo che possiede il focus
  int _focus;
  // @cmember Controllo che deve ricevere il focus
  int _next_fld;
  
  // @cmember Numero di sheet contenuti nella maschera
  int _sheets;
  // @cmember Puntatore allo sheet che contiene la maschera (puo' essere NULL)
  TSheet_field* _sheet;

  // @cmember Handler per gestire i tasti speciali nelle maschere
  MASK_HANDLER _handler;

  // @cmember Nome del file sorgente contenente la maschera
  TFilename _source_file;
  // @cmember Nome del file di salvataggio in cui sono scaricati i valori della maschera
  TFilename _workfile;

  // @cmember Ultimo offset letto nel file di salvataggio
  long _lastpos;

  // @cmember Cambio attuale per i cambi in valuta
  real _exchange;
  // @cmember Controlla se la maschera deve fare i controlli iniziali di validita' dei campi
  bool _should_check;

  // @cmember Tempo totale di caricamento della maschera
  long _total_time;
  // @cmember Tempo di compilazione della maschera
  long _build_time;
  // @cmember Tempo di inizializzazione della maschera
  long _init_time;

  // @access Protected Member
protected:
  // @cmember Ritorna la finestra della pagina corrente (Usare con attenzione)
  WINDOW win() const
  { return _page < 0 ? _pagewin[0] : _pagewin[_page]; }
  
  // @cmember Ritorna il numero di campi nella finestra
  int find_field_win(WINDOW win) const;

  // @cmember Aggiorna i controlli a video con i valori iniziali della maschera
  void set_mask_fields() const;

  // @cmember Legge i controlli relativi ad un campo
  void load_checks() const;
  // @cmember Inizializza la maschera (Chiamata quando la maschera parte)
  virtual void start_run();
  // @cmember Legge il campo da file
  virtual TMask_field* parse_field(TScanner& scanner);

  // @cmember Inizializza la maschera
  void init_mask();
  // @cmember Legge la pagina da file
  WINDOW read_page(TScanner& scanner, bool toolbar = FALSE);
  // @cmember Legge la maschera da file
  void read_mask(const char* name, int num, int max);
  // @cmember Permette di aggiungere sulla maschera tutti i bottoni per la 
  //          navigazione tra le pagine
  void add_buttons();

  // @cmember Ritorna il numero della finestra padre del campo <p f>
  int find_parent_page(const TMask_field& f) const;
  // @cmember Ritorna la posizione del primo campo attivo nella direzione specificata
  int find_first_field(WINDOW w, int dir) const;
  // @cmember Ritorna il prossimo campo attivabile
  int find_active_field(int first, int dir) const;
  // @cmember Controlla tutti i campi della pagina corrente
  bool check_current_page();
  // @cmember Mostra la prossima/precedente pagina 
  void next_page(int p);
  // @cmember Ritorna il numero della pagina corrente
  int curr_page() const
  { return _page; }

  // @cmember Controlla se e' possibile dare il focus alla finestra <p next> (TRUE se possibile)
  bool test_focus_change(WINDOW next = NULL_WIN);
  // @cmember Funzione chiamata ogni volta che arriva un evento e lo gestisce
  void control_handler(EVENT* ep);
  // @cmember Gestisce gli eventi XVT diretti alla pagina corrente della maschera
  virtual void handler(WINDOW win, EVENT* ep);

  // @access Public Member
public:
  // @cmember Costruttore (crea la maschera leggendo la descrizione dal file .msk)
  TMask(const char* name, int num = 0, int max = MAX_PAGES);
  // @cmember Costruttore (crea una maschera vuota con i parametri dati)
  TMask(const char* title, int pages, int cols, int rows, int xpos = -1, int ypos = -1);

  // @cmember Distruttore
  virtual ~TMask();

  // @cmember Ritorna il nome del file contentente la maschera
  const TFilename& source_file() const
  { return _source_file; }

  // @cmember Aggiunge runtime un campo testo alla maschera
  WINDOW add_static (short id, int page, const char* prompt, int x, int y, const char* flags = "");
  // @cmember Aggiunge runtime un campo stringa alla maschera
  WINDOW add_string (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int width = 0);
  // @cmember Aggiunge runtime un campo numerico alla maschera
  WINDOW add_number (short id, int page, const char* prompt, int x, int y, int dim,  const char* flags = "", int ndec = 0);
  // @cmember Aggiunge runtime un campo data alla maschera
  WINDOW add_date (short id, int page, const char* prompt, int x, int y, const char* flags = "");
  // @cmember Aggiunge runtime un campo bottone alla maschera
  WINDOW add_button (short id, int page, const char* prompt, int x, int y, int dx = 9, int dy = 1, const char* flags = "");
  // @cmember Aggiunge runtime un campo radio button alla maschera
  WINDOW add_radio(short id, int page, const char* prompt, int x, int y, int dx, const char* codes, const char* items, const char* flags = "");
  // @cmember Aggiunge runtime un campo memo alla maschera
  WINDOW add_memo (short id, int page, const char* prompt, int x, int y, int dx = 78, int dy = 4, const char* flags = "");
  // @cmember Aggiunge runtime un campo zoom alla maschera
  WINDOW add_zoom (short id, int page, const char* prompt, int x, int y, int dim, const char* flags = "", int width = 0);

  // @cmember Ritorna il numero di campi della maschera
  int fields() const
  { return _field.items(); }
  // @cmember Ritorna il numero di sheet della maschera
  int sheets() const
  { return _sheets; }

  // @cmember Setta la modalita' di utilizzo della maschera
  void set_mode(int m)
  { _mode = m; }
  // @cmember Ritorna la modalita' corrente di utilizzo della maschera
  int mode() const
  { return _mode; }

  // @cmember Setta il valore attuale della valuta
  void set_exchange(bool show_value, const real& nuo);
  // @cmember Ritorna il valore attuale del cambio
  const real& exchange() const
  { return _exchange; }

  // @cmember Controlla i campi di una maschera (TRUE se tutti validi)
  bool check_fields();
  // @cmember Mette il contenuto dei campi a video in stringhe interne
  void get_mask_fields();
  // @cmember Forza la chiusura della maschera
  virtual bool stop_run(KEY key);
  // @cmember Controlla se la maschera puo' essere chiusa (TRUE se puo' esserlo)
  virtual bool can_be_closed() const;

  // @cmember Permette di aprire una maschera
  virtual void open();
  // @cmember Permette di chiudere una maschera
  virtual void close();
  // @cmember Permette di attivare/disattivare tutta la pagina
  virtual void activate(bool on = TRUE);

  // @cmember Converte un identificatore di campo nella sua posizione
  int id2pos(short id) const;
  // @cmember Ritorna l'id del campo che sta prendendo il focus, DLG_NULL se non esiste
  short next_fld() const
  { return _next_fld;}
  // @cmember Ritorna il campo i-esimo della maschera
  TMask_field& fld(int i) const
  { return (TMask_field&)_field[i]; }
  // @cmember Ritorna il campo contraddistinto dall'identificatore passato
  TMask_field& field(short id) const;
  // @cmember Ritorna il campo di edit contraddistinto dall'identificatore passato
  TEdit_field& efield(short id) const;

  // @cmember Setta il campo con una stringa
  virtual void set(short fld_id, const char* str, bool hit=FALSE);
  // @cmember Setta il campo con un reale
  void set(short fld_id, const real& num, bool hit=FALSE);
  // @cmember Setta il campo con una data
  void set(short fld_id, const TDate& day, bool hit=FALSE);
  // @cmember Setta il campo con un valore
  void set(short fld_id, long num, bool hit=FALSE);
  // @cmember Ritorna il contenuto del campo <p fld_id> sotto forma di stringa
  virtual const TString& get(short fld_id) const;
  // @cmember Ritorna il contenuto del campo <p fld_id> sotto forma di long
  long get_long(short fld_id) const;
  // @cmember Ritorna il contenuto del campo <p fld_id> sotto forma di int
  //              (chiama <mf TMask::get_long>)
  int get_int(short fld_id) const
  { return (int)get_long(fld_id); }
  // @cmember Ritorna il contenuto del campo <p fld_id> sotto forma di bool
  bool get_bool(short fld_id) const;

  // @cmember Indica quale campo deve ricevere per primo il focus nella maschera
  int first_focus(short id);
  // @cmember Setta il focus al campo corrente
  void set_focus();
  // @cmember Muove il focus al prossimo o al precedente controllo valido
  void move_focus_field(int num);
  // @cmember Setta il focus al campo la cui finestra e' <p win>
  void set_focus_win(WINDOW win, bool force);
  // @cmember Ritorna il numero del controllo che possiede il focus
  TMask_field& focus_field() const
  { return fld(_focus); }
  // @cmember Disabilita la lettura dei check della maschera
  void disable_starting_check()
  { _should_check = FALSE;}

  // @cmember Assegna una azione al tasto non standard
  virtual bool on_key(KEY key);
  // @cmember Aggiorna i campi con i valori salvati una volta che non ci sono processi attivi
  virtual void on_idle();
  // @cmember Aggiorna in tutti campi della maschera, che fanno riferimento ad una ditta,
  //              con il riferimento alla ditta attuale
  virtual void on_firm_change();

  // @cmember Abilita/disabilita un campo
  virtual void enable(short fld_id, bool on = TRUE);
  // @cmember Disabilita un campo (chiama <mf TMask::enable>)
  void disable(short fld_id)
  { enable(fld_id, FALSE); }
  // @cmember Riporta il cmpo allo stato di abilitazione iniziale
  void enable_default(short fld_id = -1);

  // @cmember Forza la visualizzazione della pagina p
  void show_page(int p);
  // @cmember Abilita/disabilita una pagina e tutte le successive
  void enable_page(byte p, bool on = TRUE);
  // @cmember Disabilita una pagina e tutte le successive (chiama <mf TMask::enable_page>)
  void disable_page(byte p)
  { enable_page(p, FALSE); }
  // @cmember Controlla se una pagina e' disabilitata (TRUE se disabilitata)
  bool page_enabled(byte p) const;

  // @cmember Ritorna il numero di chiavi utilizzate nei campi della maschera
  byte num_keys() const;
  // @cmember Abilita/disabilita i campi di una chiave sulla maschera 
  void enable_key(byte key, bool on = TRUE);
  // @cmember Disabilita i campi di una chiave sulla maschera (chiama <mf TMask::enable_key>)
  void disable_key(byte key)
  { enable_key(key, FALSE); }
  // @cmember Ritorna il l'identificatore di un campo della chiave <p key>
  short get_key_field(byte key, bool first) const;
  // @cmember Controlla se la chiave <p key> ha un valore significativo 
  //                              (TRUE se il valore e' valido)
  bool key_valid(int key) const;

  // @cmember Permette di mostrare/nascondere un campo
  virtual void show(short fld_id = -1, bool on = TRUE);
  // @cmember Permette di nascondere un campo (chiama <mf TMask::show>)
  void hide(short fld_id = -1)
  { show(fld_id, FALSE); }
  // @cmember Rimette lo stato di default del campo
  void show_default(short fld_id = -1);

  // @cmember Rimette lo stato di default del campo
  void reset(short fld_id = -1);
  // @cmember Riporta il valori originali nel campo
  void undo(short fld_id = -1);

  // @cmember Legge, dalla relazione <p Trelation>, i valori del campo con specifica FIELD
  void autoload(const TRelation*);
  // @cmember Scrive, dalla relazione <p Trelation>, i valori del campo con specifica FIELD
  void autosave(TRelation*) const;

  // @cmember Permette di mandare un tasto ad un campo
  void send_key(KEY key, short id, TMask_field* from = NULL);
  // @cmember Permette di mandare un handler ad un controllo
  virtual void set_handler(short fld_id, CONTROL_HANDLER handler);
  // @cmember Permette di mandare un handler ad una maschera
  void set_handler(MASK_HANDLER handler);
  // @cmember Permette di settare il nome del file di salvataggio
  void set_workfile(const char* workfile)
  { _workfile = workfile; _lastpos = 0L;}
  // @cmember Permette di salvare il file di salvataggio
  bool save(bool append = FALSE) const;
  // @cmember Permette di leggere il file di salvataggio
  bool load(bool reset = FALSE);

  // @cmember Ritorna il primo campo dirty
  short dirty() const;
  
  // @cmember Setta lo sheet di cui la maschera gestisce le righe
  void set_sheet(TSheet_field* s) 
  { _sheet = s; }
  
  // @cmember Ritorna lo sheet che gestisce la maschera
  TSheet_field* get_sheet()
  { return _sheet; }

  // @cmember Ritorna se la maschera e' contenuta in uno sheet (TRUE se contenuta)
  bool is_sheetmask() const
  { return _sheet != NULL; }

  // @cmember Ritorna TRUE se la maschera non ha modalita' di utilizzo (vedi <t TMaskmode>)
  bool no_mode() const
  { return _mode == NO_MODE; }
  // @cmember Ritorna TRUE se la maschera e' in modalita' di richiesta (vedi <t TMaskmode>)
  bool query_mode() const
  { return _mode == MODE_QUERY || _mode == MODE_QUERYINS; }
  // @cmember Ritorna TRUE se la maschera e' in modalita' di modifica (vedi <t TMaskmode>)
  bool edit_mode() const
  { return _mode == MODE_MOD; }
  // @cmember Ritorna TRUE se la maschera e' in modalita' di inserimento (vedi <t TMaskmode>)
  bool insert_mode() const
  { return _mode == MODE_QUERYINS || _mode == MODE_INS; }

  // @cmember Ritorna il titolo della maschera
  virtual const char* get_caption() const;
  // @cmember Setta il titolo della maschera
  virtual void set_caption(const char* c);

  // @cmember Viene eseguita se il campo viene modificato???
  virtual bool on_dirty(TMask_field& c );
  
  // @cmember Ritorna la finestra della toolbar
  WINDOW toolwin() const
  { return _pagewin[MAX_PAGES]; }


};

#endif // __MASK_H
