/***************************************************************************
                          SIMPLY POWERFUL TOOLKIT (SPTK)
                          ccontrol.h  -  description
                             -------------------
    begin                : Tue Apr 4 2000
    copyright            : (C) 2000-2005 by Alexey S.Parshin
    email                : alexeyp@gmail.com
 ***************************************************************************/

/***************************************************************************
   This library is free software; you can redistribute it and/or modify it 
   under the terms of the GNU Library General Public License as published by
   the Free Software Foundation; either version 2 of the License, or (at 
   your option) any later version.

   This library 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 Library
   General Public License for more details.

   You should have received a copy of the GNU Library General Public License
   along with this library; if not, write to the Free Software Foundation, 
   Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.

   Please report all bugs and problems to "alexeyp@gmail.com"
 ***************************************************************************/

#ifndef __CCONTROL_H__
#define __CCONTROL_H__

#include <FL/Fl_Group.H>
#include <FL/Fl_Menu_Button.H>
#include <sptk3/CEvent.h>

#include <sptk3/CQuery.h>
#include <sptk3/CLayoutClient.h>

#include <string>

/// @addtogroup gui GUI Classes
/// @{

/// Control kind is the constant to report the internal SPTK RTTI.
enum CControlKind {
   DCV_UNKNOWN,				///< Control kind is unknown
   DCV_BOX=1,					///< Control is a box of plain text
   DCV_HTMLBOX=2,				///< Control is a box of HTML text
   DCV_STRING=4,				///< Control is a text input (single line)
   DCV_MEMO=8,					///< Control is a text input (multiple lines)
   DCV_INTEGER=16,			///< Control is an integer value input
   DCV_FLOAT=32,				///< Control is an integer value input
   DCV_DATE=64,				///< Control is a date input
   DCV_TIME=128,				///< Control is a time input
   DCV_DATETIME=256,			///< Control is a date and time input
   DCV_DATEINTERVAL=512,	///< Control is a date interval input
   DCV_COMBO=1024,			///< Control is a combobox
   DCV_INTVALUECOMBO=2048,	///< Control is a combobox with int key value
   DCV_LISTBOX=4096,			///< Control is a listbox
   DCV_CHECKBUTTONS=8192,	///< Control is a set of check buttons
   DCV_RADIOBUTTONS=16384,	///< Control is a set of radio buttons
   DCV_PHONE=32768,			///< Control is a phone number input
   DCV_TREEVIEW=655363		///< Control is a tree widget
};

/// Special control flags (used as bit combination)
enum FGENTRYFLAGS {
   FGE_NONE,					///< No flags
   FGE_SPELLCHECK=1,			///< Requires spell checking
   FGE_MANDATORY=2,			///< Must have some value
   FGE_CFIELD=4,				///< Is a custom field
   FGE_SINGLELINEENTRY=256,///< Is a single-line entry
   FGE_MULTILINEENTRY=512	///< Is a multi-line entry
};

/// Default height for the single-row edit control
#define SINGLE_EDIT_ENTRY_HEIGHT 23

class CDBDropDownList;
class CPackedStrings;
class CColumnList;
class CStrings;

/// Internal field name validation
SP_EXPORT bool checkFieldName(std::string fldName);

/// @brief Base class for most of SPTK widgets.
///
/// It is a group used as a container for the widget(s) inside.
/// Every CControl has a field name, and it can be a layout client.
class SP_EXPORT CControl : public Fl_Group, public CLayoutClient {
   friend class CInternalComboBoxPanel;
   friend class CEditor;
   friend class CBaseButton;
   friend class CRadioButton;
   friend class CCheckButton;
   friend class CInput_;

   /// Constructor initializer
   void ctor_init(const char *);

protected:

