#include "../modulemanager/modulemanager.h"

#include "propertyeditor.h"
#include "designer.h"

const char* PropertyEditor::type="PropertyEditor";

class PropertyEditor::MyListValueListener:public ButtonPressListener
{
	PropertyEditor* parent;
public:
	MyListValueListener(PropertyEditor* parent):parent(parent)
	{
	}
	void onButtonPress(EHeader& header,int button,const string& state,int x,int y,int x_root,int y_root)
	{
		TkBase* base=(TkBase*)parent->object.asObject();
		if (header.source==parent->propValueInsert.asObject())
		{
			if (base->typeOf(TkListbox::type))
			{
				TclListVar* var=((TkListbox*)base)->getDefaultVariable();
				var->push_back(parent->propValue->getText());
			}
			if (base->typeOf(TkSpinBox::type))
			{
				TkListOption* opt=new TkListOption();

				opt->fromObject(base->getOption(TkSpinBox::OPT_VALUES));
				opt->push_back(parent->propValue->getText());

				base->setOption(TkSpinBox::OPT_VALUES,opt);
			}
		}
		if (header.source==parent->propValueClear.asObject())
		{
			if (base->typeOf(TkListbox::type))
			{
				TclListVar* var=((TkListbox*)base)->getDefaultVariable();
				var->clear();
			}
		}
		parent->propValue->setText("");
	}
};

class PropertyEditor::MyDeleteListener:public ButtonPressListener
{
	PropertyEditor* parent;
public:
	MyDeleteListener(PropertyEditor* parent):parent(parent) {}
	void onButtonPress(EHeader& header,int button,const string& state,int x,int y,int x_root,int y_root)
	{
		if (!((TkButton*)header.source)->isEnabled()) return;
        parent->object->getParent()->removeChild(parent->object);
		parent->window->removeAll();
	}
};

class MyWindowListener:public TkTopLevelListener
{
public:
	void onDestroy(TkTopLevel* source)
	{
		source->setWindowState(TkWinStateOption::withdrawn);
	}
};

class PropertyEditor::MyAnchorListener:public TclVarListener
{
	PropertyEditor* parent;
public:
	MyAnchorListener(PropertyEditor* parent):parent(parent)
	{
	}
	void valueUpdated(TclVar* variable)
	{
		TclStringVar* strVar=(TclStringVar*)variable;
		if (strVar->get()=="") return;
		TkAnchorOption* option=new	TkAnchorOption(strVar->get());
		TkBase* object=parent->object;
		if (object->typeOf(TkButton::type)) ((TkButton*)object)->setOption(TkButton::OPT_ANCHOR,option);
		if (object->typeOf(TkCheckButton::type)) ((TkCheckButton*)object)->setOption(TkCheckButton::OPT_ANCHOR,option);
		if (object->typeOf(TkRadioButton::type)) ((TkRadioButton*)object)->setOption(TkRadioButton::OPT_ANCHOR,option);
		if (object->typeOf(TkLabel::type)) ((TkLabel*)object)->setOption(TkLabel::OPT_ANCHOR,option);
	}
};

class PropertyEditor::MyEnabledListener:public TclVarListener
{
	PropertyEditor* parent;
public:
	MyEnabledListener(PropertyEditor* parent):parent(parent)
	{
	}
	void valueUpdated(TclVar* variable)
	{
		string strValue=((TclStringVar*)variable)->get();
		if (strValue=="readonly")
		{
			if (parent->object->typeOf(TkSpinBox::type)) ((TkSpinBox*)parent->object.asObject())->setReadonly();
			if (parent->object->typeOf(TkEntry::type))	 ((TkEntry*)parent->object.asObject())->setReadonly();
		}
		else
		{
			bool value=(strValue=="normal");
			if (parent->object->typeOf(TkButton::type))			((TkButton*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkRadioButton::type))	((TkRadioButton*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkCheckButton::type))	((TkCheckButton*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkEntry::type))			((TkEntry*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkLabel::type))			((TkLabel*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkListbox::type))		((TkListbox*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkSpinBox::type))		((TkSpinBox*)parent->object.asObject())->setEnabled(value);
			if (parent->object->typeOf(TkText::type))			((TkText*)parent->object.asObject())->setEnabled(value);
		}
	}
};

