/*	Public domain	*/

#ifndef _AGAR_WIDGET_NUMERICAL_H_
#define _AGAR_WIDGET_NUMERICAL_H_

#include <agar/gui/widget.h>
#include <agar/gui/textbox.h>
#include <agar/gui/button.h>
#include <agar/gui/ucombo.h>
#include <agar/gui/units.h>

#include <agar/gui/begin.h>

#ifndef AG_NUMERICAL_INPUT_MAX
#define AG_NUMERICAL_INPUT_MAX 128
#endif

typedef struct ag_numerical {
	struct ag_widget wid;        /* AG_Widget -> AG_Numerical */
	Uint flags;
#define AG_NUMERICAL_HFILL      0x01
#define AG_NUMERICAL_VFILL      0x02
#define AG_NUMERICAL_INT        0x04   /* Make the default binding an int */
                                       /* (default = float) */
#define AG_NUMERICAL_EXCL       0x08   /* Assume exclusive access to variable */
#define AG_NUMERICAL_READONLY   0x10   /* Read-only mode */
#define AG_NUMERICAL_SLOW       0x20   /* Update every 2s (default = 250ms) */
#define AG_NUMERICAL_NO_POS_INF 0x40   /* Disallow "inf" or infinity */
#define AG_NUMERICAL_NO_NEG_INF 0x80   /* Disallow "-inf" or negative infinity */
#define AG_NUMERICAL_NO_INF (AG_NUMERICAL_NO_POS_INF | AG_NUMERICAL_NO_NEG_INF)
#define AG_NUMERICAL_EXPAND     (AG_NUMERICAL_HFILL | AG_NUMERICAL_VFILL)

	char format[28];                     /* Print format (for reals) */
	const AG_Unit *_Nonnull unit;        /* Selected conversion unit */
	const AG_Unit *_Nonnull unitGroup;   /* Group of conversion unit */
	AG_UCombo *_Nullable units;          /* Unit selector */
	char inTxt[AG_NUMERICAL_INPUT_MAX];  /* Input text buffer */
	AG_Textbox *_Nonnull input;          /* Input textbox */
	AG_Button *_Nonnull incbu;           /* Increment button */
	AG_Button *_Nonnull decbu;           /* Decrement button */
	int wUnitSel, hUnitSel;              /* Size hints for entry box */
	int wPreUnit;                        /* Size hint for unit selector */
	Uint32 _pad;
	AG_Timer toUpdate;                   /* For refresh (not in EXCL mode) */
	AG_Timer toInc, toDec;               /* For keyboard increment/decrement */
} AG_Numerical;

#define   AGNUMERICAL(obj)      ((AG_Numerical *)(obj))
#define  AGcNUMERICAL(obj)      ((const AG_Numerical *)(obj))
#define  AG_NUMERICAL_ISA(o)    (((AGOBJECT(o)->cid & 0xff000000) >> 24) == 0x1B)
#define  AG_NUMERICAL_SELF()    AGNUMERICAL(  AG_OBJECT(0,         "AG_Widget:AG_Numerical:*") )
#define  AG_NUMERICAL_PTR(n)    AGNUMERICAL(  AG_OBJECT((n),       "AG_Widget:AG_Numerical:*") )
#define  AG_NUMERICAL_NAMED(n)  AGNUMERICAL(  AG_OBJECT_NAMED((n), "AG_Widget:AG_Numerical:*") )
#define AG_cNUMERICAL_SELF()   AGcNUMERICAL( AG_cOBJECT(0,         "AG_Widget:AG_Numerical:*") )
#define AG_cNUMERICAL_PTR(n)   AGcNUMERICAL( AG_cOBJECT((n),       "AG_Widget:AG_Numerical:*") )
#define AG_cNUMERICAL_NAMED(n) AGcNUMERICAL( AG_cOBJECT_NAMED((n), "AG_Widget:AG_Numerical:*") )

/* Begin generated block */
__BEGIN_DECLS
extern DECLSPEC AG_WidgetClass agNumericalClass;
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNew(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, ...) FORMAT_ATTRIBUTE(printf,4,5);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewS(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewInt(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, int *_Nonnull);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewIntR(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, int *_Nonnull, int,int);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewUint(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, Uint *_Nonnull);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewUintR(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, Uint *_Nonnull, Uint,Uint);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewFlt(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, float *_Nonnull);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewFltR(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, float *_Nonnull, float,float);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewDbl(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, double *_Nonnull);
extern DECLSPEC AG_Numerical *_Nonnull AG_NumericalNewDblR(void *_Nullable, Uint, const char *_Nullable, const char *_Nullable, double *_Nonnull, double,double);
extern DECLSPEC float AG_NumericalGetFlt(AG_Numerical *_Nonnull);
extern DECLSPEC double AG_NumericalGetDbl(AG_Numerical *_Nonnull);
extern DECLSPEC void AG_NumericalSizeHint(AG_Numerical *_Nonnull, const char *_Nullable);
extern DECLSPEC void AG_NumericalIncrement(AG_Numerical *_Nonnull);
extern DECLSPEC void AG_NumericalDecrement(AG_Numerical *_Nonnull);
extern DECLSPEC void AG_NumericalUpdate(AG_Numerical *_Nonnull);
extern DECLSPEC void AG_NumericalSelectUnit(AG_Numerical *_Nonnull, const char *_Nonnull);
extern DECLSPEC int AG_NumericalSetUnitSystem(AG_Numerical *_Nonnull, const char *_Nonnull);
extern DECLSPEC void AG_NumericalSetWriteable(AG_Numerical *_Nonnull, int);
extern DECLSPEC void AG_NumericalSetPrecision(AG_Numerical *_Nonnull, const char *_Nonnull, int);
extern DECLSPEC int AG_NumericalGetInt(AG_Numerical *_Nonnull);
#define AG_NumericalGetUint(n) ((Uint)AG_NumericalGetInt(n))
extern DECLSPEC Uint32 AG_NumericalGetUint32(AG_Numerical *_Nonnull);
# define AG_NumericalGetUint8(n) ((Uint8)AG_NumericalGetUint32(n))
# define AG_NumericalGetUint16(n) ((Uint16)AG_NumericalGetUint32(n))
# define AG_NumericalGetSint8(n) ((Sint8)AG_NumericalGetUint32(n))
# define AG_NumericalGetSint16(n) ((Sint16)AG_NumericalGetUint32(n))
# define AG_NumericalGetSint32(n) ((Sint32)AG_NumericalGetUint32(n))
#ifdef AG_HAVE_64BIT
extern DECLSPEC Uint64 AG_NumericalGetUint64(AG_Numerical *_Nonnull);
#define AG_NumericalGetSint64(n) ((Sint64)AG_NumericalGetUint64(n))
#endif
__END_DECLS
/* Close generated block */

#include <agar/gui/close.h>
#endif /* _AGAR_WIDGET_NUMERICAL_H_ */
