/*
 * $Id: guienvironment.cpp,v 1.10 2008-09-30 10:41:07 kybav1 Exp $
 *
 * Description  : One line description of file.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 *
 * Purpose      :
 *     Long description of what the file is for.
 */


#include <wx/stattext.h>
//#include <wx/textctrl.h>
#include <wx/checkbox.h>
#include <wx/slider.h>
#include <wx/spinctrl.h>
#include <wx/popupwin.h>
//#include <wx/panel.h>
#include <wx/combobox.h>
#include <wx/button.h>
#include <wx/xrc/xmlres.h>
#include <wx/statline.h>
#include "guienvironment.h"
#include "kernel.h"
#include "eventhandler.h"
#include "draganddrop.h"

#include "colourpicker.h"
#include "filecontrol.h"
#include "listctrl.h"
#include "sceneidcontrol.h"
#include "nodeidcontrol.h"
#include "numberinput.h"
#include "module.h"
#include "shortcutpicker.h"
#include "scripteditor.h"


//#include "../data/resources/handshake.xpm"
#include "../data/resources/open.xpm"

using namespace VRUT;

// $$JB postpone updates of the layout of the gui panel - for testing potential gui improvement on loading
#define POSTPONE_UPDATE 0

class SceneIDDropTarget: public ParamDropTarget
{
public:
	SceneIDDropTarget(SceneIDControl *control, const Parameter::ParameterIdentifier &pi) : ParamDropTarget(control, DropTarget::MATERIAL | DropTarget::SCENE_NODES, pi) {}

	///Process drop functionality
	virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) {
		if ( !GetData() )
			return wxDragNone;

		wxDataObjectComposite *dataobjComp = static_cast<wxDataObjectComposite *>(GetDataObject());
		wxDataFormat format = dataobjComp->GetReceivedFormat();
		SCENE_ID sceneId = SCENE_ID_NONE;
		switch (format.GetType()) {
		case wxDF_FILENAME:
		default:
			if (format.GetId() == wxT("VRUT_Material"))
			{
				LOG("Droped material!");
#if wxCHECK_VERSION(2, 9, 0)
				wxDataObject *dataobj = dataobjComp->GetObject(format);
				MaterialDataObject *mdo = static_cast<MaterialDataObject *>(dataobj);
#else
				MaterialDataObject *mdo = (MaterialDataObject *)m_dataObject;
#endif
				sceneId = mdo->GetSceneId();
			}
			else if (format.GetId() == wxT("VRUT_SceneNodes"))
			{
				LOG("Droped scene nodes!");
#if wxCHECK_VERSION(2, 9, 0)
				wxDataObject *dataobj = dataobjComp->GetObject(format);
				SceneNodesDataObject *ndo = static_cast<SceneNodesDataObject *>(dataobj);
#else
				SceneNodesDataObject *ndo = (SceneNodesDataObject *)m_dataObject;
#endif
				sceneId = ndo->GetSceneId();
			}
			break;
		}

		if (sceneId == SCENE_ID_NONE)
			return wxDragNone;
		else {
			KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(mParamIdentifier, wxString::Format(wxT("%d"), sceneId)));
		}
		return def;
	}
};

class NodeIDDropTarget: public ParamDropTarget
{
	NodeIDControl *mControl;
public:
	NodeIDDropTarget(NodeIDControl *control, const Parameter::ParameterIdentifier &pi ) : ParamDropTarget(control, DropTarget::SCENE_NODES, pi), mControl(control) {}

	///Process drop functionality
	virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) {
		if ( !GetData() )
			return wxDragNone;

		wxDataObjectComposite *dataobjComp = static_cast<wxDataObjectComposite *>(GetDataObject());
		wxDataFormat format = dataobjComp->GetReceivedFormat();
		NODE_ID nodeId = NODE_ID_NONE;
		SCENE_ID sceneId = SCENE_ID_NONE;
		switch (format.GetType()) {
		case wxDF_FILENAME:
		default:
			if (format.GetId() == wxT("VRUT_SceneNodes"))
			{
				LOG("Droped scene nodes!");
#if wxCHECK_VERSION(2, 9, 0)
				wxDataObject *dataobj = dataobjComp->GetObject(format);
				SceneNodesDataObject *ndo = static_cast<SceneNodesDataObject *>(dataobj);
#else
				SceneNodesDataObject *ndo = (SceneNodesDataObject *)m_dataObject;
#endif
				sceneId = ndo->GetSceneId();
				if (ndo->mNodes.size() > 0)
					nodeId = ndo->mNodes[0];
			}
			break;
		}

		if (nodeId == NODE_ID_NONE)
			return wxDragNone;
		else {
			// enforce setting sceneID in the module instance in which this control is instanced
			Parameter::ParameterIdentifier pi = mParamIdentifier;
			pi.paramName = wxT("sceneID");
			KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(pi, wxString::Format(wxT("%d"), sceneId)));
			
			// update the scene id of this control element directly (potentialy problematic)
			mControl->SetSceneID(sceneId);
			KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(mParamIdentifier, wxString::Format(wxT("%d"), nodeId)));
		}
		return def;
	}
};

/// Drop target for nodes into the list control in material editor
class ListControlDropTarget: public ParamDropTarget
{
public:
	ListControlDropTarget(ListCtrl *control, const Parameter::ParameterIdentifier &pi) :
		ParamDropTarget(control, DropTarget::SCENE_NODES, pi) {}
	
	///Process drop functionality
	virtual wxDragResult OnData(wxCoord x, wxCoord y, wxDragResult def) {
		if ( !GetData() )
			return wxDragNone;

		wxDataObjectComposite *dataobjComp = static_cast<wxDataObjectComposite *>(GetDataObject());
		wxDataFormat format = dataobjComp->GetReceivedFormat();
		NODE_ID nodeId = NODE_ID_NONE;
		SCENE_ID sceneId = SCENE_ID_NONE;
		switch (format.GetType()) {
		case wxDF_FILENAME:
		default:
			if (format.GetId() == wxT("VRUT_SceneNodes")) {
				LOG("Droped scene nodes!");
#if wxCHECK_VERSION(2, 9, 0)
				wxDataObject *dataobj = dataobjComp->GetObject(format);
				SceneNodesDataObject *ndo = static_cast<SceneNodesDataObject *>(dataobj);
#else
				SceneNodesDataObject *ndo = (SceneNodesDataObject *)m_dataObject;
#endif
				sceneId = ndo->GetSceneId();
				if (ndo->mNodes.size() > 0)
					nodeId = ndo->mNodes[0];
			}
			break;
		}

		if (nodeId == NODE_ID_NONE)
			return wxDragNone;
		else {
			smart_pointer_v2<Scene> scene;
			KERNEL->sceneManager->GetScene(scene, sceneId);
			if (scene) {
				smart_pointer<SceneNode> node;
				scene->GetNode(node, nodeId);

				if (node) {
					if (mParamIdentifier.paramName == wxT("materialList")) {
						// this is performed on a materialList control widget
						MATERIAL_ID mid = MATERIAL_ID_NONE;
						if (node->GetType() == SceneNode::GEOMETRY)
							mid=((GeometryNode *)node.getPtr())->GetMaterialID();
						if (node->GetType() == SceneNode::BACKGROUND)
							mid=((BackgroundNode *)node.getPtr())->GetMaterialID();

						smart_pointer <Material> mat;
						scene->GetMaterial(mat, mid);
						if (mat) {
							// enforce setting sceneID in the module instance in which this control is instanced
							Parameter::ParameterIdentifier pi = mParamIdentifier;
							pi.paramName = wxT("sceneID");
							KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(pi, wxString::Format(wxT("%d"), sceneId)));
							KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(mParamIdentifier, wxString::Format(wxT("%lu "), (unsigned long)mid) + mat->name));
						}
					}
					else if (mParamIdentifier.paramName == wxT("lightList"))
					{
						// this is performed on a lightList control widget
						if (node->GetType() == SceneNode::LIGHT)
						{
							// enforce setting sceneID in the module instance in which this control is instanced
							Parameter::ParameterIdentifier pi = mParamIdentifier;
							pi.paramName = wxT("sceneID");
							KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(pi, wxString::Format(wxT("%d"), sceneId)));
							KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET_DO(mParamIdentifier, wxString::Format(wxT("%d"), nodeId)));
						}
					}
				}
			}
		}
		return def;
	}
};




#define XRCCTRLSAFE(var, window, id, className)                                                                     \
{                                                                                                                   \
	wxWindow *tmpControl = (window).FindWindow(XRCID(id));                                                          \
	var = (!tmpControl) ? (className *)tmpControl : (                                                               \
		(tmpControl->IsKindOf(wxCLASSINFO(className))) ? wxStaticCast(tmpControl, className) : (className *)NULL ); \
}