   bool              m_limited;     ///< Control has the defined min and max values
   std::string       m_label;       ///< Control label
   unsigned          m_labelWidth;  ///< Control label width (on the left)
   Fl_Color          m_labelColor;  ///< Control label color
   Fl_Color          m_textColor;   ///< Control text color
   Fl_Font           m_textFont;    ///< Control text font
   uchar             m_textSize;    ///< Control text font size
   std::string       m_fieldName;   ///< Field name for the universal data connection
   Fl_Widget*        m_control;     ///< The main widget inside the control.
   int               m_tag;         ///< Control's special data tag
   /// Control's special flags (a bit combination of FGENTRYFLAGS). 
   /// @see FGENTRYFLAGS for details.   
   unsigned          m_controlFlags;
   Fl_Menu_Button   *m_menuButton;  ///< Control's menu button - to show right-mouse click menu
   CEventInfo        m_event;       ///< The last SPTK event inside this control.
   bool              m_hasFocus;    ///< Does the control have focus?

protected:

   /// Does the control contain focus?
   bool containsFocus() const;

   /// Internal focus notification on focus change
   void notifyFocus(bool gotFocus=true);

   /// Internal focus notification on focus change
   virtual void     onEnter();

   /// Internal focus notification on focus change
   virtual void     onExit();

   /// Computes the label height based on the labelFont() and labelWidth()
   unsigned         labelHeight() const;

   /// Special handle() method
   int              handle(int);

   /// Internal callback function
   static void internalCallback(Fl_Widget *internalWidget,void *data);

public:   

   /// Constructor in SPTK style 
   /// @param label const char *, label
   /// @param layoutSize int, widget align in layout
   /// @param layoutAlign CLayoutAlign, widget align in layout
   CControl(const char *label,int layoutSize=20,CLayoutAlign layoutAlign=SP_ALIGN_TOP);

#ifdef __COMPATIBILITY_MODE__    
   /// Constructor in FLTK style 
   /// @param x int, x-position
   /// @param y int, y-position
   /// @param w int, width
   /// @param h int, height
   /// @param label, const char * label
   CControl(int,int,int,int,const char * = 0);
#endif    

public:

   /// Resizes the control and inside widgets. 
   /// @param x int, x-position
   /// @param y int, y-position
   /// @param w int, width
   /// @param h int, height
   virtual void     resize(int x,int y,int w,int h);

   /// Draws the control
   virtual void     draw();

   /// Returns the control's user data tag
   virtual int      tag() const { return m_tag; }

   /// Sets the control's user data tag
   virtual void     tag(int t)  { m_tag = t; }

   /// Returns the control's text font
#if FL_MAJOR_VERSION < 2
   virtual Fl_Font  textFont() const;

   /// Sets the control's text font
   virtual void     textFont(Fl_Font);
#else
   virtual Font    *textFont() const;

   /// Sets the control's text font
   virtual void     textFont(Font *);
#endif

   /// Returns the control's text font size
   virtual uchar    textSize() const;
   /// Sets the control's text font size
   virtual void     textSize(uchar);

   /// Returns the control's text color
   virtual Fl_Color textColor() const;
   /// Sets the control's text color
   virtual void     textColor(Fl_Color);

   /// Returns the control's label color
   virtual Fl_Color labelColor() const;
   /// Sets the control's label color
   virtual void     labelColor(Fl_Color);

   /// Returns the control's background color
   virtual Fl_Color color() const;
   /// Sets the control's background color
   virtual void     color(Fl_Color);

   /// Returns the control's flags
   unsigned flags() const { return m_controlFlags; }

   /// Sets the control's flags
   void flags(unsigned flags);

   /// Returns main widget inside the container
   Fl_Widget*       control() const { return m_control; }

   /// Returns controls' label
   std::string          label() const { return m_label; }
   /// Sets controls' label
   void             label(const std::string);

   /// Returns controls' menu
   Fl_Menu_*        menu() const;
   /// Sets controls' menu
   void             menu(const Fl_Menu_Item*);

   /// Returns controls' label font
   Fl_Font          labelFont() const { return labelfont(); }
   /// Sets controls' label font 
   void             labelSize(Fl_Font f) { labelfont(f); }

   /// Returns controls' label font size
   uchar            labelSize() const;
   /// Sets controls' label font size
   void             labelSize(uchar);

