#ifndef __CONTROLS_H
#define __CONTROLS_H

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

class TWindow;      // __WINDOW_H
class TMask_field;  // __MASKFLD_H

#ifndef INCL_XI
#define XI_INTERNAL
#include <xi.h>
#endif

void init_controls();
void free_controls();
XVT_FNTID xvt_default_font(bool bold = FALSE);
XVT_FNTID xvt_load_default_font();

WINDOW create_interface(WINDOW parent, short x, short y, short dx, short dy,
                        const char* caption, TWindow* mask, bool tags);

void attach_interface(WINDOW win, COLOR back = COLOR_WHITE);
short get_focus_id(WINDOW win);

///////////////////////////////////////////////////////////
// Custom control
///////////////////////////////////////////////////////////

// @doc INTERNAL

// @class TControl | Classe per la creazione di controlli
class TControl : public TObject
// @author:(INTERNAL) Guido

// @access:(INTERNAL) Private Member
{

// @access Protected Member
protected:
  // @cmember:(INTERNAL) Puntatore al controllo creato
  XI_OBJ* _obj;

  // @cmember:(INTERNAL) Puntatore al TMask_field eventualmente associato
  TMask_field* _fld;

  // @cmember Ricava l'interfaccia da una finestra
  XI_OBJ* get_interface(WINDOW win = NULL_WIN) const;
  
  // @cmember Cerca un controllo operabile (in avanti o all'indietro)
  XI_OBJ* find_operable(XI_OBJ* container, bool forward, bool normal) const;

  // @cmember Setta l'identificatore del prossimo controllo per il tasto TAB
  void set_tab_cid(XI_OBJ* obj, short id) const;

  void coord2rct(WINDOW win, short left, short top, short width, short height, RCT& rct) const;
  unsigned long flags2attr(const char* flags) const;
  void update_tab_cid();
  const char* parse_caption(const char* cap, bool& bold, COLOR& color) const;

  void change_attrib(unsigned long attr, bool on, XI_OBJ* obj = NULL);
  
  bool notify_key(KEY k);

// @access Public Member
public:
  TControl();
  virtual ~TControl();
  
  static KEY xiev_to_key(const XI_EVENT* xiev);

  virtual bool event_handler(XI_OBJ* itf, XI_EVENT* ep);

  bool is_edit_key(KEY k) const;

  // @cmember Ritorna l'identificatore assegnato al controllo
  short id() const { return _obj->cid; }
  WINDOW parent() const;                
  
  XI_OBJ_TYPE type() const { return _obj->type; }
  
  // @cmember Ritorna il prompt del controllo
  virtual const char* caption() const;
  // @cmember Setta il prompt del controllo
  virtual void set_caption(const char* c);

  // @cmember Abilita/disabilita il controllo
  virtual void enable(bool on = TRUE);
  void disable() { enable(FALSE); }
  
  // @cmember Mostra/nasconde il controllo
  virtual void show(bool on = TRUE);
  void hide() { show(FALSE); }
  
  void autoselect(bool on);
  
  // @cmember Forza il focus al controllo
  virtual void set_focus() const;
  
  RCT& get_rect(RCT& r) const;
  virtual void set_rect(const RCT& r);
  
  bool on_key(KEY k);
};


class TText_control : public TControl
{         
public: // TControl
  virtual void set_caption(const char* text);
  
public:
  TText_control(WINDOW win, short cid, 
                short left, short top, short width, short height,
                const char* flags, const char* text);
  virtual ~TText_control() {}
};


class TGroupbox_control : public TText_control
{
  XI_OBJ* _rct;      // Rettangolo del gruppo
 
public: // TControl
  virtual void show(bool on);

public:
  TGroupbox_control(WINDOW win, short cid, 
                short left, short top, short width, short height,
                const char* flags, const char* text);
  virtual ~TGroupbox_control() {}
};

class TField_control : public TControl
{             
protected:
  bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
  
  void create(WINDOW win, short cid, 
              short left, short top, 
              short width, short height, short maxlen, 
              const char* flags, const char* text, bool button);

  TField_control() {}
  
public:          
  // @cmember Mostra o nasconde il bottone associato
  void show_button(bool on);
  
  // @cmember Forza il focus al controllo
  virtual void set_focus() const;
       
  TField_control(WINDOW win, short cid, 
                 short left, short top, 
                 short width, short maxlen, 
                 const char* flags, const char* text);
  virtual ~TField_control() {}
};

class TMultiline_control : public TField_control
{             
public:
  TMultiline_control(WINDOW win, short cid, 
                     short left, short top, 
                     short width, short height, short maxlen, 
                     const char* flags, const char* text);
  virtual ~TMultiline_control() {}
};