ParametersWindow::ParametersWindow(wxWindow * parent, wxWindowID id) : wxScrolledWindow(parent, id), m_groupBox(0), m_groupSizer(0), m_hasLayout(false)
{
	wxBoxSizer * mainSizer = new wxBoxSizer(wxVERTICAL);
	SetSizer(mainSizer);
}

void ParametersWindow::beginGroup(const wxString & groupName)
{
	//m_groupBox = new wxStaticBoxSizer(wxVERTICAL, this, groupName);
	m_groupBox = new wxBoxSizer(wxVERTICAL);
	wxBoxSizer * mainSizer = static_cast<wxBoxSizer*>(GetSizer());
	mainSizer->Add(m_groupBox, 0, wxEXPAND|wxALL, 5, 0);
	m_groupSizer = new wxFlexGridSizer(4, 2, 2);
	m_groupBox->Add(m_groupSizer, 1, wxEXPAND, 0, 0);
}

const wxString GUIEnvironment::setParamOriginId = "core.GUIEnvironment";

GUIEnvironment::GUIEnvironment(wxWindow * parent) : wxAuiNotebook(parent, wxID_ANY, wxDefaultPosition, wxSize(480, 170), wxAUI_NB_DEFAULT_STYLE | wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_WINDOWLIST_BUTTON)
{
	/*this->GetArtProvider()->SetColour(*wxBLUE);
	this->GetArtProvider()->SetActiveColour(*wxBLUE);
	this->SetBackgroundColour(*wxBLUE);*/

	Connect(wxID_ANY, wxEVT_AUINOTEBOOK_PAGE_CLOSE, wxAuiNotebookEventHandler(GUIEnvironment::onPageClose), (wxObject *)NULL, this);
	Connect(wxID_ANY, wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN, wxAuiNotebookEventHandler(GUIEnvironment::onUndock), (wxObject *)NULL, this);
	batchMode = false;

	wxXmlResource::Get()->InitAllHandlers();
	// handlers for new widgets
	wxXmlResource::Get()->AddHandler(new SceneIDControlXmlHandler());
	wxXmlResource::Get()->AddHandler(new NodeIDControlXmlHandler());
	wxXmlResource::Get()->AddHandler(new ColourPickerXmlHandler());
	wxXmlResource::Get()->AddHandler(new FileControlXmlHandler());
	wxXmlResource::Get()->AddHandler(new ListCtrlXmlHandler());
	wxXmlResource::Get()->AddHandler(new DropSourceControlXmlHandler());
	wxXmlResource::Get()->AddHandler(new SpinCtrlDoubleXmlHandler());
	wxXmlResource::Get()->AddHandler(new ShortCutPickerXmlHandler());
	wxXmlResource::Get()->AddHandler(new ScriptEditorXmlHandler());
	wxXmlResource::Get()->AddHandler(new NumberInputXmlHandler());
}

void GUIEnvironment::onCommandEvent(wxCommandEvent & evt)
{
	wxWindow * win = dynamic_cast<wxWindow *>(evt.GetEventObject());
	if (win)
	{
		Parameter::ParameterIdentifier pi = Parameter::ParameterIdentifier::FromParamName(win->GetName());

//				LOGERROR(wxT("GUIEnvironment::OnCommand - ")+pi.ToString());

		if (pi.IsValid())
		{
			wxString newValue;

			// ListCtrl event
			if (evt.GetEventType() == wxEVT_LIST_ITEM_SELECTED)
			{
				ListCtrl * listControl = (ListCtrl*)evt.GetEventObject();
				newValue = wxT("0,") + listControl->GetValue();
			}
			else if (evt.GetEventType() == wxEVT_LIST_ITEM_ACTIVATED)
			{
				ListCtrl * listControl = (ListCtrl*)evt.GetEventObject();
				newValue = wxT("1,") + listControl->GetValue();
			}
			// wxCheckBox events
			else if (evt.GetEventType() == wxEVT_COMMAND_CHECKBOX_CLICKED)
				newValue = (evt.IsChecked() ? wxT("1") : wxT("0"));
			// wxSlider events
			else if ((evt.GetEventType() == wxEVT_SCROLL_THUMBTRACK) ||
					    (evt.GetEventType() == wxEVT_SCROLL_THUMBRELEASE) ||
					    (evt.GetEventType() == wxEVT_SCROLL_PAGEDOWN) ||
					    (evt.GetEventType() == wxEVT_SCROLL_PAGEUP) ||
					    (evt.GetEventType() == wxEVT_SCROLL_TOP) ||
					    (evt.GetEventType() == wxEVT_SCROLL_BOTTOM) ||
					    (evt.GetEventType() == wxEVT_SCROLL_LINEUP) ||
					    (evt.GetEventType() == wxEVT_SCROLL_LINEDOWN) ||
					    (evt.GetEventType() == wxEVT_SCROLL_CHANGED))
				newValue = wxString::Format(wxT("%i"), evt.GetInt());
			// wxButton event
			else if (evt.GetEventType() == wxEVT_COMMAND_BUTTON_CLICKED)
			{
				newValue = KERNEL->environment.GetParam(pi);
				long tmpVal = 0;
				newValue.ToLong(&tmpVal);
				newValue = wxString::Format(wxT("%li"), tmpVal + 1);
			}
			// wxTextCtrl / FileControl / ColourPicker / ShortCutPicker event
			else if (evt.GetEventType() == wxEVT_COMMAND_TEXT_ENTER)
			{
				newValue = evt.GetString();
			}
			// wxComboBox / wxSpinCtrl / SpinCtrlDouble event
			else if (evt.GetEventType() == wxEVT_COMMAND_TEXT_UPDATED)
			{
				if (evt.GetEventObject()->IsKindOf(wxClassInfo::FindClass(wxT("wxSpinCtrl"))))
					newValue = wxString::Format(wxT("%i"), ((wxSpinCtrl *)evt.GetEventObject())->GetValue());
				else if (evt.GetEventObject()->IsKindOf(wxClassInfo::FindClass(wxT("SpinCtrlDouble"))))
					newValue = wxString::Format(wxT("%f"), ((SpinCtrlDouble *)evt.GetEventObject())->GetValue());
				else
					newValue = evt.GetString();
			}
#ifdef USE_wxDEFINE_EVENT
			// NumberInput event
			else if (evt.GetEventType() == EVT_NUMBER_INPUT)
			{
				if (evt.GetEventObject()->IsKindOf(wxClassInfo::FindClass(wxT("NumberInput"))))
					newValue = ((NumberInput *)evt.GetEventObject())->GetTextValue();
			}
#endif
			// wxGrid events
#if wxUSE_GRID
#if wxCHECK_VERSION(2, 9, 1)
			else if (evt.GetEventType() == wxEVT_GRID_CELL_CHANGED)
#else
			else if (evt.GetEventType() == wxEVT_GRID_CELL_CHANGE)
#endif
			{
				int col = ((wxGridEvent*)&evt)->GetCol();
				int row = ((wxGridEvent*)&evt)->GetRow();
				newValue = wxString::Format(wxT("%i,%i,"), col,row) + ((wxGrid *)evt.GetEventObject())->GetCellValue(row, col);
			}
			else if ((evt.GetEventType() == wxEVT_GRID_CELL_LEFT_CLICK))
			{
				int col = ((wxGridEvent*)&evt)->GetCol();
				int row = ((wxGridEvent*)&evt)->GetRow();

				Grid *grid_ptr = (Grid *)evt.GetEventObject();
				wxGridCellEditor *gc_editor = grid_ptr->GetCellEditor(row, col);

				if (dynamic_cast<wxGridCellChoiceEditor*>(gc_editor))
				{
					grid_ptr->SetCurrentCell(row, col);
					gc_editor->DecRef();
					evt.Skip();
					return;
				}
				if (dynamic_cast<wxGridCellBoolEditor*>(gc_editor))
				{
					wxString chBoxNewVal = (grid_ptr->GetCellValue(row, col) == wxT("1")) ? wxT("") : wxT("1");
					newValue = wxString::Format(wxT("%i,%i,"), col, row) + chBoxNewVal;
					grid_ptr->SetCellValue(row, col, chBoxNewVal);
				}
				else if (dynamic_cast<CellButtonRenderer*>( grid_ptr->GetCellRenderer(row, col)))
					newValue = wxString::Format(wxT("%i,%i,"), col,row) + ((wxGrid *)evt.GetEventObject())->GetCellValue(row, col);
				else
					evt.Skip();

				gc_editor->DecRef();
			}
#endif /* wxUSE_GRID */
			else
				return;
			/*KERNEL->GetMessageSink()->PostEvent(GET_EVT_PARAM_SET(pi, newValue));*/
			KERNEL->environment.SetParam(pi, newValue, setParamOriginId);
		}
	}
}