class PropertyEditor::MyResizeableListener:public TclVarListener
{
	PropertyEditor* editor;
public:
	MyResizeableListener(PropertyEditor* editor)
	{
		this->editor=editor;
	}
	void valueUpdated(TclVar* variable)
	{
		bool value=((TclBoolVar*)variable)->get();
		TkTopLevel* topLevel=(TkTopLevel*)editor->object.asObject();
		topLevel->setResizable(value,value);
	}
};

class PropertyEditor::MyBindTopLevelListener:public TclVarListener
{
	PropertyEditor* editor;
public:
	MyBindTopLevelListener(PropertyEditor* editor)
	{
		this->editor=editor;
	}
	void valueUpdated(TclVar* variable)
	{
		string value=((TclStringVar*)variable)->get();
		TkTopLevel* topLevel=(TkTopLevel*)editor->object.asObject();
		if (value=="NONE")
		{
			topLevel->setTag(Ptr<TXmlObject>());
		}
		else
		{
			ModuleManager* manager=editor->designer->getManager();
			ModuleType* moduleType=manager->getModuleType(value);
			topLevel->setTag(new MyModuleType(moduleType));
		}
	}
};

class PropertyEditor::MyBindVarListener:public event::DoubleListener
{
	PropertyEditor* editor;
public:
	MyBindVarListener(PropertyEditor* editor)
	{
		this->editor=editor;
	}
	void onDouble(EHeader& header,int button,int x,int y,int x_root,int y_root)
	{
        int cursor=editor->propBindVar->getCursor();
		TkBase* object=editor->object;
		MyModuleType* myModuleType=(MyModuleType*)object->getParent()->getTag().asObject();
		if (cursor==0)
		{
			object->setTag(Ptr<TXmlObject>());
			editor->propBindVarEntry->setText("NONE");
		}
		else
		{
            cursor--;
			VarDef* def=editor->curVars[cursor];
			object->setTag(new MyVarDef(def,myModuleType->moduleType));
			editor->propBindVarEntry->setText(def->getName());
		}
	}
};

class PropertyEditor::MyWrapListener:public TclVarListener
{
	PropertyEditor* parent;
public:
	MyWrapListener(PropertyEditor* parent):parent(parent)
	{
	}
	void valueUpdated(TclVar* variable)
	{
		bool boolVar=((TclBoolVar*)variable)->get();

		parent->object->setOption(TkSpinBox::OPT_WRAP,new TkBoolOption(boolVar));
	}
};

class PropertyEditor::MyGroupListener:public TclVarListener
{
	PropertyEditor* parent;
	typedef map<string,Ptr<TclVar> > t_groups;
	t_groups groups;
public:
	MyGroupListener(PropertyEditor* parent):parent(parent)
	{
	}
	void valueUpdated(TclVar* variable)
	{
		string str=((TclStringVar*)variable)->get();
		TkRadioButton* rbut=(TkRadioButton*)parent->object.asObject();
		rbut->setGroup(str);
	}
};

class PropertyEditor::MyPropertyEnterListener:public KeyPressListener
{
	PropertyEditor* parent;
public:
	MyPropertyEnterListener(PropertyEditor* parent):parent(parent)
	{
	}
	void onKeyPress(EHeader& header,int keyCode,const string& state,const string& printChar,const string& keySym,int keySymDecimal,int x_root,int y_root)
	{
		if (keyCode==13)
		{
			parent->handlePropertyChange(header.source);
		}
	}
};

class PropertyEditor::MyPropertySpinListener:public ButtonReleaseListener
{
	PropertyEditor* parent;
public:
	MyPropertySpinListener(PropertyEditor* parent):parent(parent)
	{
	}
	void onButtonRelease(EHeader& header,int button,const string& state,int x,int y,int x_root,int y_root)
	{
		parent->handlePropertyChange(header.source);
	}
};