   /// Returns controls' label width
   unsigned         labelWidth() const { return m_labelWidth; }
   /// Sets controls' label width
   void             labelWidth(unsigned);

   /// Returns controls' max input length, if applicable
   virtual int      maxLength() const { return 0; }
   /// Sets controls' max input length, if applicable
   virtual void     maxLength(int) {}

   /// Returns controls' field name for universal data connection
   virtual const std::string& fieldName() const { return m_fieldName; }
   /// Sets controls' field name for universal data connection
   virtual void     fieldName(const std::string&);

   /// Returns controls' kind (internal SPTK RTTI).
   virtual CControlKind kind() const = 0;

   /// Returns controls' class name (internal SPTK RTTI).
   virtual std::string className() const { return "CControl"; }

   /// Sets the control to empty text (for the input entries)
   /// or to no selection state / default selection (for the lists)
   virtual void     reset() { data(""); }

   /// Loads control data from query fields
   virtual void     load(CQuery *) = 0;
   /// Saves control data to query params
   virtual void     save(CQuery *) = 0;

   /// Returns true if the control state is valid, and the data is inside the limits
   /// if applicable
   virtual bool     valid() const = 0;

   /// The universal data connector,
   /// @returns control data
   virtual CVariant data() const { return CVariant(""); }

   /// The universal data connector, sets control data
   virtual void     data(const CVariant v) {}

   /// Fires the event by this control
   void             fireEvent(CEvent ev,long arg);

   /// Returns the last event fired by this control
   const CEventInfo& event() const { return m_event; }

   /// Returns the event type for the last fired by this control
   CEvent           eventType() const { return m_event.type(); }
   /// Returns the event argument for the last fired by this control
   int              eventArgument() const { return m_event.argument(); }

   /// Converts control name to control kind
   static  CControlKind controlNameToType(std::string typeName,int& maxLength,std::string values="");

   /// Control data assignment
   CControl& operator = (const std::string& str) { data(str); return *this; }
   /// Control data assignment
   CControl& operator = (const char *str)    { data(str); return *this; }
   /// Control data assignment
   CControl& operator = (int v)              { data(v); return *this;   }
   /// Control data assignment
   CControl& operator = (unsigned v)         { data(v); return *this;   }
   /// Control data assignment
   CControl& operator = (float v)            { data(v); return *this;   }
   /// Control data assignment
   CControl& operator = (double v)           { data(v); return *this;   }
   /// Control data assignment
   CControl& operator = (CDateTime& dt)      { data(dt); return *this;  }
   /// Control data assignment
   CControl& operator = (CField& fld)        { data(fld); return *this; }

   /// Control data conversion
   operator std::string () const   { return data(); }
   /// Control data conversion
   operator int () const       { return data(); }
   /// Control data conversion
   operator unsigned () const  { return data(); }
   /// Control data conversion
   operator float () const     { return data(); }
   /// Control data conversion
   operator double () const    { return data(); }
   /// Control data conversion
   operator CDateTime () const { return data(); }

public:   
   /// Default callback function to support CControl default menu item 'Copy'
   static void defaultControlMenuCopy(Fl_Widget *,void *);

   /// Default callback function to support CControl default menu item 'Delete'
   static void defaultControlMenuCut(Fl_Widget *,void *);

   /// Default callback function to support CControl default menu item 'Paste'
   static void defaultControlMenuPaste(Fl_Widget *,void *);

   /// Default callback function to support CControl default menu item 'Clear'
   static void defaultControlMenuClear(Fl_Widget *,void *);

   /// CControl default menu 
   static const Fl_Menu_Item defaultControlMenu[];
};

/// The utility function that allows to create a control with one step
/// @param controlKind int, a control kind
/// @param label std::string, a control label
/// @param fieldName std::string, a control field name
/// @param layoutSize int, a control layout size
CControl *createControl(int controlKind,std::string label,std::string fieldName,int layoutSize);

/// @}

#endif