void GUIEnvironment::onPageClose(wxAuiNotebookEvent & evt)
{
	if (evt.GetEventType() == wxEVT_AUINOTEBOOK_PAGE_CLOSE)
	{
		evt.Veto();
		int id = evt.GetSelection();

		if (id > 0)
		{
			wxString moduleName(GetPageText(id));
			TextParser textParser(moduleName.utf8_str());
			textParser.GetString(".");//skip the module name
			textParser.GetChar(NULL, false);//skip the .

			int moduleInstance = -1;
			textParser.ParseInt(&moduleInstance);
			size_t pos = moduleName.find_last_of('.');
			moduleName = moduleName.substr(0, pos);
			ModuleList insts;
			KERNEL->GetModules(&insts, moduleName, moduleInstance);

			if (insts.size() == 1)
				insts[0].first->PostToKernel(GET_EVT_MODULE_RELEASE(insts[0].first->GetID()));
			else
			{
				LOGWARNING(wxString::Format(wxT("<GUIEnvironment> Can't release module (inst.size()=%lu)"), (unsigned long)insts.size()));
			}
		}
	}
}

void GUIEnvironment::onUndock(wxAuiNotebookEvent & evt)
{
	if (evt.GetEventType() == wxEVT_AUINOTEBOOK_TAB_RIGHT_DOWN)
	{
		int id = evt.GetSelection();
		undock(id);
	}
}

void GUIEnvironment::OnUndockedClose(wxCloseEvent & evt)
{
	wxWindow *frame = (wxWindow *)evt.GetEventObject();
	wxString moduleName(frame->GetLabel());
	size_t pos = moduleName.rfind(wxT('.'));
	if ((pos > 0) && (pos < moduleName.size()))
		moduleName = moduleName.substr(0, pos);
	KERNEL->WinPosSizeToVRUTConfig(frame, wxT("/") + moduleName + wxT("/"));

	ParametersWindow *paramWindow = (ParametersWindow *)*frame->GetChildren().begin();
	for (size_t i = 0; i < undockedWindows.size(); i++)
	{
		if (undockedWindows[i] == paramWindow)
		{
			undockedWindows.erase(undockedWindows.begin()+i);
			break;
		}
	}
	AddPage(paramWindow, frame->GetLabel());
	evt.Skip();
}

wxWindow* GUIEnvironment::GetControl(const Parameter::ParameterIdentifier & paramID)
{
	wxString poolInstName = paramID.poolName+wxT(".")+paramID.instName;
	if (paramID.poolName.IsSameAs(wxT("kernel")))
		poolInstName = paramID.poolName;

	ParametersWindow *paramWindow = getParametersWindow(poolInstName);
	if (paramWindow)
	{
		if(paramWindow->getHasLayout() && !paramID.paramName.IsSameAs(wxT(" ")))
		{
			return paramWindow->FindWindowByName(paramID.ToString());
		}
		else 
		{
			wxWindowList & children = paramWindow->GetChildren();
			for (auto &win : children)
			{
				if (win && win->GetName().IsSameAs(paramID.ToString()) && !paramID.paramName.IsSameAs(wxT(" ")))
					return dynamic_cast<wxWindow *>(win);
			}
		}
	}

	return (wxWindow *)NULL;
}

void GUIEnvironment::ShowParams(const Parameter::ParameterIdentifier & paramID)
{
	for (auto &controlInfo : controlsInfo)
		if (controlInfo.second.paramID.Matches(paramID))
		{
			std::vector<Environment::NameValue> vals;
			KERNEL->environment.GetParams(controlInfo.second.paramID, vals);

			if (!vals.empty())
				RegisterGUIParam(controlInfo.second, vals.front().second);
		}
}

void GUIEnvironment::HideParams(const Parameter::ParameterIdentifier & paramID, bool unregister)
{
	if (unregister)
	{
		if (!paramID.paramName.IsSameAs(wxT("*")))
		{
			LOGWARNING(wxT("<GUIEnvironment>Only whole pool page with parameters can be hidden, use 'pool' or 'pool.*.inst' ('?' and '*' allowed)"));
			return;
		}

		std::vector<GUIInfoList::iterator> forDeletion;
		for (GUIInfoList::iterator it = controlsInfo.begin(); it != controlsInfo.end(); ++it)
			if (it->second.paramID.Matches(paramID))
				forDeletion.push_back(it);

		for (std::vector<GUIInfoList::iterator>::const_iterator delIt = forDeletion.begin(); delIt != forDeletion.end(); ++delIt)
			controlsInfo.erase(*delIt);
	}

	for (size_t pg = 0; pg < GetPageCount(); )
	{
		TextParser textParser(GetPageText(pg).utf8_str());
		Parameter::ParameterIdentifier pgi(textParser.GetWxString("."));

		if (!textParser.IsEmpty("."))
			pgi.instName = textParser.GetWxString();

		if (pgi.Matches(paramID))
			DeletePage(pg);
		else
			++pg;
	}

	for (size_t pg = 0; pg < undockedWindows.size(); ++pg)
	{
		TextParser textParser(undockedWindows[pg]->GetParent()->GetLabel().utf8_str());
		Parameter::ParameterIdentifier pgi(textParser.GetWxString("."));

		if (!textParser.IsEmpty("."))
			pgi.instName = textParser.GetWxString();

		if (pgi.Matches(paramID))
		{
			delete undockedWindows[pg]->GetParent();
			undockedWindows.erase(undockedWindows.begin()+pg);
		}
		else
			++pg;
	}
}

