#include "tk_spinbox.h"
#include <iostream>

const Ptr<TkOptionDef> TkSpinBox::OPT_ACTIVEBACKGROUND=new TkOptionDef("activebackground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_BACKGROUND=new TkOptionDef("background",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_BORDERWIDTH=new TkOptionDef("borderwidth",TkIntOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_BUTTONDOWNRELIEF=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_BUTTONUPRELIEF=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_COMMAND=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_CURSOR=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_DISABLEDBACKGROUND=new TkOptionDef("disabledbackground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_FONT=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_FOREGROUND=new TkOptionDef("foreground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_FORMAT=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_FROM=new TkOptionDef("from",TkDoubleOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_HIGHLIGHTBACKGROUND=new TkOptionDef("highlightbackground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_HIGHLIGHTCOLOR=new TkOptionDef("highlightcolor",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_HIGHLIGHTTHICKNESS=new TkOptionDef("highlightthickness",TkIntOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_INCREMENT=new TkOptionDef("increment",TkDoubleOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_INSERTBACKGROUND=new TkOptionDef("insertbackground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_INSERTOFFTIME=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_INSERTONTIME=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_INSERTWIDTH=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_INVALIDCOMMAND=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_JUSTIFY=new TkOptionDef("justify",TkJustifyOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_RELIEF=new TkOptionDef("relief",TkReliefOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_READONLYBACKGROUND=new TkOptionDef("readonlybackground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_REPEATDELAY=new TkOptionDef("repeatdelay",TkIntOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_SELECTBACKGROUND=new TkOptionDef("selectbackground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_SELECTBORDERWIDTH=new TkOptionDef("selectborderwidth",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_SELECTFOREGROUND=new TkOptionDef("selectforeground",TkColorOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_STATE=new TkOptionDef("state",Tk3StateOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_TAKEFOCUS=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_TEXTVARIABLE=new TkOptionDef("textvariable",TclStringVar::type,true,false);
const Ptr<TkOptionDef> TkSpinBox::OPT_TO=new TkOptionDef("to",TkDoubleOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_VALIDATE=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_VALIDATECOMMAND=0;
const Ptr<TkOptionDef> TkSpinBox::OPT_VALUES=new TkOptionDef("values",TkListOption::type,false);
const Ptr<TkOptionDef> TkSpinBox::OPT_WRAP=new TkOptionDef("wrap",TkBoolOption::type);
const Ptr<TkOptionDef> TkSpinBox::OPT_XSCROLLCOMMAND=0;

const Ptr<TkOptionDef> TkSpinBox::optAll[]=
{
	TkSpinBox::OPT_ACTIVEBACKGROUND,
	TkSpinBox::OPT_BACKGROUND,
	TkSpinBox::OPT_BORDERWIDTH,
	TkSpinBox::OPT_BUTTONDOWNRELIEF,
	TkSpinBox::OPT_BUTTONUPRELIEF,
	TkSpinBox::OPT_COMMAND,
	TkSpinBox::OPT_CURSOR,
	TkSpinBox::OPT_DISABLEDBACKGROUND,
	TkSpinBox::OPT_FONT,
	TkSpinBox::OPT_FOREGROUND,
	TkSpinBox::OPT_FORMAT,
	TkSpinBox::OPT_FROM,
	TkSpinBox::OPT_HIGHLIGHTBACKGROUND,
	TkSpinBox::OPT_HIGHLIGHTCOLOR,
	TkSpinBox::OPT_HIGHLIGHTTHICKNESS,
	TkSpinBox::OPT_INCREMENT,
	TkSpinBox::OPT_INSERTBACKGROUND,
	TkSpinBox::OPT_INSERTOFFTIME,
	TkSpinBox::OPT_INSERTONTIME,
	TkSpinBox::OPT_INSERTWIDTH,
	TkSpinBox::OPT_INVALIDCOMMAND,
	TkSpinBox::OPT_JUSTIFY,
	TkSpinBox::OPT_RELIEF,
	TkSpinBox::OPT_READONLYBACKGROUND,
	TkSpinBox::OPT_REPEATDELAY,
	TkSpinBox::OPT_SELECTBACKGROUND,
	TkSpinBox::OPT_SELECTBORDERWIDTH,
	TkSpinBox::OPT_SELECTFOREGROUND,
	TkSpinBox::OPT_STATE,
	TkSpinBox::OPT_TAKEFOCUS,
	TkSpinBox::OPT_TEXTVARIABLE,
	TkSpinBox::OPT_TO,
	TkSpinBox::OPT_VALIDATE,
	TkSpinBox::OPT_VALIDATECOMMAND,
	TkSpinBox::OPT_VALUES,
	TkSpinBox::OPT_WRAP,
	TkSpinBox::OPT_XSCROLLCOMMAND
};

const char* TkSpinBox::type="TkSpinBox";
const char* TkSpinBox::tkClass="spinbox";

const Ptr<TkOptionDef>* TkSpinBox::getOptionAll() const
{
	return TkSpinBox::optAll;
}

const char* TkSpinBox::getType() const
{
	return TkSpinBox::type;
}

const char* TkSpinBox::getTkClass() const
{
	return TkSpinBox::tkClass;
}

void TkSpinBox::doSerialize(TiXmlElement& element) const
{
	TkBase::doSerialize(element);
	
	element.SetAttribute("text",getText().c_str());
}

void TkSpinBox::doDeserialize(const TiXmlElement& element)
{
	TkBase::doDeserialize(element);
	
	const char* text=element.Attribute("text");
	setText(text);
//	cout<<getText()<<endl;
}

TObject* TkSpinBox::clone()
{
	TkSpinBox* obj=new TkSpinBox(interp);

	baseClone(obj);
	obj->setText(getText());

	return obj;
}

TkSpinBox::TkSpinBox(Ptr<TclInterp> interp):TkBase(interp),defaultVar(interp)
{
	setOption(TkSpinBox::OPT_TEXTVARIABLE,&defaultVar);
}

void TkSpinBox::setEnabled(bool value)
{
	if (value)
		setOption(TkSpinBox::OPT_STATE,new Tk3StateOption(Tk3StateOption::normal));
	else
		setOption(TkSpinBox::OPT_STATE,new Tk3StateOption(Tk3StateOption::disabled));	
}

bool TkSpinBox::isEnabled() const
{
	const string enabled=getStrOption(TkSpinBox::OPT_STATE);
	if (enabled=="disabled") return false;
	if (enabled=="readonly") return false;
	return true;
}

void TkSpinBox::setReadonly()
{
	setOption(TkSpinBox::OPT_STATE,new Tk3StateOption(Tk3StateOption::readonly));	
}

void TkSpinBox::setValues(const char* values[])
{
	setOption(TkSpinBox::OPT_VALUES,new TkListOption(values));
}

void TkSpinBox::setValues(const list<string>& values)
{
	setOption(TkSpinBox::OPT_VALUES,new TkListOption(values));
}	

int TkSpinBox::getValuesIndex() const
{
	TkListOption lst;
	lst.fromObject(getOption(TkSpinBox::OPT_VALUES));
	string text=getText();
	
	int index=0;
	for(TkListOption::const_iterator it=lst.begin();it!=lst.end();it++)
	{
		if (*it==text)
		{
			return index;
		}
		index++;
	}
	return -1;
}

int TkSpinBox::intValue() const
{
	return atoi(getText().c_str());
}
	
double TkSpinBox::doubleValue() const
{
	return atof(getText().c_str());
}

void TkSpinBox::setLimitFrom(double value)
{
	setOption(TkSpinBox::OPT_FROM,new TkDoubleOption(value));
	setOption(TkSpinBox::OPT_VALUES,new TkListOption());
}
    
void TkSpinBox::setLimitTo(double value)
{
	setOption(TkSpinBox::OPT_TO,new TkDoubleOption(value));
	setOption(TkSpinBox::OPT_VALUES,new TkListOption());
}

void TkSpinBox::setIncrement(double value)
{
	setOption(TkSpinBox::OPT_INCREMENT,new TkDoubleOption(value));
	setOption(TkSpinBox::OPT_VALUES,new TkListOption());
}

void TkSpinBox::setRange(double from,double to,double increment)
{
	setOption(TkSpinBox::OPT_FROM,new TkDoubleOption(from));
	setOption(TkSpinBox::OPT_TO,new TkDoubleOption(to));
	setOption(TkSpinBox::OPT_INCREMENT,new TkDoubleOption(increment));

	setOption(TkSpinBox::OPT_VALUES,new TkListOption());
}

const string& TkSpinBox::getText() const
{
	return *(new string(defaultVar.get()));
}

void TkSpinBox::setText(const string& text)
{
	defaultVar.set(text);
}

void TkSpinBox::setValue(double value)
{
	char buf[128];
	sprintf(buf,"%f",value);
	setText(string(buf));
}

void TkSpinBox::setValue(int value)
{
	char buf[128];
	sprintf(buf,"%d",value);
	setText(string(buf));
}

void TkSpinBox::addValueListener(TclVarListener* listener)
{
	defaultVar.addListener(listener);
}

void TkSpinBox::setBackgroundColor(TkColorOption* color)
{
	setOption(OPT_BACKGROUND,color);
}

Ptr<TkColorOption>& TkSpinBox::getBackgroundColor() const
{
	TkColorOption* colorOption=new TkColorOption();
	
	colorOption->fromObject(getOption(OPT_BACKGROUND));
	return *(new Ptr<TkColorOption>(colorOption));
}

void TkSpinBox::create()
{
	string text=getText();
	TkBase::create();
	if (text.size()) setText(text);
}