PropertyEditor::PropertyEditor(Ptr<TclInterp>& interp,Designer* designer):
	fwe(TkGridConstraints::WEST|TkGridConstraints::EAST),
	fall(TkGridConstraints::WEST|TkGridConstraints::EAST|TkGridConstraints::SOUTH|TkGridConstraints::NORTH)
{
	this->interp=interp;
	this->designer=designer;

	window=new TkTopLevel(interp);
	window->setTitle("Properties");
	window->create();
	window->setWindowListener(new MyWindowListener());
	window->setLayoutManager(new TkGridLayout());
	window->setBounds(200,400,0,78);

	butDelete=new TkButton(interp,"delete");
	butDelete->addButtonPressListener(new MyDeleteListener(this));

	labName=new TkLabel(interp,"name",TkAnchorOption::w);
	propName=new TkEntry(interp);
	propName->addFocusOutListener(this);
	propName->addKeyPressListener(new MyPropertyEnterListener(this));
                
	labX=new TkLabel(interp,"x",TkAnchorOption::w);
	propX=new TkSpinBox(interp);
	propX->setRange(0,INT_MAX,1);
	propX->addFocusOutListener(this);
	propX->addKeyPressListener(new MyPropertyEnterListener(this));
	propX->addButtonReleaseListener(new MyPropertySpinListener(this));

	labY=new TkLabel(interp,"y",TkAnchorOption::w);
	propY=new TkSpinBox(interp);
	propY->setRange(0,INT_MAX,1);
	propY->addFocusOutListener(this);
	propY->addKeyPressListener(new MyPropertyEnterListener(this));
	propY->addButtonReleaseListener(new MyPropertySpinListener(this));


	labWidth=new TkLabel(interp,"width",TkAnchorOption::w);
	propWidth=new TkSpinBox(interp);
	propWidth->setRange(0,INT_MAX,1);
	propWidth->addFocusOutListener(this);
	propWidth->addKeyPressListener(new MyPropertyEnterListener(this));
	propWidth->addButtonReleaseListener(new MyPropertySpinListener(this));

	labHeight=new TkLabel(interp,"height",TkAnchorOption::w);
	propHeight=new TkSpinBox(interp);
	propHeight->setRange(0,INT_MAX,1);
	propHeight->addFocusOutListener(this);
	propHeight->addKeyPressListener(new MyPropertyEnterListener(this));
	propHeight->addButtonReleaseListener(new MyPropertySpinListener(this));

	labText=new TkLabel(interp,"text",TkAnchorOption::w);
	propText=new TkEntry(interp);
	propText->addFocusOutListener(this);
	propText->addKeyPressListener(new MyPropertyEnterListener(this));

	labSelected=new TkLabel(interp,"selected",TkAnchorOption::w);
	propSelected=new TkCheckButton(interp);

	labValue=new TkLabel(interp,"value",TkAnchorOption::w);
	propValue=new TkEntry(interp);
	Ptr<MyListValueListener> propValueListener=new MyListValueListener(this);
	propValueInsert=new TkButton(interp,"+");
	propValueInsert->addButtonPressListener(propValueListener);
	propValueClear=new TkButton(interp,"X");
	propValueClear->addButtonPressListener(propValueListener);
	propValueFrame=new TkFrame(interp);
	propValueFrame->setLayoutManager(new TkGridLayout());
	propValueFrame->addChild(propValue,new TkGridConstraints(0,0,1,2));
	propValueFrame->addChild(propValueInsert,new TkGridConstraints(0,3));
	propValueFrame->addChild(propValueClear,new TkGridConstraints(0,4));

	labFrom=new TkLabel(interp,"from",TkAnchorOption::w);
	propFrom=new TkEntry(interp);
	propFrom->setValidationDouble();
	propFrom->addFocusOutListener(this);
	propFrom->addKeyPressListener(new MyPropertyEnterListener(this));

	
	labTo=new TkLabel(interp,"to",TkAnchorOption::w);
	propTo=new TkEntry(interp);
	propTo->setValidationDouble();
	propTo->addFocusOutListener(this);
	propTo->addKeyPressListener(new MyPropertyEnterListener(this));

	labIncr=new TkLabel(interp,"increment",TkAnchorOption::w);
	propIncr=new TkEntry(interp);
	propIncr->setValidationDouble();
	propIncr->addFocusOutListener(this);
	propIncr->addKeyPressListener(new MyPropertyEnterListener(this));

	labTitle=new TkLabel(interp,"title",TkAnchorOption::w);
	propTitle=new TkEntry(interp);
	propTitle->addFocusOutListener(this);
	propTitle->addKeyPressListener(new MyPropertyEnterListener(this));

	labResizeable=new TkLabel(interp,"resizeable",TkAnchorOption::w);
	propResizeable=new TkCheckButton(interp);
	propResizeable->addValueListener(new MyResizeableListener(this));

	labEnabled=new TkLabel(interp,"state",TkAnchorOption::w);
	propEnabled=new TkSpinBox(interp);
	propEnabled->setOption(TkSpinBox::OPT_WRAP,new TkBoolOption(true));
	propEnabled->setReadonly();
	propEnabled->addValueListener(new MyEnabledListener(this));

	labAnchor=new TkLabel(interp,"anchor",TkAnchorOption::w);
	propAnchor=new TkSpinBox(interp);
	propAnchor->setValues(TkAnchorOption::enums);
	propAnchor->setReadonly();
	propAnchor->addValueListener(new MyAnchorListener(this));

	labWrap=new TkLabel(interp,"wrap",TkAnchorOption::w);
	propWrap=new TkCheckButton(interp);
	propWrap->addValueListener(new MyWrapListener(this));

	labBindTopLevel=new TkLabel(interp,"module type",TkAnchorOption::w);
	propBindTopLevel=new TkSpinBox(interp);
	propBindTopLevel->setReadonly();
	ModuleManager* manager=designer->getManager();
	list<string> values;
	values.push_back("NONE");
	for(ModuleManager::const_iterator it=manager->begin();it!=manager->end();it++)
	{
		values.push_back((*it)->getName());
	}
	propBindTopLevel->setValues(values);
	propBindTopLevel->addValueListener(new MyBindTopLevelListener(this));

	propBindVarFrame=new TkFrame(interp);
	propBindVarFrame->setLayoutManager(new TkGridLayout());

	labBindVar=new TkLabel(interp,"bind variable",TkAnchorOption::w);
	labBindVar->setOption(TkLabel::OPT_ANCHOR,new TkAnchorOption(TkAnchorOption::w));
	propBindVar=new TkListbox(interp);
	propBindVar->addDoubleListener(new MyBindVarListener(this));
	propBindVarScroll=new TkScrollBar(interp,TkOrientOption::vertical);
	propBindVar->setYScrollBar(propBindVarScroll);
	propBindVarEntry=new TkEntry(interp,"NONE");
	propBindVarEntry->setReadonly();

	propBindVarFrame->addChild(labBindVar,new TkGridConstraints(0,0,1,3,fall));
	propBindVarFrame->addChild(propBindVarEntry,new TkGridConstraints(0,3,1,3,fall));
	propBindVarFrame->addChild(propBindVarScroll,new TkGridConstraints(1,5,5,1,fall));
	propBindVarFrame->addChild(propBindVar,new TkGridConstraints(1,0,5,5,fall));

	labGroup=new TkLabel(interp,"group",TkAnchorOption::w);
	propGroup=new TkEntry(interp);
	propGroup->addValueListenter(new MyGroupListener(this));
}