void GUIEnvironment::FillGrid(wxGrid *control, const wxArrayString &values, bool updateExisting)
{
#if wxUSE_GRID
#if wxCHECK_VERSION(2, 9, 1)
	wxGridUpdateLocker updateLocker(control);
#else
	control->Freeze();
#endif
	int cols = 0, rows = 0, colLabelSize = 0, rowLabelSize = 0;
	if (values.size() > 0)
	{
		TextParser textParser(values[0].utf8_str());

		if (!textParser.ParseInt(&cols, ","))
			LOGERROR(wxT("GUIEnvironment::FillGrid: error parsing cols"));
		if (!textParser.ParseInt(&rows, ","))
			LOGERROR(wxT("GUIEnvironment::FillGrid: error parsing rows"));
		if (!textParser.ParseInt(&colLabelSize, ","))
			LOGERROR(wxT("GUIEnvironment::FillGrid: error parsing colLabelSize"));
		if (!textParser.ParseInt(&rowLabelSize, ","))
			LOGERROR(wxT("GUIEnvironment::FillGrid: error parsing rowLabelSize"));
	}
	if (updateExisting)
	{
		//fix number of cols and rows
		int curCols = ((wxGrid *)control)->GetNumberCols();
		if (curCols > cols)
			((wxGrid *)control)->DeleteCols(cols, curCols-cols);
		else if (curCols < cols)
			((wxGrid *)control)->AppendCols(cols-curCols);

		int curRows = ((wxGrid *)control)->GetNumberRows();
		if (curRows > rows)
			((wxGrid *)control)->DeleteRows(rows, curRows-rows);
		else if (curRows<rows)
			((wxGrid *)control)->AppendRows(rows-curRows);
	}
	else
	{
		((wxGrid *)control)->CreateGrid(rows, cols);
#if wxCHECK_VERSION(2, 9, 1)
		control->Connect(wxID_ANY, wxEVT_GRID_CELL_CHANGED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
#else
		control->Connect(wxID_ANY, wxEVT_GRID_CELL_CHANGE, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
#endif
		control->Connect(wxID_ANY, wxEVT_GRID_CELL_LEFT_CLICK, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
	}
	((wxGrid *)control)->SetColLabelSize(colLabelSize);
	((wxGrid *)control)->SetRowLabelSize(rowLabelSize);

	if ((values.size()>0) && (cols*rows+1 + ((colLabelSize>0)?cols:0) + ((rowLabelSize>0)?rows:0)))
	{
		size_t valPos = 1;//skip 0, using is hard coded
		//set cols labels
		if (colLabelSize > 0)
			for (int i=0; i<cols; i++)
				((wxGrid *)control)->SetColLabelValue(i, values[valPos++]);

		//set rows labels
		if (rowLabelSize > 0)
			for (int i=0; i<rows; i++)
				((wxGrid *)control)->SetRowLabelValue(i, values[valPos++]);

		//set cell types and values
		for (int j=0; j<rows; j++)
		{
			for (int i=0; i<cols; i++)
			{
				TextParser textParser(values[valPos++].utf8_str());
				int cellType = 0;
				if (textParser.ParseInt(&cellType))
				{
					textParser.GetChar();//skip ","
					switch (cellType)
					{
						case 0://read-write text
							((wxGrid *)control)->SetCellValue(j, i, textParser.GetWxStringUtf8(""));
							((wxGrid *)control)->SetCellEditor(j, i, NULL);
							((wxGrid *)control)->SetCellRenderer(j, i, NULL);
							((wxGrid *)control)->SetReadOnly(j, i, false);
							break;
						case 1://read only text
							((wxGrid *)control)->SetCellValue(j, i, textParser.GetWxStringUtf8(""));
							((wxGrid *)control)->SetCellEditor(j, i, NULL);
							((wxGrid *)control)->SetCellRenderer(j, i, NULL);
							((wxGrid *)control)->SetReadOnly(j, i);
							break;
						case 2://check box
							((wxGrid *)control)->SetCellRenderer(j, i, new wxGridCellBoolRenderer());
							((wxGrid *)control)->SetCellEditor(j, i, new wxGridCellBoolEditor());
							//((wxGrid *)control)->SetReadOnly(j, i, false);
							if (textParser.NextCharIs('1'))
								((wxGrid *)control)->SetCellValue(j, i, wxT("1"));
							else
								((wxGrid *)control)->SetCellValue(j, i, wxT("")); // false must be empty string
							break;
						case 3://combo box
						{
							wxArrayString choices;
							while (!textParser.NextCharIs(','))
								choices.Add(textParser.GetWxStringUtf8(";,"));
							//((wxGrid *)control)->SetCellRenderer(j, i, new wxGridCellChoiceEditor());
							((wxGrid *)control)->SetCellRenderer(j, i, NULL);
							((wxGrid *)control)->SetCellEditor(j, i, new wxGridCellChoiceEditor(choices));
							textParser.GetChar();//skip ","
							((wxGrid *)control)->SetCellValue(j, i, textParser.GetWxStringUtf8(""));
							((wxGrid *)control)->SetReadOnly(j, i, false);
							break;
						}
						case 4://button
						{
							((wxGrid *)control)->SetCellRenderer(j, i, new CellButtonRenderer());
							((wxGrid *)control)->SetCellEditor(j, i, NULL);
							((wxGrid *)control)->SetCellValue(j, i, textParser.GetWxStringUtf8(""));
							((wxGrid *)control)->SetReadOnly(j, i);
						}
					}
				}
				else
				{
					((wxGrid *)control)->SetCellEditor(j, i, NULL);
					((wxGrid *)control)->SetCellRenderer(j, i, NULL);
					((wxGrid *)control)->SetCellValue(j, i, values[valPos-1]);
					((wxGrid *)control)->SetReadOnly(j, i);
				}
			}
		}
		//set autosize
#if wxCHECK_VERSION(2, 9, 0)
		if (rows > 0) //this line is workaround for wxWidgets 2.9 bug (for rows==0), remove it when the bug will be fixed
#endif
			for (int i=0; i<cols; i++)
				((wxGrid *)control)->AutoSizeColumn(i);
	}
#if wxCHECK_VERSION(2, 9, 1)
#else
	control->Thaw();
#endif
#else /* wxUSE_GRID */
	#pragma message (__WARNING_LOC__"wxGrid is not supported in this build, you must recompile wxWidgets!")
	LOGERROR(wxT("wxGrid is not supported in this build, you must recompile wxWidgets!"));
#endif /* wxUSE_GRID */
}

void GUIEnvironment::SetLayout(const Parameter::ParameterIdentifier & paramID, const wxString & layoutFileName)
{
	wxFileName fileName(KERNEL->GetAppPath() + layoutFileName);

	if (!paramID.IsValid() || !fileName.IsOk() || !fileName.FileExists())
		return;
	
	wxString poolInstName = paramID.poolName+wxT(".")+paramID.instName;
	if (paramID.poolName.IsSameAs(wxT("kernel")))
		poolInstName = paramID.poolName;

	// load parameter window layout (panel) from xrc file
	if (!wxXmlResource::Get()->Load(fileName.GetFullPath()))
	{
		LOGWARNING(wxT("<GUIEnvironment>::SetLayout: xrc file not loaded successfully - ")+layoutFileName);
		return;
	}

	LOG(wxT("<GUIEnvironment>::SetLayout: layout file loaded - ")+layoutFileName);

	ParametersWindow *paramWindow = getParametersWindow(poolInstName);
	if (!paramWindow)
	{
		paramWindow = createParametersWindow(poolInstName, this);
		paramWindow->beginGroup(wxT("Parameters"));
	}

    wxWindow * controlParent = paramWindow->getControlsParent();
	wxWindow * control = (wxWindow *)NULL;
	wxPanel *panel = new wxPanel();

	if (!wxXmlResource::Get()->LoadPanel(panel, controlParent, "editorLayout"))
	{
		LOGWARNING(wxT("<GUIEnvironment>::SetLayout: panel with name 'editorLayout' was not created."));
		return;
	}

	control = panel;
	control->SetName(paramID.ToString());
	control->SetToolTip(paramID.description);

	wxBoxSizer * mainSizer = static_cast<wxBoxSizer *>(paramWindow->GetSizer());
	mainSizer->Insert(0, control, 1, wxALIGN_CENTRE);
	mainSizer->Insert(1, new wxStaticLine(controlParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL), 0, wxEXPAND | wxALL);

	paramWindow->setHasLayout(true);
	paramWindow->setLayoutFile(layoutFileName);

	//if (!batchMode) {
	mainSizer->FitInside(paramWindow);
	//paramWindow->Layout();
	//}

	// unload parameter window layout's xrc file to avoid conflicts with other layouts
	if (!wxXmlResource::Get()->Unload(fileName.GetFullPath()))
		LOGWARNING(wxT("<GUIEnvironment>::SetLayout: xrc file was not unloaded successfully - ")+layoutFileName);
}

void GUIEnvironment::StoreUserPerspective()
{
	for (size_t pg = 1; pg < GetPageCount(); ++pg)
	{
		wxString moduleName(GetPageText(pg));
		size_t pos = moduleName.rfind(wxT('.'));
		if ((pos > 0) && (pos < moduleName.size()))
			moduleName = moduleName.substr(0, pos);
		KERNEL->VRUTConfig->Write(wxT("/") + moduleName + wxT("/undocked"), false);
	}
	for (size_t pg = 0; pg < undockedWindows.size(); ++pg)
	{
		wxString moduleName(undockedWindows[pg]->GetParent()->GetLabel());
		size_t pos = moduleName.rfind(wxT('.'));
		if ((pos > 0) && (pos < moduleName.size()))
			moduleName = moduleName.substr(0, pos);
		KERNEL->VRUTConfig->Write(wxT("/") + moduleName + wxT("/undocked"), true);
		KERNEL->WinPosSizeToVRUTConfig(undockedWindows[pg]->GetParent(), wxT("/") + moduleName + wxT("/"));
	}
}

void GUIEnvironment::DockAll()
{
	for (size_t i = 0; i < undockedWindows.size(); i++)
	{
		ParametersWindow *paramWindow = undockedWindows[i];
		undockedWindows.erase(undockedWindows.begin() + i);
		wxWindow *frame = paramWindow->GetParent();
		AddPage(paramWindow, frame->GetLabel());
		delete frame;
	}
}

ParametersWindow* GUIEnvironment::createParametersWindow(const wxString& poolInstName, wxWindow* parent)
{
	ParametersWindow *paramWindow = new ParametersWindow(parent, wxID_ANY);

	paramWindow->SetName(poolInstName);
	paramWindow->SetScrollRate(20, 20);

	// $$JB should be set to false to prevent weird appearance on module loading?? $$RH That will not help.
	AddPage(paramWindow, poolInstName, true);
	wxString moduleName(poolInstName);
	size_t pos = moduleName.rfind(wxT('.'));
	if ((pos > 0) && (pos < moduleName.size()))
		moduleName = moduleName.substr(0, pos);
	if (KERNEL->VRUTConfig->ReadBool(wxT("/") + moduleName + wxT("/undocked"), false))
		undock(GetPageCount()-1);
	return paramWindow;
}

void GUIEnvironment::BeginGUIParamGroup(const GUIParamGroup & groupInfo)
{
	wxString poolInstName = groupInfo.poolName+wxT(".")+groupInfo.instanceName;

	if (groupInfo.poolName.IsSameAs(wxT("kernel")))
		poolInstName = groupInfo.poolName;

	ParametersWindow *paramWindow = getParametersWindow(poolInstName);
	if (!paramWindow)
		paramWindow = createParametersWindow(poolInstName, this);

	paramWindow->beginGroup(groupInfo.groupName);
}

bool GUIEnvironment::RegisterGUIParam(const GUIParamInfo &paramInfo, const wxString & value)
{
	if (!paramInfo.paramID.IsValid())
		return false;

	//don't do GUI for IO modules //TODO: remove after refactoring of IO modules
	//if (paramInfo.paramID.poolName.substr(0, 2)==wxT("IO"))
	//	return false;

///Get instance name - '0' by default
	wxString instNameExact = wxT("0");
	if ((paramInfo.paramID.instName.Find('*') == wxNOT_FOUND) && (paramInfo.paramID.instName.Find('?') == wxNOT_FOUND) && !paramInfo.paramID.instName.IsEmpty())
		instNameExact = CloneWxString(paramInfo.paramID.instName);

	Parameter::ParameterIdentifier pi(paramInfo.paramID.poolName, paramInfo.paramID.paramName, instNameExact);
	///Check if already shown
	if (GetControl(pi)) 
		return ChangeGUIParam(paramInfo, value);

	wxString fullName = pi.ToString();
	GUIInfoList::iterator cit = controlsInfo.find(fullName);
	if (cit == controlsInfo.end())
		controlsInfo.insert(GUIInfoList::value_type(fullName, paramInfo));

	///Get pool notebook
	wxString poolInstName = paramInfo.paramID.poolName+wxT(".")+paramInfo.paramID.instName;
	if (paramInfo.paramID.poolName.IsSameAs(wxT("kernel")))
		poolInstName = paramInfo.paramID.poolName;

	ParametersWindow *paramWindow = getParametersWindow(poolInstName);
	if (!paramWindow)
	{
		paramWindow = createParametersWindow(poolInstName, this);
        paramWindow->beginGroup(wxT("Parameters"));
	}

	///Add new param control
	wxWindow * controlParent = paramWindow->getControlsParent();
	wxWindow * control = (wxWindow *)NULL;
	bool notInLayout = true;

	switch (paramInfo.type)
	{
	case GUIParamInfo::GUI_TYPE_LISTCONTROL:
		{
			if (GUIParamInfo::ACTION_DEFAULT != paramInfo.action)
			{
				LOGWARNING(wxT("GUIEnvironment::RegisterGUIParam() - non-default action for GUI list control."));
				return false;
			}

			ListCtrl *listControl = NULL;

			if (paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(listControl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), ListCtrl);
				if(listControl)
				{
					notInLayout = false;
					listControl->Enable(true);
				}
			}
			if (!listControl)
				listControl = new ListCtrl(controlParent, wxID_ANY, wxDefaultPosition, wxSize(150, 100), wxLC_LIST | wxLC_SINGLE_SEL);
			for (wxString rowDef : paramInfo.values)
			{
				listControl->AddItem(rowDef, false);
			}
			listControl->UpdateListGui();
			listControl->SelectByValue(value);
			listControl->SetSceneID(paramInfo.sceneID);
			listControl->Connect(wxID_ANY, wxEVT_LIST_ITEM_SELECTED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			listControl->Connect(wxID_ANY, wxEVT_LIST_ITEM_ACTIVATED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = listControl;

#if TEST_NEW_DRAGDROP
			listControl->SetDropTarget(new ListControlDropTarget(listControl, pi));
#endif
		}
		break;
	case GUIParamInfo::GUI_TYPE_BITMAP:
		{
			wxStaticBitmap* staticBitmap = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(staticBitmap, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxStaticBitmap);
				if(staticBitmap)
				{
					notInLayout = false;
					staticBitmap->Enable(true);
				}
			}
			if(!staticBitmap)
				staticBitmap = new wxStaticBitmap(controlParent, wxID_ANY, wxNullBitmap, wxDefaultPosition, wxSize(64, 64), 0);

			const_smart_pointer<Image> image = KERNEL->sceneManager->GetImage(value);
			if (image != NULL && image->GetType() == Image::WXIMAGE)
			{
				ImageCommon * imgCommon = (ImageCommon*)image.getPtr();
				wxBitmap bitmap(*imgCommon->GetWxImage());
				staticBitmap->SetBitmap(bitmap);
			}
			control = staticBitmap;
		}
		break;
	case GUIParamInfo::GUI_TYPE_PANEL:
		{
			wxPanel* panel = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(panel, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxPanel);
				if(panel)
				{
					notInLayout = false;
					panel->Enable(true);
				}
			}
			if(!panel)
			{
				LOGWARNING(wxT("GUIEnvironment::RegisterGUIParam() - wxPanel can be registered only in GUI defined by XRC"));
				return false;
			}

			control = panel;
		}
		break;
	case GUIParamInfo::GUI_TYPE_CHECKBOX:
		{
			wxCheckBox* checkBox = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(checkBox, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxCheckBox);
				if(checkBox)
				{
					notInLayout = false;
					checkBox->Enable(true);
				}
			}
			if(!checkBox)
				checkBox = new wxCheckBox(controlParent, wxID_ANY, wxEmptyString);

			checkBox->SetValue(isTrue(value));
			checkBox->Connect(wxID_ANY, wxEVT_COMMAND_CHECKBOX_CLICKED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = checkBox;
		}
		break;
	case GUIParamInfo::GUI_TYPE_SLIDER:
		{
			long val = roundVR(paramInfo.minval);
			value.ToLong(&val);

			wxSlider* slider = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(slider, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxSlider);
				if(slider)
				{
					notInLayout = false;
					slider->Enable(true);
					slider->SetValue(int(val));
					slider->SetRange(roundVR(paramInfo.minval), roundVR(paramInfo.maxval));
				}
			}
			if(!slider)
				slider = new wxSlider(controlParent, wxID_ANY, int(val), roundVR(paramInfo.minval), roundVR(paramInfo.maxval), wxDefaultPosition, wxSize(170, wxDefaultCoord), wxHORIZONTAL | wxSL_LABELS);

			slider->Connect(wxID_ANY, wxEVT_SCROLL_THUMBTRACK, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_THUMBRELEASE, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_PAGEDOWN, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_PAGEUP, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_TOP, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_BOTTOM, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_LINEUP, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_LINEDOWN, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			slider->Connect(wxID_ANY, wxEVT_SCROLL_CHANGED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = slider;
		}
		break;
	case GUIParamInfo::GUI_TYPE_SPINCONTROL:
		{
			wxSpinCtrl* spinCtrl = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(spinCtrl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxSpinCtrl);
				if(spinCtrl)
				{
					notInLayout = false;
					spinCtrl->Enable(true);
					spinCtrl->SetValue(value);
					spinCtrl->SetRange(roundVR(paramInfo.minval), roundVR(paramInfo.maxval));
				}
			}
			if(!spinCtrl)
				spinCtrl = new wxSpinCtrl(controlParent, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, roundVR(paramInfo.minval), roundVR(paramInfo.maxval));

			spinCtrl->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = spinCtrl;
		}
		break;
	case GUIParamInfo::GUI_TYPE_SPINCONTROL_DOUBLE:
		{
			SpinCtrlDouble* spinCtrlDouble = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(spinCtrlDouble, *paramWindow, paramInfo.paramID.paramName.utf8_str(), SpinCtrlDouble);
				if(spinCtrlDouble)
				{
					notInLayout = false;
					spinCtrlDouble->Enable(true);
					spinCtrlDouble->SetRange(paramInfo.minval, paramInfo.maxval);
					spinCtrlDouble->SetValue(value);
					spinCtrlDouble->SetIncrement(paramInfo.step);
				}
			}
			if(!spinCtrlDouble)
				spinCtrlDouble = new SpinCtrlDouble(controlParent, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, wxSP_ARROW_KEYS, paramInfo.minval, paramInfo.maxval, 0, paramInfo.step);

			spinCtrlDouble->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = spinCtrlDouble;
		}
		break;
	case GUIParamInfo::GUI_TYPE_COMBOBOX:
		{
			wxString realValue(value);
			size_t valueIndex = FindBestMatch(paramInfo.values, value);
			if (valueIndex != (size_t)-1)
				realValue = paramInfo.values[valueIndex];

			wxComboBox* comboBox = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(comboBox, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxComboBox);
				if(comboBox)
				{
					notInLayout = false;
					comboBox->Enable(true);
					comboBox->Clear();
					comboBox->Append(paramInfo.values);
					//comboBox->SetValue(paramInfo.values[valueIndex]);
					comboBox->SetValue(realValue);
				}
			}
			if(!comboBox)
				comboBox = new wxComboBox(controlParent, wxID_ANY, realValue, wxDefaultPosition, wxDefaultSize, paramInfo.values, wxCB_READONLY);

			comboBox->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = comboBox;
		}
		break;
	case GUIParamInfo::GUI_TYPE_BUTTON:
		{
			wxButton* button = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(button, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxButton);
				if(button)
				{
					notInLayout = false;
					button->Enable(true);
					button->SetLabel(paramInfo.paramID.paramName);
				}
			}
			if(!button)
				button = new wxButton(controlParent, wxID_ANY, paramInfo.paramID.paramName);

			button->Connect(wxID_ANY, wxEVT_COMMAND_BUTTON_CLICKED, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = button;
		}
		break;
	case GUIParamInfo::GUI_TYPE_COLOURPICKER:
		{
			ColourPicker* picker = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(picker, *paramWindow, paramInfo.paramID.paramName.utf8_str(), ColourPicker);
				if(picker)
				{
					notInLayout = false;
					picker->Enable(true);
					picker->SetValue(value);
				}
			}
			if(!picker)
				picker = new ColourPicker(controlParent, wxID_ANY, paramInfo.paramID.paramName, value);

			picker->SetColourDialogMode(paramInfo.dialogMode);
			picker->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = picker;
		}
		break;
	case GUIParamInfo::GUI_TYPE_SHORTCUTPICKER:
		{
			ShortCutPicker* picker = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(picker, *paramWindow, paramInfo.paramID.paramName.utf8_str(), ShortCutPicker);
				if(picker)
				{
					notInLayout = false;
					picker->Enable(true);
					picker->SetValue(value);
				}
			}
			if(!picker)
				picker = new ShortCutPicker(controlParent, wxID_ANY, paramInfo.paramID.paramName, value);

			picker->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = picker;
		}
		break;
	case GUIParamInfo::GUI_TYPE_SCRIPTEDITOR:
		{
			ScriptEditor* scriptEditor = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(scriptEditor, *paramWindow, paramInfo.paramID.paramName.utf8_str(), ScriptEditor);
				if(scriptEditor)
				{
					notInLayout = false;
					scriptEditor->Enable(true);
					scriptEditor->SetValue(value);
				}
			}
			if(!scriptEditor)
				scriptEditor = new ScriptEditor(controlParent, wxID_ANY, paramInfo.paramID.paramName, value);

			scriptEditor->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = scriptEditor;
		}
		break;
	case GUIParamInfo::GUI_TYPE_FILECONTROL:
		{
			FileControl* fileControl = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(fileControl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), FileControl);
				if(fileControl)
				{
					notInLayout = false;
					fileControl->Enable(true);
					fileControl->SetValue(value);
					fileControl->SetMode(((paramInfo.fileMode == wxT("save")) ? wxFD_SAVE : wxFD_OPEN));
					fileControl->SetWildcard(paramInfo.wildcard);
					fileControl->SetDialogType((paramInfo.fileMode != wxT("directory")));
				}
			}
			if(!fileControl)
				fileControl = new FileControl(controlParent, wxID_ANY, value, ((paramInfo.fileMode == wxT("save")) ? wxFD_SAVE : wxFD_OPEN), paramInfo.wildcard, (paramInfo.fileMode != wxT("directory")));

			fileControl->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			fileControl->SetToolTip(paramInfo.paramID.description);
			control = fileControl;
		}
		break;
	case GUIParamInfo::GUI_TYPE_SCENEID:
		{
			wxArrayString strArray;
			SceneIDControl *sceneIDControl = NULL;

			if (paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(sceneIDControl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), SceneIDControl);
				if(sceneIDControl)
				{
					notInLayout = false;
					sceneIDControl->Enable(true);
					sceneIDControl->SetValue(value);
				}
			}
			if (!sceneIDControl)
			{
				sceneIDControl = new SceneIDControl(controlParent, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, strArray, wxCB_READONLY);
				sceneIDControl->SetValue(value);
			}