class TButton_control : public TControl
{     
protected:
  void create(WINDOW win, short cid, 
              short left, short top, short width, short height,
              const char* flags, const char* text, 
              WIN_TYPE wc, XI_OBJ* container);

  virtual bool event_handler(XI_OBJ* itf, XI_EVENT* ep);

public:
  virtual void set_rect(const RCT& r);
                  
  bool checked() const;
  void check(bool on = TRUE);
  void uncheck() { check(FALSE); }
  bool toggle();

  XI_BTN_TYPE button_type() const;
  XI_OBJ* container() const;
                            
  TButton_control() {}
  virtual ~TButton_control() {}
};

class TPushbutton_control : public TButton_control
{   
  TString _caption;
  int _underscore;
  short _bmp_up, _bmp_dn;

protected:
  virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
  virtual const char* caption() const { return _caption; }
               
public:
  virtual void update();
  
  void set_bmp(short up, short dn);

  TPushbutton_control(WINDOW win, short cid, 
                      short left, short top, short width, short height,
                      const char* flags, const char* text,
                      short bmp_up = 0, short _bmp_dn = 0);
  virtual ~TPushbutton_control() {}
};

class TRadiobutton_control : public TButton_control
{                    
protected:  // TControl
  virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);
  virtual void set_focus() const;
  
protected:
  TRadiobutton_control() { }    // To be derived

public:
  // @cmember Abilita/disabilita il controllo
  virtual void enable(bool on = TRUE);
  // @cmember Mostra/nasconde il controllo
  virtual void show(bool on = TRUE);

  byte get_checked() const;
  void check_button(byte b);
  
  void show_button(byte b, bool on = TRUE);
  void hide_button(byte b) { show_button(b, FALSE); }

  TRadiobutton_control(WINDOW win, short cid, 
                      short left, short top, short width, short height,
                      const char* flags, const char* text);
  virtual ~TRadiobutton_control() {}
};

class TTagbutton_control : public TRadiobutton_control
{                    
protected:   // TControl
  virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);

public:                                       
  virtual void set_caption(const char* text);

  TTagbutton_control(WINDOW win, short cid, 
                     short left, short top, short width, short height,
                     const char* flags, const char* text, int tag);
  virtual ~TTagbutton_control() {}
};


class TCheckbox_control : public TButton_control
{
public:
  TCheckbox_control(WINDOW win, short cid, 
                    short left, short top, short width,
                    const char* flags, const char* text);
  virtual ~TCheckbox_control() {}
};
  
class TDropDownList : public TObject
{ 
  XI_OBJ*       _obj;
  XI_OBJ*       _xi_lst;            
  
  TToken_string _codes;
  TToken_string _values;                                                      
  
  int           _selected;
  bool          _open;
  bool          _displayed;          
  bool          _in_cell;

protected:  
  static void ddl_str_eh (XI_OBJ* itf, XI_EVENT* xiev);
  void update_selection(XI_EVENT* xiev) const;
  int calc_min_width();

public:
  const int selected() const { return _selected; }                       
  void open();
  void close();           
  bool is_open() const  { return _open; }
  bool displayed() const { return _displayed; }
                                                                         
  const char* item(int i)  { return _values.get(i);  } 
  int items() const { return _values.items(); } 
  long row2rec(int) const; 
  int rec2row(long rec) const;                       
  void set_values(const char* c, const char* v);

  bool select(int i, bool force = FALSE);
  bool select_by_initial(char c); 
  bool select_by_ofs(int n); 
  
  TDropDownList(XI_OBJ* o, const char* codes, const char* values);
  virtual ~TDropDownList() {}
};                                        
  
class TListbox_control : public TField_control
{                            
  friend class TDropDownList;  
  TDropDownList*  _ddl;                           

private:  
  void drop_down();

protected: // TTField_control
  virtual bool event_handler(XI_OBJ* itf, XI_EVENT* xiev);

public:
  void set_values(const char* c, const char* v);
  int  items() const             { return _ddl->items(); }
  bool select(int i)             { return _ddl->select(i);            }
  bool select_by_initial(char c) { return _ddl->select_by_initial(c); }
  bool select_by_ofs(int i)      { return _ddl->select_by_ofs(i);     }
  int  selected() const          { return _ddl->selected();    }
  
  TListbox_control(WINDOW win, short cid, 
                   short left, short top, short width,
                   const char* flags, const char* text, 
                   const char* codes, const char* values);
  virtual ~TListbox_control();
};



#endif