void PropertyEditor::onButton(TkBase* source)
{
	TkButton* component=(TkButton*)object.asObject();

	if (source==propText)
	{
		component->setText(propText->getText());
	}
}

void PropertyEditor::onEntry(TkBase* source)
{
	TkEntry* component=(TkEntry*)object.asObject();

	if (source==propText)
	{
		component->setText(propText->getText());
	}
}

void PropertyEditor::onLabel(TkBase* source)
{
	TkLabel* component=(TkLabel*)object.asObject();

	if (source==propText)
	{
		component->setText(propText->getText());
	}
}

void PropertyEditor::onCheckButton(TkBase* source)
{
	TkCheckButton* component=(TkCheckButton*)object.asObject();

	if (source==propText)
	{
		component->setText(propText->getText());
	}
}

void PropertyEditor::onSpinbox(TkBase* source)
{
	TkSpinBox* component=(TkSpinBox*)object.asObject();

	if (source==propFrom)
	{
		component->setLimitFrom(propFrom->doubleValue());
	}
	if (source==propTo)
	{
		component->setLimitTo(propTo->doubleValue());
	}
	if (source==propIncr)
	{
		component->setIncrement(propIncr->doubleValue());
	}
}

void PropertyEditor::onRadioButton(TkBase* source)
{
	TkRadioButton* component=(TkRadioButton*)object.asObject();

	if (source==propText)
	{
		component->setText(propText->getText());
	}
}

void PropertyEditor::onTopLevel(TkBase* source)
{
	TkTopLevel* component=(TkTopLevel*)object.asObject();

	if (source==propTitle)
	{
		component->setTitle(propTitle->getText());
	}
}