#if TEST_NEW_DRAGDROP
			sceneIDControl->SetDropTarget(new SceneIDDropTarget(sceneIDControl, pi));
#endif
			
			control = sceneIDControl;
		}
		break;
    case GUIParamInfo::GUI_TYPE_NODEID:
		{
			wxArrayString strArray;
			NodeIDControl *nodeIDControl = NULL;
			
			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(nodeIDControl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), NodeIDControl);
				if(nodeIDControl)
				{
					notInLayout = false;
					nodeIDControl->Enable(true);
					nodeIDControl->SetValue(value);
					nodeIDControl->SetNodeTypes(paramInfo.nodeTypes);
					nodeIDControl->SetSceneID(paramInfo.sceneID);
				}
			}
			if(!nodeIDControl) {
				nodeIDControl = new NodeIDControl(controlParent, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, strArray, 0/*wxCB_READONLY*/, wxDefaultValidator, wxComboBoxNameStr, paramInfo.sceneID, paramInfo.nodeTypes);
#if TEST_NEW_DRAGDROP
				nodeIDControl->SetDropTarget(new NodeIDDropTarget(nodeIDControl, pi));
#endif
			}
			control = nodeIDControl;
		}
		break;
	case GUIParamInfo::GUI_TYPE_STATICTEXT:
		control = new wxStaticText(controlParent, wxID_ANY, paramInfo.paramID.paramName);
		break;
	case GUIParamInfo::GUI_TYPE_DROPSOURCE:
		{
			DropSourceControl* dropSourceControl = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(dropSourceControl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), DropSourceControl);
				if(dropSourceControl)
				{
					notInLayout = false;
					dropSourceControl->Enable(true);
					dropSourceControl->SetData(paramInfo.dataObject);
					dropSourceControl->SetTextLabel(paramInfo.paramID.paramName);
					dropSourceControl->SetBitmapLabel(wxBitmap(open_xpm/*handshake_xpm*/));						
				}
			}
			if(!dropSourceControl)
				dropSourceControl = new DropSourceControl(controlParent, wxID_ANY, paramInfo.paramID.paramName, wxBitmap(open_xpm/*handshake_xpm*/), paramInfo.dataObject);

			delete paramInfo.dataObject;
			dropSourceControl->SetToolTip(paramInfo.paramID.description);

			paramWindow->Layout();

			control = dropSourceControl;
		}
		break;
	case GUIParamInfo::GUI_TYPE_TABLE:
