#ifndef _PROPERTY_EDITOR_H_
#define _PROPERTY_EDITOR_H_

#include "../tk/gui/gui.h"
#include "appwindow.h"

#include "../modulemanager/vardef.h"
#include "../modulemanager/moduletype.h"

#include <list>

using namespace std;

class PropertyEditor:public FocusOutListener
{
	Ptr<TclInterp> interp;
	Designer* designer;
	Ptr<TkTopLevel> window;

	Ptr<TkBase> object;

	Ptr<TkLabel> labX,labY,labWidth,labHeight,
		labName,labText,labSelected,labValue,
		labFrom,labTo,labIncr,labTitle,labResizeable,
		labEnabled,labAnchor,labBindTopLevel,labBindVar,
		labWrap,labGroup;
		

	Ptr<TkEntry>   propName;

	Ptr<TkSpinBox> propX;
	Ptr<TkSpinBox> propY;
	Ptr<TkSpinBox> propWidth;
	Ptr<TkSpinBox> propHeight;

	Ptr<TkEntry>   propText;

	Ptr<TkCheckButton> propSelected;

	Ptr<TkFrame> propValueFrame;
	Ptr<TkEntry> propValue;
	Ptr<TkButton> propValueInsert;
	Ptr<TkButton> propValueClear;

	Ptr<TkEntry> propFrom,propTo,propIncr;

	Ptr<TkEntry> propTitle;
	Ptr<TkCheckButton> propResizeable;

	Ptr<TkSpinBox> propEnabled;

	Ptr<TkSpinBox> propAnchor;

	Ptr<TkButton> butDelete;

	Ptr<TkSpinBox> propBindTopLevel;

	Ptr<TkFrame> propBindVarFrame;
	Ptr<TkListbox> propBindVar;
	Ptr<TkScrollBar> propBindVarScroll;
	Ptr<TkEntry> propBindVarEntry;

	Ptr<TkCheckButton> propWrap;

	Ptr<TkEntry> propGroup;

	typedef vector<VarDef* > t_cur_vars;
	t_cur_vars curVars;

	class MyListValueListener; // handles event on adding item/clearing to list (spinbox,listbox)
	class MyDeleteListener;    // handles "DELETE-button-press" event (all)
	class MyEnabledListener;   // handles enable switching (all except toplevel)
	class MyAnchorListener;    // handles anchor changing (all widgets with label)
	class MyResizeableListener;  // handles changing window from resizeable to non-resizeable and vice versa (toplevel)
	class MyBindTopLevelListener; // handles binding top-level window to specific module-type (toplevel)
	class MyBindVarListener; // handles binding to specific variable
	class MyWrapListener;    // handles changing wrap (spinbox)
	class MyGroupListener;   // handles group changing (radiobutton)
	class MyPropertyEnterListener; // handles pressing enter in property
	class MyPropertySpinListener; //handles spinbox change

	void setBounds()
	{
		((TkTopLevel*)object.asObject())->setBounds(
			propWidth->intValue(),
			propHeight->intValue(),
			propX->intValue(),
			propY->intValue()
		);
	}
	const int fwe;
	const int fall;

	// "on*" functions are used for type-specific handling in handlePropertyChange() method
	void onButton(TkBase* source);
	void onEntry(TkBase* source);
	void onLabel(TkBase* source);
	void onCheckButton(TkBase* source);
	void onSpinbox(TkBase* source);
	void onRadioButton(TkBase* source);
	void onTopLevel(TkBase* source);

	// "set*" functions are used for type-specific handling in setObject() method
	void setButton(TkButton* object,int &i);
	void setRadioButton(TkRadioButton* object,int &i);
	void setCheckButton(TkCheckButton* object,int &i);
	void setEntry(TkEntry* object,int &i);
	void setLabel(TkLabel* object,int &i);
	void setListbox(TkListbox* object,int &i);
	void setSpinBox(TkSpinBox* object,int &i);
	void setText(TkText* object,int &i);
	void setTopLevel(TkTopLevel* object,int &i);

	Ptr<TkColorOption> lastColor;
	bool saveColor;
public:
	static const char* type;
	const char* getType() const
	{
		return type;
	}


	/**
	 * \brief get selected object (widget)
	 * \return selected object (widget)
	 */
	Ptr<TkBase>& getObject()
	{
		return object;
	}
	
	/**
	 * \brief quick-set place properties for widget
	 * \param x coordinate of widget
	 * \param y coordinate of widget
	 * \param width widget width
	 * \param height widget height;
	 */
	void setBoundValues(int x,int y,int width,int height)
	{
		propX->setValue(x);
		propY->setValue(y);
		propWidth->setValue(width);
		propHeight->setValue(height);
	}

	/**
	 * \brief ctor
	 * \param interp interpret
	 * \param designer designer
	 */
	PropertyEditor(Ptr<TclInterp>& interp,Designer* designer);

	void valueUpdated(TclVar* variable)
	{
		((TkCheckButton*)object.asObject())->setSelected(propSelected->isSelected());
	}

	/**
	 * \brief adjust property editor values due to widget passed
	 * \param object freshly selected widget
	 */
	void setObject(TkBase* object);

	void handlePropertyChange(TkBase* source);
	
	void onFocusOut(EHeader& header,const string& detail,const string& mode)
	{
		handlePropertyChange(header.source);
	}

	void setVisible(bool value);
	void beforeSave();
	void afterSave();
};

#endif/*_PROPERTY_EDITOR_H_*/