void PropertyEditor::setObject(TkBase* object)
{
	window->removeAll();

	if (!this->object.isNull()&&this->object->typeOf(TkCheckButton::type))
	{
		TkCheckButton* chxButton=((TkCheckButton*)this->object.asObject());
		chxButton->setVariable((TclBoolVar*)(chxButton->getDefaultVar()));
		propSelected->setVariable((TclBoolVar*)(propSelected->getDefaultVar()));
	}

	if (!lastColor.isNull()&&!this->object.isNull())
	{
		this->object->setBackgroundColor(lastColor);
	}
	lastColor=object->getBackgroundColor();
	this->object=object;
	this->object->setBackgroundColor(new TkColorOption(255,0,0));
	int i=0;

	window->addChild(butDelete,new TkGridConstraints(i,0,1,2,fwe));
	if (object->typeOf(TkTopLevel::type))
		butDelete->setEnabled(false);
	else
		butDelete->setEnabled(true);
	i++;

	window->addChild(labName,new TkGridConstraints(i,0,fwe));
	window->addChild(propName,new TkGridConstraints(i,1,fwe));
	propName->setText(object->getName());
	i++;

	window->addChild(labX,new TkGridConstraints(i,0,fwe));
	window->addChild(propX,new TkGridConstraints(i,1,fwe));
	i++;

	window->addChild(labY,new TkGridConstraints(i,0,fwe));
	window->addChild(propY,new TkGridConstraints(i,1,fwe));
	i++;

	window->addChild(labWidth,new TkGridConstraints(i,0,fwe));
	window->addChild(propWidth,new TkGridConstraints(i,1,fwe));
	i++;

	window->addChild(labHeight,new TkGridConstraints(i,0,fwe));
	window->addChild(propHeight,new TkGridConstraints(i,1,fwe));
	i++;

	if (object->typeOf(TkButton::type)) setButton((TkButton*)object,i);
	if (object->typeOf(TkRadioButton::type)) setRadioButton((TkRadioButton*)object,i);
	if (object->typeOf(TkCheckButton::type)) setCheckButton((TkCheckButton*)object,i);
	if (object->typeOf(TkEntry::type)) setEntry((TkEntry*)object,i);
	if (object->typeOf(TkLabel::type)) setLabel((TkLabel*)object,i);
	if (object->typeOf(TkListbox::type)) setListbox((TkListbox*)object,i);
	if (object->typeOf(TkSpinBox::type)) setSpinBox((TkSpinBox*)object,i);
	if (object->typeOf(TkText::type)) setText((TkText*)object,i);
	if (object->typeOf(TkTopLevel::type)) setTopLevel((TkTopLevel*)object,i);

	TkPlaceConstraints* pc=(TkPlaceConstraints*)object->getConstraints().asObject();
	if (pc!=0)
	{
		propX->setValue(pc->x);
		propY->setValue(pc->y);
		propWidth->setValue(pc->width);
		propHeight->setValue(pc->height);
	}
	else
	{
		TkTopLevel* topLevel=(TkTopLevel*)object;
		const TkRectOption bounds=topLevel->getBounds();
		
		propX->setValue(bounds.x);
		propY->setValue(bounds.y);
		propWidth->setValue(bounds.width);
		propHeight->setValue(bounds.height);
	}
}

void PropertyEditor::setVisible(bool value)
{
	if (value) 
		window->setWindowState(TkWinStateOption::normal);
	else
		window->setWindowState(TkWinStateOption::withdrawn);
}