#if wxUSE_GRID
		{
			wxGrid *grid = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(grid, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxGrid);
				if(grid)
				{
					notInLayout = false;
					grid->Enable(true);
					//grid->SetName(paramInfo.paramID.paramName);
				}
			}
			if(!grid)
				grid = new Grid(controlParent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxWANTS_CHARS, paramInfo.paramID.paramName);

			FillGrid(grid, paramInfo.values);
			control = grid;
		}
#endif /* wxUSE_GRID */
		break;
	case GUIParamInfo::GUI_TYPE_NUMBER_INPUT:
		{
			NumberInput* numberInput = nullptr;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(numberInput, *paramWindow, paramInfo.paramID.paramName.utf8_str(), NumberInput);
				if(numberInput)
				{
					notInLayout = false;
					numberInput->Enable(true);
					numberInput->SetValue(value);
					numberInput->SetRange(paramInfo.minval, paramInfo.maxval);
					numberInput->SetIncrement(paramInfo.step);
					numberInput->SetFlags(paramInfo.flags);
				}
			}
			if(!numberInput)
			{
				numberInput = new NumberInput(controlParent, wxID_ANY);
				numberInput->SetValue(value);
				numberInput->SetRange(paramInfo.minval, paramInfo.maxval);
				numberInput->SetIncrement(paramInfo.step);
				numberInput->SetFlags(paramInfo.flags);
			}
#ifdef USE_wxDEFINE_EVENT
			numberInput->Connect(wxID_ANY, EVT_NUMBER_INPUT, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
#endif
			control = numberInput;
		}
		break;
	case GUIParamInfo::GUI_TYPE_TEXTCONTROL:
	default:
		{
			wxTextCtrl* textCtrl = NULL;

			if(paramWindow->getHasLayout())
			{
				XRCCTRLSAFE(textCtrl, *paramWindow, paramInfo.paramID.paramName.utf8_str(), wxTextCtrl);
				if(textCtrl)
				{
					notInLayout = false;
					textCtrl->Enable(true);
					textCtrl->SetValue(value);
				}
			}
			if(!textCtrl)
				textCtrl = new wxTextCtrl(controlParent, wxID_ANY, value, wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);

			textCtrl->Connect(wxID_ANY, wxEVT_COMMAND_TEXT_ENTER, wxCommandEventHandler(GUIEnvironment::onCommandEvent), (wxObject *)NULL, this);
			control = textCtrl;
		}
		break;
	}

	control->SetToolTip(paramInfo.paramID.description);
	control->SetName(paramInfo.paramID.ToString());

	if (notInLayout)
	{
		wxFlexGridSizer * sizer = paramWindow->getGroupSizer();
		if ((paramInfo.type != GUIParamInfo::GUI_TYPE_BUTTON) && (paramInfo.type != GUIParamInfo::GUI_TYPE_COLOURPICKER) && (paramInfo.type != GUIParamInfo::GUI_TYPE_SHORTCUTPICKER) && (paramInfo.type != GUIParamInfo::GUI_TYPE_SCRIPTEDITOR) && (paramInfo.type != GUIParamInfo::GUI_TYPE_DROPSOURCE) && (paramInfo.type != GUIParamInfo::GUI_TYPE_STATICTEXT))
		{
			if ((sizer-> GetItemCount()+1)%sizer->GetCols()==0)
				sizer->Add(new wxStaticText(controlParent, wxID_ANY, wxT("")), 0, wxALIGN_CENTRE);//add empty text, so the control starts on next line
			sizer->Add(new wxStaticText(controlParent, wxID_ANY, paramInfo.paramID.paramName), 0, wxALIGN_CENTRE);
		}
		sizer->Add(control, 1, wxALIGN_CENTRE);

		if (!batchMode) {
			// LOG(wxT("<GUIEnvironment>Param registered ")+paramInfo.paramID.paramName);
			// paramPage->SetSizerAndFit(paramPage->GetSizer(), false);
			// paramPage->SetSizeHints();
#if !POSTPONE_UPDATE
			paramWindow->Layout();
			// KERNEL->GetMainWindow()->GetAUIManager()->Update();
#endif
		}
	}
	return true;
}