void PropertyEditor::setButton(TkButton* object,int &i)
{
	window->addChild(labText,new TkGridConstraints(i,0,fwe));
	window->addChild(propText,new TkGridConstraints(i,1,fwe));
	i++;
	
	propText->setText(object->getText());

	propAnchor->setEventsEnabled(false);
	window->addChild(labAnchor,new TkGridConstraints(i,0,fwe));
	window->addChild(propAnchor,new TkGridConstraints(i,1,fwe));
	propAnchor->setText(object->getStrOption(TkButton::OPT_ANCHOR));
	propAnchor->setEventsEnabled(true);
	i++;

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(TkStateOption::enums);
	propEnabled->setText(object->getStrOption(TkButton::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;
}

void PropertyEditor::setRadioButton(TkRadioButton* object,int &i)
{
	window->addChild(labText,new TkGridConstraints(i,0,fwe));
	window->addChild(propText,new TkGridConstraints(i,1,fwe));
	i++;
		
	propText->setText(object->getText());

	propAnchor->setEventsEnabled(false);
	window->addChild(labAnchor,new TkGridConstraints(i,0,fwe));
	window->addChild(propAnchor,new TkGridConstraints(i,1,fwe));
	propAnchor->setText(object->getStrOption(TkRadioButton::OPT_ANCHOR));
	propAnchor->setEventsEnabled(true);
	i++;

	propGroup->setEventsEnabled(false);
	propGroup->setText(object->getGroup());
	window->addChild(labGroup,new TkGridConstraints(i,0,fwe));
	window->addChild(propGroup,new TkGridConstraints(i,1,fwe));
	propGroup->setEventsEnabled(true);
	i++;

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(TkStateOption::enums);
	propEnabled->setText(object->getStrOption(TkRadioButton::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;
}

void PropertyEditor::setCheckButton(TkCheckButton* object,int &i)
{
	window->addChild(labText,new TkGridConstraints(i,0,fwe));
	window->addChild(propText,new TkGridConstraints(i,1,fwe));
	i++;
	
	propText->setText(object->getText());

	propAnchor->setEventsEnabled(false);
	window->addChild(labAnchor,new TkGridConstraints(i,0,fwe));
	window->addChild(propAnchor,new TkGridConstraints(i,1,fwe));
	propAnchor->setText(object->getStrOption(TkLabel::OPT_ANCHOR));
	propAnchor->setEventsEnabled(true);
	i++;

	window->addChild(labSelected,new TkGridConstraints(i,0,fwe));
	window->addChild(propSelected,new TkGridConstraints(i,1,fwe));
	i++;

	object->setVariable((TclBoolVar*)(propSelected->getDefaultVar()));

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(TkStateOption::enums);
	propEnabled->setText(object->getStrOption(TkCheckButton::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;

	if (object->getParent()->getTag()!=0)
	{
		MyVarDef* myVar=(MyVarDef*)object->getTag().asObject();
		if (myVar!=0)
		{
			propBindVarEntry->setText(myVar->def->getName());
		}
		else
		{
			propBindVarEntry->setText("NONE");
		}
		
		MyModuleType* moduleType=(MyModuleType*)object->getParent()->getTag().asObject();
        		
		window->addChild(propBindVarFrame,new TkGridConstraints(i,0,6,2,fall));
		i+=6;

		TclListVar* listVar=propBindVar->getDefaultVariable();
		listVar->clear();
		listVar->push_back("NONE");

		curVars.clear();

		Ptr<VarDef>* defs=moduleType->moduleType->getVariables();
		int cnt=0;
		while(!defs[cnt].isNull())
		{
			if (defs[cnt]->getIType()==VarDef::VAR_BOOL)
			{
				listVar->push_back(defs[cnt]->getName());
				curVars.push_back((VarDef*)defs[cnt].asObject());
			}
			cnt++;
		}
	}
}

void PropertyEditor::setEntry(TkEntry* object,int &i)
{
	window->addChild(labText,new TkGridConstraints(i,0,fwe));
	window->addChild(propText,new TkGridConstraints(i,1,fwe));
	i++;
	
	propText->setText(object->getText());

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(Tk3StateOption::enums);
	propEnabled->setText(object->getStrOption(TkEntry::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;

	if (object->getParent()->getTag()!=0)
	{
		MyVarDef* myVar=(MyVarDef*)object->getTag().asObject();
		if (myVar!=0)
		{
			propBindVarEntry->setText(myVar->def->getName());
		}
		else
		{
			propBindVarEntry->setText("NONE");
		}
		
		MyModuleType* moduleType=(MyModuleType*)object->getParent()->getTag().asObject();
        		
		window->addChild(propBindVarFrame,new TkGridConstraints(i,0,6,2,fall));
		i+=6;

		TclListVar* listVar=propBindVar->getDefaultVariable();
		listVar->clear();
		listVar->push_back("NONE");

		curVars.clear();

		Ptr<VarDef>* defs=moduleType->moduleType->getVariables();
		int cnt=0;
		while(!defs[cnt].isNull())
		{
			if (defs[cnt]->getIType()==VarDef::VAR_STRING)
			{
				listVar->push_back(defs[cnt]->getName());
				curVars.push_back((VarDef*)defs[cnt].asObject());
			}
			cnt++;
		}
	}
}

void PropertyEditor::setLabel(TkLabel* object,int &i)
{
	window->addChild(labText,new TkGridConstraints(i,0,fwe));
	window->addChild(propText,new TkGridConstraints(i,1,fwe));
	i++;
		
	propText->setText(object->getText());

	propAnchor->setEventsEnabled(false);
	window->addChild(labAnchor,new TkGridConstraints(i,0,fwe));
	window->addChild(propAnchor,new TkGridConstraints(i,1,fwe));
	propAnchor->setText(object->getStrOption(TkLabel::OPT_ANCHOR));
	propAnchor->setEventsEnabled(true);
	i++;

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(TkStateOption::enums);
	propEnabled->setText(object->getStrOption(TkLabel::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;
}

void PropertyEditor::setListbox(TkListbox* object,int &i)
{
	window->addChild(labValue,new TkGridConstraints(i,0,fwe));
	window->addChild(propValueFrame,new TkGridConstraints(i,1,fwe));
	i++;

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(TkStateOption::enums);
	propEnabled->setText(object->getStrOption(TkListbox::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;
}

void PropertyEditor::setSpinBox(TkSpinBox* object,int &i)
{
	TkDoubleOption doubleOption;
	Tcl_Obj* option;

	TkListOption values;
	values.fromObject(object->getOption(TkSpinBox::OPT_VALUES));

	propFrom->setEventsEnabled(false);
	propTo->setEventsEnabled(false);
	propIncr->setEventsEnabled(false);

	if (values.size()==0)
	{
		option=object->getOption(TkSpinBox::OPT_FROM);
		doubleOption.fromObject(option);
		propFrom->setText(doubleOption.toString());

		option=object->getOption(TkSpinBox::OPT_TO);
		doubleOption.fromObject(option);
		propTo->setText(doubleOption.toString());

		option=object->getOption(TkSpinBox::OPT_INCREMENT);
		doubleOption.fromObject(option);
		propIncr->setText(doubleOption.toString());
	}
	else
	{
		propFrom->setText("0");
		propTo->setText("0");
		propIncr->setText("0");
	}

	propFrom->setEventsEnabled(true);
	propTo->setEventsEnabled(true);
	propIncr->setEventsEnabled(true);

	window->addChild(labFrom,new TkGridConstraints(i,0,fwe));
	window->addChild(propFrom,new TkGridConstraints(i,1,fwe));
	i++;

	window->addChild(labTo,new TkGridConstraints(i,0,fwe));
	window->addChild(propTo,new TkGridConstraints(i,1,fwe));
	i++;

	window->addChild(labIncr,new TkGridConstraints(i,0,fwe));
	window->addChild(propIncr,new TkGridConstraints(i,1,fwe));
	i++;

	window->addChild(labValue,new TkGridConstraints(i,0,fwe));
	propValue->setText("");
	window->addChild(propValueFrame,new TkGridConstraints(i,1,fwe));
	i++;

	TkBoolOption wrapOpt;
	wrapOpt.fromObject(object->getOption(TkSpinBox::OPT_WRAP));
	propWrap->setSelected(wrapOpt.get());
	window->addChild(labWrap,new TkGridConstraints(i,0,fwe));
	window->addChild(propWrap,new TkGridConstraints(i,1,fwe));
	i++;

	propEnabled->setEventsEnabled(false);
	propEnabled->setValues(Tk3StateOption::enums);
	propEnabled->setText(object->getStrOption(TkSpinBox::OPT_STATE));
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;

	if (object->getParent()->getTag()!=0)
	{
		MyVarDef* myVar=(MyVarDef*)object->getTag().asObject();
		if (myVar!=0)
		{
			propBindVarEntry->setText(myVar->def->getName());
		}
		else
		{
			propBindVarEntry->setText("NONE");
		}
		
		MyModuleType* moduleType=(MyModuleType*)object->getParent()->getTag().asObject();
        		
		window->addChild(propBindVarFrame,new TkGridConstraints(i,0,6,2,fall));
		i+=6;

		TclListVar* listVar=propBindVar->getDefaultVariable();
		listVar->clear();
		listVar->push_back("NONE");

		curVars.clear();

		Ptr<VarDef>* defs=moduleType->moduleType->getVariables();
		int cnt=0;
		while(!defs[cnt].isNull())
		{
			if (defs[cnt]->getIType()==VarDef::VAR_INT||
				defs[cnt]->getIType()==VarDef::VAR_DOUBLE)
			{
				listVar->push_back(defs[cnt]->getName());
				curVars.push_back((VarDef*)defs[cnt].asObject());
			}
			cnt++;
		}
	}
}

void PropertyEditor::setText(TkText* object,int &i)
{
	propEnabled->setEventsEnabled(false);
	propEnabled->setText(object->getStrOption(TkText::OPT_STATE));
	propEnabled->setValues(TkStateOption::enums);
	window->addChild(labEnabled,new TkGridConstraints(i,0,fwe));
	window->addChild(propEnabled,new TkGridConstraints(i,1,fwe));
	propEnabled->setEventsEnabled(true);
	i++;
}

void PropertyEditor::setTopLevel(TkTopLevel* object,int &i)
{
	window->addChild(labTitle,new TkGridConstraints(i,0,fwe));
	window->addChild(propTitle,new TkGridConstraints(i,1,fwe));
	propTitle->setText(object->getTitle());
	i++;

	window->addChild(labResizeable,new TkGridConstraints(i,0,fwe));
	window->addChild(propResizeable,new TkGridConstraints(i,1,fwe));
	propResizeable->setSelected(object->isResizableHeight());
	i++;

	window->addChild(labBindTopLevel,new TkGridConstraints(i,0,fwe));
	propBindTopLevel->setEventsEnabled(false);
	window->addChild(propBindTopLevel,new TkGridConstraints(i,1,fwe));
	i++;
	if (!object->getTag().isNull())
	{
		Ptr<MyModuleType> moduleType=(MyModuleType*)object->getTag().asObject();
		propBindTopLevel->setText(moduleType->moduleType->getName());
	}
	else
	{
		propBindTopLevel->setText("NONE");
	}
	propBindTopLevel->setEventsEnabled(true);
}

void PropertyEditor::handlePropertyChange(TkBase* source)
{
	if (object.isNull()) return;

	if (source==propName)
	{
		object->setName(propName->getText());
		return;
	}

	if (object->getType()==TkTopLevel::type)
	{
		if (source==propX||source==propY||source==propWidth||source==propHeight)
		{
			setBounds();
			return;
		}
	}

	TkPlaceConstraints* pc=(TkPlaceConstraints*)object->getConstraints().asObject();

	if (source==propX)
	{
		pc->x=(float)((TkSpinBox*)source)->doubleValue();
		object->invalidate();
		return;
	}

	if (source==propY)
	{
		pc->y=(float)((TkSpinBox*)source)->doubleValue();
		object->invalidate();
		return;
	}

	if (source==propWidth)
	{
		pc->width=(float)((TkSpinBox*)source)->doubleValue();
		object->invalidate();
		return;
	}

	if (source==propHeight)
	{
		pc->height=(float)((TkSpinBox*)source)->doubleValue();
		object->invalidate();
		return;
	}

	if (object->typeOf(TkButton::type))
	{
		onButton(source);
		return;
	}
		
	if (object->typeOf(TkLabel::type))
	{
		onLabel(source);
		return;
	}

	if (object->typeOf(TkEntry::type))
	{
		onEntry(source);
		return;
	}

	if (object->typeOf(TkRadioButton::type))
	{
		onRadioButton(source);
		return;
	}

	if (object->typeOf(TkCheckButton::type))
	{
		onCheckButton(source);
		return;
	}

	if (object->typeOf(TkSpinBox::type))
	{
		onSpinbox(source);
		return;
	}

	if (object->typeOf(TkTopLevel::type))
	{
		onTopLevel(source);
		return;
	}
}

void PropertyEditor::beforeSave()
{
	saveColor=false;
	if (!object.isNull()&&!lastColor.isNull())
	{
		object->setBackgroundColor(lastColor);
		saveColor=true;
	}
}

void PropertyEditor::afterSave()
{
	if (saveColor)
	{
		object->setBackgroundColor(new TkColorOption(255,0,0));
	}
	saveColor=false;
}