void GUIEnvironment::EnterBatchMode()
{
	batchMode = true;
}

void GUIEnvironment::LeaveBatchMode()
{
	batchMode = false;
	//	paramPage->Layout();
	//	paramPage->SetSizerAndFit(paramPage->GetSizer(), false);
#if !POSTPONE_UPDATE
	//	KERNEL->GetMainWindow()->GetAUIManager()->Update();
#endif
}

bool GUIEnvironment::EnableGUIControl(const GUIParamInfo & paramInfo, const bool enable)
{
	if (paramInfo.paramID.IsValid())
	{
		///Get instance name - '0' by default
		wxString instNameExact = wxT("0");
		if ((paramInfo.paramID.instName.Find('*') == wxNOT_FOUND)
		        && (paramInfo.paramID.instName.Find('?') == wxNOT_FOUND)
		        && !paramInfo.paramID.instName.IsEmpty())
			instNameExact = CloneWxString(paramInfo.paramID.instName);

		Parameter::ParameterIdentifier pi(paramInfo.paramID.poolName, paramInfo.paramID.paramName, instNameExact);
		wxWindow *control = GetControl(pi);

		///Check if exists
		if (!control)
			return false;

		control->Enable(enable);
#if !POSTPONE_UPDATE

		if (control->GetParent())
			control->GetParent()->Layout();
		//		KERNEL->GetMainWindow()->GetAUIManager()->Update();
#endif
		return true;
	}
	return false;
}

bool GUIEnvironment::ShowGUIControl(const GUIParamInfo & paramInfo, const bool show)
{
	if (paramInfo.paramID.IsValid())
	{
		///Get instance name - '0' by default
		wxString instNameExact = wxT("0");
		if ((paramInfo.paramID.instName.Find('*') == wxNOT_FOUND)
		        && (paramInfo.paramID.instName.Find('?') == wxNOT_FOUND)
		        && !paramInfo.paramID.instName.IsEmpty())
			instNameExact = CloneWxString(paramInfo.paramID.instName);

		Parameter::ParameterIdentifier pi(paramInfo.paramID.poolName, paramInfo.paramID.paramName, instNameExact);
		wxWindow *control = GetControl(pi);

		///Check if exists
		if (!control)
			return false;

		if (show)
			control->Show();
		else
			control->Hide();

#if !POSTPONE_UPDATE
		control->Layout();

		if (control->GetParent())
			control->GetParent()->Layout();
		//		KERNEL->GetMainWindow()->GetAUIManager()->Update();
#endif
		return true;
	}
	return false;
}

bool GUIEnvironment::ChangeGUIParam(const GUIParamInfo & paramInfo, const wxString & value)
{
	if (paramInfo.paramID.IsValid())
	{
		///Get instance name - '0' by default
		wxString instNameExact = wxT("0");
		if ((paramInfo.paramID.instName.Find('*') == wxNOT_FOUND)
		        && (paramInfo.paramID.instName.Find('?') == wxNOT_FOUND)
		        && !paramInfo.paramID.instName.IsEmpty())
			instNameExact = CloneWxString(paramInfo.paramID.instName);

		Parameter::ParameterIdentifier pi(paramInfo.paramID.poolName, paramInfo.paramID.paramName, instNameExact);
		wxWindow *control = GetControl(pi);

		///Check if exists
		if (!control)
			return false;

		//TODO: check type
		switch (paramInfo.type)
		{
		case GUIParamInfo::GUI_TYPE_LISTCONTROL:
			{
				if (!control->IsKindOf(CLASSINFO(ListCtrl)))
					break;
				ListCtrl * listControl = (ListCtrl*)control;
				switch (paramInfo.action)
				{
				case GUIParamInfo::ACTION_DEFAULT:
					{
						listControl->RemoveAllItems();
						for (wxString rowDef : paramInfo.values)
						{
							listControl->AddItem(rowDef, false);
						}
						listControl->UpdateListGui();
						listControl->SelectByValue(value);
						listControl->SetSceneID(paramInfo.sceneID);
					}
					break;
				case GUIParamInfo::ACTION_ADD_ROWS:
					{
						for (wxString rowDef : paramInfo.values)
						{
							listControl->AddItem(rowDef, false);
						}
						listControl->UpdateListGui();
						listControl->SelectByValue(value);
				}
					break;
				case GUIParamInfo::ACTION_UPDATE_ROWS:
					{
						for (wxString rowDef : paramInfo.values)
						{
							listControl->UpdateItem(rowDef, false);
						}
						listControl->UpdateListGui();
					}
					break;
				case GUIParamInfo::ACTION_REMOVE_ROWS:
					{
						for (wxString rowDef : paramInfo.values)
						{
							listControl->RemoveItem(rowDef, false);
						}
						listControl->UpdateColumns();
					}
					break;
				default:
					// Do nothing
					LOGWARNING(wxT("GUIEnvironment::ChangeGUIParam() - Unknown action for GUI list control."));
					break;
				}
			}
			break;
		case GUIParamInfo::GUI_TYPE_BITMAP:
			{
				if (!control->IsKindOf(CLASSINFO(wxStaticBitmap)))
					break;
				const_smart_pointer<Image> image = KERNEL->sceneManager->GetImage(value);
				if (image != NULL && image->GetType() == Image::WXIMAGE)
				{
					ImageCommon * imgCommon = (ImageCommon*)image.getPtr();
					wxBitmap bitmap(*imgCommon->GetWxImage());
					((wxStaticBitmap*)control)->SetBitmap(bitmap);
				}
			}
			break;
		case GUIParamInfo::GUI_TYPE_CHECKBOX:
			{
				if (!control->IsKindOf(CLASSINFO(wxCheckBox)))
					break;

				bool newState = isTrue(value);
				if (((wxCheckBox *)control)->IsChecked() != newState)
					((wxCheckBox *)control)->SetValue(newState);
			}
			break;
		case GUIParamInfo::GUI_TYPE_SLIDER:
			{
				if (!control->IsKindOf(CLASSINFO(wxSlider)))
					break;
				long val = roundVR(paramInfo.minval);
				value.ToLong(&val);
				((wxSlider *)control)->SetValue(int(val));
				((wxSlider *)control)->SetRange(roundVR(paramInfo.minval), roundVR(paramInfo.maxval));
			}
			break;
		case GUIParamInfo::GUI_TYPE_SPINCONTROL:
			{
				if (!control->IsKindOf(CLASSINFO(wxSpinCtrl)))
					break;
				((wxSpinCtrl *)control)->SetValue(value);
				((wxSpinCtrl *)control)->SetRange(roundVR(paramInfo.minval), roundVR(paramInfo.maxval));
			}
			break;
		case GUIParamInfo::GUI_TYPE_SPINCONTROL_DOUBLE:
			{
				if (!control->IsKindOf(CLASSINFO(SpinCtrlDouble)))
					break;
				((SpinCtrlDouble *)control)->SetRange(paramInfo.minval, paramInfo.maxval);
				((SpinCtrlDouble *)control)->SetValue(value);
				((SpinCtrlDouble *)control)->SetIncrement(paramInfo.step);
			}
			break;
		case GUIParamInfo::GUI_TYPE_COMBOBOX:
			{
				if (!control->IsKindOf(CLASSINFO(wxComboBox)))
					break;
				((wxComboBox *)control)->Clear();
				((wxComboBox *)control)->Append(paramInfo.values);
				/*for (size_t i=0; i<paramInfo.values.size(); i++)
					((wxComboBox *)control)->Append(paramInfo.values[i]);*/
				size_t valueIndex = FindBestMatch(paramInfo.values, value);
				if (valueIndex != (size_t)-1)
					((wxComboBox *) control)->SetValue(paramInfo.values[valueIndex]);
			}
			break;
		case GUIParamInfo::GUI_TYPE_BUTTON:
			{
				if (!control->IsKindOf(CLASSINFO(wxButton)))
					break;
				((wxButton *)control)->SetLabel(paramInfo.paramID.paramName);
			}
			break;
		case GUIParamInfo::GUI_TYPE_DROPSOURCE:
			{
				((DropSourceControl *)control)->SetData(paramInfo.dataObject);
				delete paramInfo.dataObject;
			}
			break;
		case GUIParamInfo::GUI_TYPE_SCENEID:
			{
				((SceneIDControl *)control)->SetValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_NODEID:
			{
				((NodeIDControl *)control)->SetSceneID(paramInfo.sceneID);
				((NodeIDControl *)control)->SetNodeTypes(paramInfo.nodeTypes);
				((NodeIDControl *)control)->SetValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_TABLE:
#if wxUSE_GRID
			if (control->IsKindOf(CLASSINFO(wxGrid)))
				FillGrid((wxGrid*)control, paramInfo.values, true);
#endif
			break;
		case GUIParamInfo::GUI_TYPE_COLOURPICKER:
			{
				if (!control->IsKindOf(CLASSINFO(ColourPicker)))
					break;
				if (((ColourPicker *)control)->GetValue() != value)
					((ColourPicker *)control)->SetValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_SHORTCUTPICKER:
			{
				if (!control->IsKindOf(CLASSINFO(ShortCutPicker)))
					break;
				if (((ShortCutPicker *)control)->GetValue() != value)
					((ShortCutPicker *)control)->SetValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_SCRIPTEDITOR:
			{
				if (!control->IsKindOf(CLASSINFO(ScriptEditor)))
					break;
				if (((ScriptEditor *)control)->GetValue() != value)
					((ScriptEditor *)control)->SetValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_FILECONTROL:
			{
				if (!control->IsKindOf(CLASSINFO(FileControl)))
					break;
				if (((FileControl *)control)->GetValue() != value)
					((FileControl *)control)->SetValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_PANEL:
			{
				if (!control->IsKindOf(CLASSINFO(wxPanel)))
					break;
				// right now nothing to do
			}
			break;
		case GUIParamInfo::GUI_TYPE_NUMBER_INPUT:
			{
				if (!control->IsKindOf(CLASSINFO(NumberInput)))
					break;
				NumberInput *numberInput = (NumberInput *)control;
				numberInput->SetValue(value);
				numberInput->SetRange(paramInfo.minval, paramInfo.maxval);
				numberInput->SetIncrement(paramInfo.step);
				numberInput->SetFlags(paramInfo.flags);
			}
			break;
		case GUIParamInfo::GUI_TYPE_TEXTCONTROL:
		default:
			{
				if (!control->IsKindOf(CLASSINFO(wxTextCtrl)))
					break;
				if (((wxTextCtrl *)control)->GetValue() != value)
					((wxTextCtrl *)control)->SetValue(value);
			}
			break;
		}

		control->SetName(paramInfo.paramID.ToString());
		control->SetToolTip(paramInfo.paramID.description);

		if ((paramInfo.type != GUIParamInfo::GUI_TYPE_COLOURPICKER) && (paramInfo.type != GUIParamInfo::GUI_TYPE_SHORTCUTPICKER) && (paramInfo.type != GUIParamInfo::GUI_TYPE_SCRIPTEDITOR))
		{
#if !POSTPONE_UPDATE
			if (control->GetParent())
				control->GetParent()->Layout();
			//			KERNEL->GetMainWindow()->GetAUIManager()->Update();
#endif
		}
		return true;
	}
	return false;
}

void GUIEnvironment::SetParam(const Parameter::ParameterIdentifier & paramID, const wxString & value)
{
	wxWindow *control = GetControl(paramID);
	GUIInfoList::iterator cit = controlsInfo.find(paramID.ToString());

	//LOGERROR(wxT("GUIEnvironment::SetParam - ")+paramID.ToString());

	if (control && (cit != controlsInfo.end()))
	{
		switch (cit->second.type)
		{
		case GUIParamInfo::GUI_TYPE_LISTCONTROL:
			{
				ListCtrl *listControl = (ListCtrl *)control;
				listControl->SelectByValue(value);
			}
			break;
		case GUIParamInfo::GUI_TYPE_BITMAP:
			{
				const_smart_pointer<Image> image = KERNEL->sceneManager->GetImage(value);
				if (image != NULL && image->GetType() == Image::WXIMAGE)
				{
					ImageCommon * imgCommon = (ImageCommon*)image.getPtr();
					wxBitmap bitmap(*imgCommon->GetWxImage());
					((wxStaticBitmap*)control)->SetBitmap(bitmap);
				}
			}
			break;
		case GUIParamInfo::GUI_TYPE_CHECKBOX:
			{
				bool newState = isTrue(value);
				if (((wxCheckBox *)control)->IsChecked() != newState)
					((wxCheckBox *)control)->SetValue(newState);
			}
			break;
		case GUIParamInfo::GUI_TYPE_SLIDER:
			{
				long val = roundVR(cit->second.minval);
				if (value.ToLong(&val) && ((wxSlider *)control)->GetValue() != val)
					((wxSlider *)control)->SetValue(val);
			}
			break;
		case GUIParamInfo::GUI_TYPE_SPINCONTROL:
			{
				long val = roundVR(cit->second.minval);
				if (value.ToLong(&val) && ((wxSpinCtrl *)control)->GetValue() != val)
					((wxSpinCtrl *)control)->SetValue(val);
			}
			break;
		case GUIParamInfo::GUI_TYPE_SPINCONTROL_DOUBLE:
			{
				double val = cit->second.minval;
				if (value.ToDouble(&val) && ((SpinCtrlDouble *)control)->GetValue() != val)
					((SpinCtrlDouble *)control)->SetValue(val);
			}
			break;
		case GUIParamInfo::GUI_TYPE_COMBOBOX:
			{
				size_t valueIndex = FindBestMatch(((wxComboBox *)control)->GetStrings(), value);
				if (valueIndex != (size_t)-1)
				{
					wxString newValue = ((wxComboBox *)control)->GetStrings()[valueIndex];
					if(newValue != ((wxComboBox *)control)->GetValue())
						((wxComboBox *) control)->SetValue(newValue);
				}
				break;
			}
		case GUIParamInfo::GUI_TYPE_COLOURPICKER:
			if (((ColourPicker *)control)->GetValue() != value)
				((ColourPicker *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_SHORTCUTPICKER:
			if (((ShortCutPicker *)control)->GetValue() != value)
				((ShortCutPicker *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_SCRIPTEDITOR:
			if (((ScriptEditor *)control)->GetValue() != value)
				((ScriptEditor *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_FILECONTROL:
			if (((FileControl *)control)->GetValue() != value)
				((FileControl *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_TEXTCONTROL:
			if (((wxTextCtrl *)control)->GetValue() != value)
				((wxTextCtrl *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_BUTTON:
			break;
		case GUIParamInfo::GUI_TYPE_DROPSOURCE:
			break;
		case GUIParamInfo::GUI_TYPE_PANEL:
			break;
		case GUIParamInfo::GUI_TYPE_SCENEID:
			((SceneIDControl *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_NODEID:
			((NodeIDControl *)control)->SetValue(value);
			break;
		case GUIParamInfo::GUI_TYPE_TABLE:
#if wxUSE_GRID
			{
				if (!control->IsKindOf(CLASSINFO(wxGrid)))
					break;
				TextParser tmpParser(value.utf8_str());
				int col, row;
				if (!tmpParser.ParseInt(&col))
					col = -1;
				tmpParser.GetChar();
				if (!tmpParser.ParseInt(&row))
					row = -1;
				tmpParser.GetChar();
				wxGrid *grid = (wxGrid*)control;
				if ((grid->GetNumberCols()<=col) || (grid->GetNumberRows()<=row) || (col<0) || (row<0))
					break;

				Grid *grid_ptr = (Grid *)grid;
				wxGridCellEditor *gc_editor = grid_ptr->GetCellEditor(row, col);

				if (!dynamic_cast<CellButtonRenderer*>( grid_ptr->GetCellRenderer(row, col)))
					grid->SetCellValue(row, col, tmpParser.GetWxLine());

				gc_editor->DecRef();
			}
#endif
			break;
		case GUIParamInfo::GUI_TYPE_NUMBER_INPUT:
			if (((NumberInput *)control)->GetTextValue() != value)
				((NumberInput *)control)->SetValue(value);
			break;
		default:
			break;
		}
	}
}
