
///////////////////////////////////////////////////////////
//                                                       //
//                         SAGA                          //
//                                                       //
//      System for Automated Geoscientific Analyses      //
//                                                       //
//           Application Programming Interface           //
//                                                       //
//                  Library: SAGA_API                    //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//                  parameter_data.cpp                   //
//                                                       //
//          Copyright (C) 2005 by Olaf Conrad            //
//                                                       //
//-------------------------------------------------------//
//                                                       //
// This file is part of 'SAGA - System for Automated     //
// Geoscientific Analyses'.                              //
//                                                       //
// This library is free software; you can redistribute   //
// it and/or modify it under the terms of the GNU Lesser //
// General Public License as published by the Free       //
// Software Foundation, either version 2.1 of the        //
// License, or (at your option) any later version.       //
//                                                       //
// This library is distributed in the hope that it will  //
// be useful, but WITHOUT ANY WARRANTY; without even the //
// implied warranty of MERCHANTABILITY or FITNESS FOR A  //
// PARTICULAR PURPOSE. See the GNU Lesser General Public //
// License for more details.                             //
//                                                       //
// You should have received a copy of the GNU Lesser     //
// General Public License along with this program; if    //
// not, see <http://www.gnu.org/licenses/>.              //
//                                                       //
//-------------------------------------------------------//
//                                                       //
//    contact:    Olaf Conrad                            //
//                Institute of Geography                 //
//                University of Goettingen               //
//                Goldschmidtstr. 5                      //
//                37077 Goettingen                       //
//                Germany                                //
//                                                       //
//    e-mail:     oconrad@saga-gis.org                   //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
#include "parameters.h"
#include "data_manager.h"


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_String SG_Parameter_Type_Get_Name(TSG_Parameter_Type Type)
{
	switch( Type )
	{
	default                              :	return( _TL("parameter"            ) );

	case PARAMETER_TYPE_Node             :	return( _TL("node"                 ) );

	case PARAMETER_TYPE_Bool             :	return( _TL("boolean"              ) );
	case PARAMETER_TYPE_Int              :	return( _TL("integer number"       ) );
	case PARAMETER_TYPE_Double           :	return( _TL("floating point number") );
	case PARAMETER_TYPE_Degree           :	return( _TL("degree"               ) );
	case PARAMETER_TYPE_Date             :	return( _TL("date"                 ) );
	case PARAMETER_TYPE_Range            :	return( _TL("value range"          ) );
	case PARAMETER_TYPE_Data_Type        :	return( _TL("data type"            ) );
	case PARAMETER_TYPE_Choice           :	return( _TL("choice"               ) );
	case PARAMETER_TYPE_Choices          :	return( _TL("choices"              ) );

	case PARAMETER_TYPE_String           :	return( _TL("text"                 ) );
	case PARAMETER_TYPE_Text             :	return( _TL("long text"            ) );
	case PARAMETER_TYPE_FilePath         :	return( _TL("file path"            ) );

	case PARAMETER_TYPE_Font             :	return( _TL("font"                 ) );
	case PARAMETER_TYPE_Color            :	return( _TL("color"                ) );
	case PARAMETER_TYPE_Colors           :	return( _TL("colors"               ) );
	case PARAMETER_TYPE_FixedTable       :	return( _TL("static table"         ) );
	case PARAMETER_TYPE_Grid_System      :	return( _TL("grid system"          ) );
	case PARAMETER_TYPE_Table_Field      :	return( _TL("table field"          ) );
	case PARAMETER_TYPE_Table_Fields     :	return( _TL("table fields"         ) );

	case PARAMETER_TYPE_DataObject_Output:	return( _TL("data object"          ) );
	case PARAMETER_TYPE_Grid             :	return( _TL("grid"                 ) );
	case PARAMETER_TYPE_Grids            :	return( _TL("grid collection"      ) );
	case PARAMETER_TYPE_Table            :	return( _TL("table"                ) );
	case PARAMETER_TYPE_Shapes           :	return( _TL("shapes"               ) );
	case PARAMETER_TYPE_TIN              :	return( _TL("TIN"                  ) );
	case PARAMETER_TYPE_PointCloud       :	return( _TL("point cloud"          ) );

	case PARAMETER_TYPE_Grid_List        :	return( _TL("grid list"            ) );
	case PARAMETER_TYPE_Grids_List       :	return( _TL("grid collection list" ) );
	case PARAMETER_TYPE_Table_List       :	return( _TL("table list"           ) );
	case PARAMETER_TYPE_Shapes_List      :	return( _TL("shapes list"          ) );
	case PARAMETER_TYPE_TIN_List         :	return( _TL("TIN list"             ) );
	case PARAMETER_TYPE_PointCloud_List  :	return( _TL("point cloud list"     ) );

	case PARAMETER_TYPE_Parameters       :	return( _TL("parameters"           ) );
	}
}

//---------------------------------------------------------
CSG_String SG_Parameter_Type_Get_Identifier(TSG_Parameter_Type Type)
{
	switch( Type )
	{
	default                              :	return( "parameter"    );

	case PARAMETER_TYPE_Node             :	return( "node"         );

	case PARAMETER_TYPE_Bool             :	return( "boolean"      );
	case PARAMETER_TYPE_Int              :	return( "integer"      );
	case PARAMETER_TYPE_Double           :	return( "double"       );
	case PARAMETER_TYPE_Degree           :	return( "degree"       );
	case PARAMETER_TYPE_Date             :	return( "date"         );
	case PARAMETER_TYPE_Range            :	return( "range"        );
	case PARAMETER_TYPE_Data_Type        :	return( "datatype"     );
	case PARAMETER_TYPE_Choice           :	return( "choice"       );
	case PARAMETER_TYPE_Choices          :	return( "choices"      );

	case PARAMETER_TYPE_String           :	return( "text"         );
	case PARAMETER_TYPE_Text             :	return( "long_text"    );
	case PARAMETER_TYPE_FilePath         :	return( "file"         );

	case PARAMETER_TYPE_Font             :	return( "font"         );
	case PARAMETER_TYPE_Color            :	return( "color"        );
	case PARAMETER_TYPE_Colors           :	return( "colors"       );
	case PARAMETER_TYPE_FixedTable       :	return( "static_table" );
	case PARAMETER_TYPE_Grid_System      :	return( "grid_system"  );
	case PARAMETER_TYPE_Table_Field      :	return( "table_field"  );
	case PARAMETER_TYPE_Table_Fields     :	return( "table_fields" );

	case PARAMETER_TYPE_DataObject_Output:	return( "data_object"  );
	case PARAMETER_TYPE_Grid             :	return( "grid"         );
	case PARAMETER_TYPE_Grids            :	return( "grids"        );
	case PARAMETER_TYPE_Table            :	return( "table"        );
	case PARAMETER_TYPE_Shapes           :	return( "shapes"       );
	case PARAMETER_TYPE_TIN              :	return( "tin"          );
	case PARAMETER_TYPE_PointCloud       :	return( "points"       );

	case PARAMETER_TYPE_Grid_List        :	return( "grid_list"    );
	case PARAMETER_TYPE_Grids_List       :	return( "grids_list"   );
	case PARAMETER_TYPE_Table_List       :	return( "table_list"   );
	case PARAMETER_TYPE_Shapes_List      :	return( "shapes_list"  );
	case PARAMETER_TYPE_TIN_List         :	return( "tin_list"     );
	case PARAMETER_TYPE_PointCloud_List  :	return( "points_list"  );

	case PARAMETER_TYPE_Parameters       :	return( "parameters"   );
	}
}

//---------------------------------------------------------
TSG_Parameter_Type SG_Parameter_Type_Get_Type(const CSG_String &Identifier)
{
	if( !Identifier.Cmp("node"        ) )	{	return( PARAMETER_TYPE_Node             );	}
	if( !Identifier.Cmp("boolean"     ) )	{	return( PARAMETER_TYPE_Bool             );	}
	if( !Identifier.Cmp("integer"     ) )	{	return( PARAMETER_TYPE_Int              );	}
	if( !Identifier.Cmp("double"      ) )	{	return( PARAMETER_TYPE_Double           );	}
	if( !Identifier.Cmp("degree"      ) )	{	return( PARAMETER_TYPE_Degree           );	}
	if( !Identifier.Cmp("date"        ) )	{	return( PARAMETER_TYPE_Date             );	}
	if( !Identifier.Cmp("range"       ) )	{	return( PARAMETER_TYPE_Range            );	}
	if( !Identifier.Cmp("datatype"    ) )	{	return( PARAMETER_TYPE_Data_Type        );	}
	if( !Identifier.Cmp("choice"      ) )	{	return( PARAMETER_TYPE_Choice           );	}
	if( !Identifier.Cmp("choices"     ) )	{	return( PARAMETER_TYPE_Choices          );	}

	if( !Identifier.Cmp("text"        ) )	{	return( PARAMETER_TYPE_String           );	}
	if( !Identifier.Cmp("long_text"   ) )	{	return( PARAMETER_TYPE_Text             );	}
	if( !Identifier.Cmp("file"        ) )	{	return( PARAMETER_TYPE_FilePath         );	}

	if( !Identifier.Cmp("font"        ) )	{	return( PARAMETER_TYPE_Font             );	}
	if( !Identifier.Cmp("color"       ) )	{	return( PARAMETER_TYPE_Color            );	}
	if( !Identifier.Cmp("colors"      ) )	{	return( PARAMETER_TYPE_Colors           );	}
	if( !Identifier.Cmp("static_table") )	{	return( PARAMETER_TYPE_FixedTable       );	}
	if( !Identifier.Cmp("grid_system" ) )	{	return( PARAMETER_TYPE_Grid_System      );	}
	if( !Identifier.Cmp("table_field" ) )	{	return( PARAMETER_TYPE_Table_Field      );	}
	if( !Identifier.Cmp("table_fields") )	{	return( PARAMETER_TYPE_Table_Fields     );	}

	if( !Identifier.Cmp("data_object" ) )	{	return( PARAMETER_TYPE_DataObject_Output);	}
	if( !Identifier.Cmp("grid"        ) )	{	return( PARAMETER_TYPE_Grid             );	}
	if( !Identifier.Cmp("grids"       ) )	{	return( PARAMETER_TYPE_Grids            );	}
	if( !Identifier.Cmp("table"       ) )	{	return( PARAMETER_TYPE_Table            );	}
	if( !Identifier.Cmp("shapes"      ) )	{	return( PARAMETER_TYPE_Shapes           );	}
	if( !Identifier.Cmp("tin"         ) )	{	return( PARAMETER_TYPE_TIN              );	}
	if( !Identifier.Cmp("points"      ) )	{	return( PARAMETER_TYPE_PointCloud       );	}

	if( !Identifier.Cmp("grid_list"   ) )	{	return( PARAMETER_TYPE_Grid_List        );	}
	if( !Identifier.Cmp("grids_list"  ) )	{	return( PARAMETER_TYPE_Grids_List       );	}
	if( !Identifier.Cmp("table_list"  ) )	{	return( PARAMETER_TYPE_Table_List       );	}
	if( !Identifier.Cmp("shapes_list" ) )	{	return( PARAMETER_TYPE_Shapes_List      );	}
	if( !Identifier.Cmp("tin_list"    ) )	{	return( PARAMETER_TYPE_TIN_List         );	}
	if( !Identifier.Cmp("points_list" ) )	{	return( PARAMETER_TYPE_PointCloud_List  );	}

	if( !Identifier.Cmp("parameters"  ) )	{	return( PARAMETER_TYPE_Parameters       );	}

	return( PARAMETER_TYPE_Undefined );
}


///////////////////////////////////////////////////////////
//                                                       //
//                         Node	                         //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Node::CSG_Parameter_Node(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}


///////////////////////////////////////////////////////////
//                                                       //
//                         Bool                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Bool::CSG_Parameter_Bool(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Value	= false;
}

//---------------------------------------------------------
bool CSG_Parameter_Bool::is_Default(void) const
{
	return( m_Value == (Get_Default().asInt() != 0) );
}

//---------------------------------------------------------
bool CSG_Parameter_Bool::Toggle_Value(void)
{
	return( Set_Value(asBool() ? 0 : 1) );
}

//---------------------------------------------------------
int CSG_Parameter_Bool::_Set_Value(int Value)
{
	bool bValue = Value != 0;

	if( m_Value != bValue )
	{
		m_Value = bValue;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

int CSG_Parameter_Bool::_Set_Value(double Value)
{
	return( _Set_Value((int)Value) );
}

int CSG_Parameter_Bool::_Set_Value(const CSG_String &Value)
{
	if( !Value.CmpNoCase(_TL("true" )) || !Value.CmpNoCase(_TL("yes")) )
	{
		return( _Set_Value(1) );
	}

	if( !Value.CmpNoCase(_TL("false")) || !Value.CmpNoCase(_TL("no" )) )
	{
		return( _Set_Value(0) );
	}

	int i;

	if( Value.asInt(i) )
	{
		return( _Set_Value(i) );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Bool::_Set_String(void)
{
	m_String = m_Value ? _TL("true") : _TL("false");
}

//---------------------------------------------------------
bool CSG_Parameter_Bool::_Assign(CSG_Parameter *pSource)
{
	m_Value = pSource->asBool();

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Bool::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Content(m_Value ? "true" : "false");
	}
	else
	{
		m_Value = Entry.Cmp_Content("true", true);
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                        Value                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Value::CSG_Parameter_Value(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Minimum	= 0.;
	m_bMinimum	= false;

	m_Maximum	= 0.;
	m_bMaximum	= false;
}

//---------------------------------------------------------
bool CSG_Parameter_Value::Set_Valid_Range(double Minimum, double Maximum)
{
	if( m_bMinimum && m_bMaximum && Minimum > Maximum )
	{
		m_Minimum	= Maximum;
		m_Maximum	= Minimum;
	}
	else
	{
		m_Minimum	= Minimum;
		m_Maximum	= Maximum;
	}

	int	Result;

	switch( Get_Type() )
	{
	case PARAMETER_TYPE_Double:
	case PARAMETER_TYPE_Degree: Result = _Set_Value(asDouble()); break;
	case PARAMETER_TYPE_Int   : Result = _Set_Value(asInt   ()); break;
	default                   : return( false );
	}

	if( Result == SG_PARAMETER_DATA_SET_CHANGED )
	{
		has_Changed();
	}

	return( Result != SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Value::Set_Minimum(double Minimum, bool bOn)
{
	if( bOn == false )
	{
		m_bMinimum	= false;
	}
	else
	{
		m_bMinimum	= true;

		if( m_bMaximum && m_Maximum < Minimum )
		{
			m_Maximum	= Minimum;
		}

		Set_Valid_Range(Minimum, m_Maximum);
	}
}

//---------------------------------------------------------
void CSG_Parameter_Value::Set_Maximum(double Maximum, bool bOn)
{
	if( bOn == false )
	{
		m_bMaximum	= false;
	}
	else
	{
		m_bMaximum	= true;

		if( m_bMinimum && m_Minimum > Maximum )
		{
			m_Minimum	= Maximum;
		}

		Set_Valid_Range(m_Minimum, Maximum);
	}
}

//---------------------------------------------------------
bool CSG_Parameter_Value::_Assign(CSG_Parameter *pSource)
{
	m_Minimum	= pSource->asValue()->m_Minimum;
	m_bMinimum	= pSource->asValue()->m_bMinimum;

	m_Maximum	= pSource->asValue()->m_Maximum;
	m_bMaximum	= pSource->asValue()->m_bMaximum;

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                         Int                           //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Int::CSG_Parameter_Int(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Value(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Value = 0;
}

//---------------------------------------------------------
bool CSG_Parameter_Int::is_Default(void) const
{
	return( m_Value == Get_Default().asInt() );
}

//---------------------------------------------------------
int CSG_Parameter_Int::_Set_Value(int Value)
{
	if( m_bMinimum && Value < (int)m_Minimum )
	{
		return( _Set_Value((int)m_Minimum) );
	}

	if( m_bMaximum && Value > (int)m_Maximum )
	{
		return( _Set_Value((int)m_Maximum) );
	}

	if( m_Value != Value )
	{
		m_Value	= Value;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

int CSG_Parameter_Int::_Set_Value(double Value)
{
	return( _Set_Value((int)Value) );
}

int CSG_Parameter_Int::_Set_Value(const CSG_String &Value)
{
	int i;

	if( Value.asInt(i) )
	{
		return( _Set_Value(i) );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Int::_Set_String(void)
{
	m_String.Printf("%d", m_Value);
}

//---------------------------------------------------------
bool CSG_Parameter_Int::_Assign(CSG_Parameter *pSource)
{
	CSG_Parameter_Value::_Assign(pSource);

	return( _Set_Value(((CSG_Parameter_Value *)pSource)->asInt()) != 0 );
}

//---------------------------------------------------------
bool CSG_Parameter_Int::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Content(asString());
	}
	else
	{
		return( Entry.Get_Content().asInt(m_Value) );
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Double                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Double::CSG_Parameter_Double(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Value(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Value = 0.;
}

//---------------------------------------------------------
bool CSG_Parameter_Double::is_Default(void) const
{
	return( m_Value == Get_Default().asDouble() );
}

//---------------------------------------------------------
int CSG_Parameter_Double::_Set_Value(int Value)
{
	return( _Set_Value((double)Value) );
}

int CSG_Parameter_Double::_Set_Value(double Value)
{
	if( m_bMinimum && Value < m_Minimum )
	{
		return( _Set_Value(m_Minimum) );
	}

	if( m_bMaximum && Value > m_Maximum )
	{
		return( _Set_Value(m_Maximum) );
	}

	if( m_Value != Value )
	{
		m_Value	= Value;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

int  CSG_Parameter_Double::_Set_Value(const CSG_String &Value)
{
	double	d;

	if( Value.asDouble(d) )
	{
		return( _Set_Value(d) );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Double::_Set_String(void)
{
	m_String.Printf("%.*f", SG_Get_Significant_Decimals(m_Value, 16), m_Value);
}

//---------------------------------------------------------
bool CSG_Parameter_Double::_Assign(CSG_Parameter *pSource)
{
	CSG_Parameter_Value::_Assign(pSource);

	return( _Set_Value(pSource->asDouble()) != 0 );
}

//---------------------------------------------------------
bool CSG_Parameter_Double::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Fmt_Content("%.*f", SG_Get_Significant_Decimals(m_Value, 16), m_Value);
	}
	else
	{
		return( Entry.Get_Content().asDouble(m_Value) );
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Degree                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Degree::CSG_Parameter_Degree(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Double(pOwner, pParent, ID, Name, Description, Constraint)
{
	Set_Collapsed();
}

//---------------------------------------------------------
int CSG_Parameter_Degree::_Set_Value(const CSG_String &Value)
{
	return( CSG_Parameter_Double::_Set_Value(SG_Degree_To_Double(Value)) );
}

//---------------------------------------------------------
void CSG_Parameter_Degree::_Set_String(void)
{
	m_String = SG_Double_To_Degree(asDouble());
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Date                            //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Date::CSG_Parameter_Date(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	_Set_Value(CSG_DateTime::Now().Get_JDN());
}

//---------------------------------------------------------
int CSG_Parameter_Date::_Set_Value(int Value)
{
	return( _Set_Value((double)Value) );
}

int CSG_Parameter_Date::_Set_Value(double Value)
{
	Value	= 0.5 + floor(Value);	// always adjust to high noon, prevents rounding problems (we're not intested in time, just date!)

	if( Value != asDouble() )
	{
		m_Date.Set(Value);

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

int CSG_Parameter_Date::_Set_Value(const CSG_String &Value)
{
	CSG_DateTime	Date;

	if( Date.Parse_ISODate(Value) )
	{
		if( !m_Date.is_EqualTo(Date) )
		{
			m_Date.Set(Date);

			return( SG_PARAMETER_DATA_SET_CHANGED );
		}

		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	if( Date.Parse_Date(Value) )
	{
		if( !m_Date.is_EqualTo(Date) )
		{
			m_Date.Set(Date);

			return( SG_PARAMETER_DATA_SET_CHANGED );
		}

		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Date::_Set_String(void)
{
	m_String	= m_Date.Format_ISODate();
}

//---------------------------------------------------------
int CSG_Parameter_Date::_asInt(void)	const
{
	return( (int)asDouble() );
}

//---------------------------------------------------------
double CSG_Parameter_Date::_asDouble(void)	const
{
	return( m_Date.Get_JDN() );
}

//---------------------------------------------------------
void CSG_Parameter_Date::Set_Date(const CSG_DateTime &Date)
{
	m_Date	= Date;
}

//---------------------------------------------------------
bool CSG_Parameter_Date::_Assign(CSG_Parameter *pSource)
{
	m_Date	= ((CSG_Parameter_Date *)pSource)->m_Date;

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Date::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Content(asString());
	}
	else
	{
		_Set_Value(Entry.Get_Content());
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Range                           //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Range::CSG_Parameter_Range(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_pRange = new CSG_Parameters;

	if( is_Information() )
	{
		m_pMin = (CSG_Parameter_Double *)m_pRange->Add_Info_Value(ID, "MIN", "Minimum", Description, PARAMETER_TYPE_Double);
		m_pMax = (CSG_Parameter_Double *)m_pRange->Add_Info_Value(ID, "MAX", "Maximum", Description, PARAMETER_TYPE_Double);
	}
	else
	{
		m_pMin = (CSG_Parameter_Double *)m_pRange->Add_Double    (ID, "MIN", "Minimum", Description);
		m_pMax = (CSG_Parameter_Double *)m_pRange->Add_Double    (ID, "MAX", "Maximum", Description);
	}

	Set_Collapsed();
}

CSG_Parameter_Range::~CSG_Parameter_Range(void)
{
	delete(m_pRange);
}

//---------------------------------------------------------
void CSG_Parameter_Range::_Set_String(void)
{
	m_String.Printf("%.*f; %.*f",
		SG_Get_Significant_Decimals(Get_Min(), 16), Get_Min(),
		SG_Get_Significant_Decimals(Get_Min(), 16), Get_Max()
	);
}

//---------------------------------------------------------
int CSG_Parameter_Range::_Set_Value(const CSG_String &Value)
{
	return( Set_Range(Value.BeforeFirst(';').asDouble(), Value.AfterFirst(';').asDouble()) ? SG_PARAMETER_DATA_SET_CHANGED : SG_PARAMETER_DATA_SET_FALSE );
}

bool CSG_Parameter_Range::Set_Range(double Min, double Max)
{
	bool bResult;

	if( Min > Max )
	{
		bResult  = m_pMin->Set_Value(Max);
		bResult |= m_pMax->Set_Value(Min);
	}
	else
	{
		bResult  = m_pMin->Set_Value(Min);
		bResult |= m_pMax->Set_Value(Max);
	}

	return( bResult );
}

//---------------------------------------------------------
bool CSG_Parameter_Range::Set_Min(double Value)
{
	if( m_pMin->Set_Value(Value) )
	{
		has_Changed();

		return( true );
	}

	return( false );
}

double CSG_Parameter_Range::Get_Min(void)	const
{
	return( m_pMin->asDouble() );
}

//---------------------------------------------------------
bool CSG_Parameter_Range::Set_Max(double Value)
{
	if( m_pMax->Set_Value(Value) )
	{
		has_Changed();

		return( true );
	}

	return( false );
}

double CSG_Parameter_Range::Get_Max(void)	const
{
	return( m_pMax->asDouble() );
}

//---------------------------------------------------------
bool CSG_Parameter_Range::is_Default(void) const
{
	return( m_pMin->is_Default() && m_pMax->is_Default() );
}

//---------------------------------------------------------
bool CSG_Parameter_Range::Restore_Default(void)
{
	return( m_pMin->Restore_Default() && m_pMax->Restore_Default() );
}

//---------------------------------------------------------
bool CSG_Parameter_Range::_Assign(CSG_Parameter *pSource)
{
	m_pMin->Assign(pSource->asRange()->m_pMin);
	m_pMax->Assign(pSource->asRange()->m_pMax);

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Range::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Fmt_Content("%.*f; %.*f",
			SG_Get_Significant_Decimals(Get_Min(), 16), Get_Min(),
			SG_Get_Significant_Decimals(Get_Min(), 16), Get_Max()
		);

		return( true );
	}
	else
	{
		CSG_String	s(Entry.Get_Content());	double	Min, Max;

		if( s.BeforeFirst(';').asDouble(Min) && s.AfterFirst(';').asDouble(Max) )
		{
			return( Set_Range(Min, Max) );
		}
	}

	return( false );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Choice                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Choice::CSG_Parameter_Choice(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Value = -1;
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::is_Default(void) const
{
	return( m_Value == Get_Default().asInt() );
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::Toggle_Value(void)
{
	return( Get_Count() > 1 && Set_Value((asInt() + 1) % Get_Count()) );
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::Del_Items(void)
{
	m_Items.Clear(); m_Data.Clear();

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::Add_Item(const CSG_String &Item, const CSG_String &Data)
{
	if( !Item.is_Empty() )
	{
		m_Items.Add(Item);
		m_Data .Add(Data);

		_Set_String();	// items have changed

		return( true );
	}

	return( false );
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::Set_Items(const SG_Char *String)
{
	m_Items.Clear(); m_Data.Clear();

	if( String && *String != '\0' )
	{
		CSG_Strings Items(SG_String_Tokenize(String, "|"));

		for(int i=0; i<Items.Get_Count(); i++)
		{
			if( Items[i].Find('{') == 0 && Items[i].Find('}') > 0 )	// data entry within leading curly brackets: '{data} item text'
			{
				CSG_String Data(Items[i].AfterFirst('{').BeforeFirst('}'));
				CSG_String Item(Items[i].AfterFirst('}')); Item.Trim();

				Add_Item(Item, Data);
			}
			else
			{
				Add_Item(Items[i]);
			}
		}
	}

	if( m_Value < 0 && m_Items.Get_Count() > 0 )
	{
		m_Value	= 0;
	}

	if( m_Value >= m_Items.Get_Count() )
	{
		m_Value	= m_Items.Get_Count() - 1;
	}

	_Set_String(); // items have changed

	return( Get_Count() > 0 );
}

//---------------------------------------------------------
CSG_String CSG_Parameter_Choice::Get_Items(bool bIncludeData) const
{
	CSG_String Items;

	for(int i=0; i<Get_Count(); i++)
	{
		if( i > 0 )
		{
			Items += "|";
		}

		if( bIncludeData )
		{
			Items += "{" + m_Data[i] + "}";
		}

		Items += m_Items[i];
	}

	return( Items );
}

//---------------------------------------------------------
const SG_Char * CSG_Parameter_Choice::Get_Item(int Index)	const
{
	if( Index >= 0 && Index < Get_Count() )
	{
		return( m_Items[Index] );
	}

	return( NULL );
}

//---------------------------------------------------------
CSG_String CSG_Parameter_Choice::Get_Item_Data(int Index)	const
{
	if( Index >= 0 && Index < Get_Count() )
	{
		return( m_Data[Index] );
	}

	return( "" );
}

CSG_String CSG_Parameter_Choice::Get_Data(void)	const
{
	return( Get_Item_Data(m_Value) );
}

bool CSG_Parameter_Choice::Get_Data(CSG_String &Value)	const
{
	Value = Get_Item_Data(m_Value);

	return( !Value.is_Empty() );
}

bool CSG_Parameter_Choice::Get_Data(int &Value)	const
{
	CSG_String String;

	return( Get_Data(String) && String.asInt(Value) );
}

bool CSG_Parameter_Choice::Get_Data(double &Value)	const
{
	CSG_String String;

	return( Get_Data(String) && String.asDouble(Value) );
}

//---------------------------------------------------------
int CSG_Parameter_Choice::_Set_Value(int Value)
{
	if( Value >= 0 && Value < m_Items.Get_Count() )
	{
		if( m_Value != Value )
		{
			m_Value = Value;

			return( SG_PARAMETER_DATA_SET_CHANGED );
		}

		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
int CSG_Parameter_Choice::_Set_Value(double Value)
{
	return( _Set_Value((int)Value) );
}

//---------------------------------------------------------
int CSG_Parameter_Choice::_Set_Value(CSG_Grid_Resampling Value)
{
	CSG_Grid_Resampling Resampling = asGrid_Resampling();
	
	if( Resampling != CSG_Grid_Resampling::Undefined )
	{
		if( Resampling == Value )
		{
			return( SG_PARAMETER_DATA_SET_TRUE );
		}

		for(int i=0, Data; i<m_Data.Get_Count(); i++)
		{
			if( m_Data[i].asInt(Data) && Data == (int)Value )
			{
				m_Value = i;

				return( SG_PARAMETER_DATA_SET_CHANGED );
			}
		}
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
int CSG_Parameter_Choice::_Set_Value(const CSG_String &Value)
{
	if( !Value.is_Empty() )
	{
		for(int i=0; i<m_Items.Get_Count(); i++)
		{
			if( !Value.Cmp(Get_Item_Data(i)) || !Value.Cmp(Get_Item(i)) )
			{
				return( _Set_Value(i) );
			}
		}

		int Index; // choice not found? then test, if value string is an integer specifying the index position

		if( Value.asInt(Index) && Index >= 0 && Index < m_Items.Get_Count() )
		{
			return( _Set_Value(Index) );
		}

	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Choice::_Set_String(void)
{
	m_String = m_Value >= 0 && m_Value < Get_Count() ? Get_Item(m_Value) : _TL("<no choice available>");
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::_Assign(CSG_Parameter *pSource)
{
	m_Items = pSource->asChoice()->m_Items;
	m_Data  = pSource->asChoice()->m_Data ;
	m_Value = pSource->asChoice()->m_Value;

	_Set_String(); // items have changed

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Choice::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Add_Property("index", m_Value);

		Entry.Set_Content(asString());

		return( true );
	}
	else
	{
		int	Index;

		return( (Entry.Get_Property("index", Index) || Entry.Get_Content().asInt(Index)) && _Set_Value(Index) );
	}
}


///////////////////////////////////////////////////////////
//                                                       //
//                      Data Type                        //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Data_Type::CSG_Parameter_Data_Type(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Choice(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
/**
* This function initializes the data types available for
* selection. The Data_Types argument expects a combination
* of data type flags as defined in <api_core.h>, e.g.
* SG_DATATYPES_Integer or SG_DATATYPES_Numeric. You can add
* an additional choice with the User argument, e.g. to offer
* a type related to an selected input data set.
*/
//---------------------------------------------------------
bool CSG_Parameter_Data_Type::Set_Data_Types(int Data_Types, TSG_Data_Type Default, const CSG_String &User)
{
	if( Data_Types <= SG_DATATYPES_Undefined )
	{
		Data_Types = SG_DATATYPES_Standard;
	}

	if( Default == SG_DATATYPE_Undefined && User.is_Empty() )
	{
		switch( Data_Types )
		{
		case (SG_DATATYPES_Integer                 ): Default = SG_DATATYPE_Int   ; break;
		case (SG_DATATYPES_Integer|SG_DATATYPES_Bit): Default = SG_DATATYPE_Int   ; break;
		case (SG_DATATYPES_Numeric                 ): Default = SG_DATATYPE_Float ; break;
		case (SG_DATATYPES_Numeric|SG_DATATYPES_Bit): Default = SG_DATATYPE_Float ; break;
		case (SG_DATATYPES_Table                   ): Default = SG_DATATYPE_String; break;
		case (SG_DATATYPES_Standard                ): Default = SG_DATATYPE_String; break;
		}
	}

	#define ADD_TYPE(type) if( (Data_Types & SG_Data_Type_Get_Flag(type)) != 0 ) {  if( Default == type ) { _Default = Get_Count(); } Add_Item(SG_Data_Type_Get_Name(type), SG_Data_Type_Get_Identifier(type)); }

	int _Default = -1;

	ADD_TYPE(SG_DATATYPE_String); // data types are added in this order to the choice item list
	ADD_TYPE(SG_DATATYPE_Date  );
	ADD_TYPE(SG_DATATYPE_Color );
	ADD_TYPE(SG_DATATYPE_Bit   );
	ADD_TYPE(SG_DATATYPE_Byte  );
	ADD_TYPE(SG_DATATYPE_Char  );
	ADD_TYPE(SG_DATATYPE_Word  );
	ADD_TYPE(SG_DATATYPE_Short );
	ADD_TYPE(SG_DATATYPE_DWord );
	ADD_TYPE(SG_DATATYPE_Int   );
	ADD_TYPE(SG_DATATYPE_ULong );
	ADD_TYPE(SG_DATATYPE_Long  );
	ADD_TYPE(SG_DATATYPE_Float );
	ADD_TYPE(SG_DATATYPE_Double);
	ADD_TYPE(SG_DATATYPE_Binary);

	if( !User.is_Empty() )
	{
		if( _Default < 0 )
		{
			_Default = Get_Count();
		}

		Add_Item(User, SG_Data_Type_Get_Identifier(SG_DATATYPE_Undefined));
	}
	else if( _Default < 0 )
	{
		_Default = 0;
	}

	Set_Default(_Default); Set_Value(_Default);

	return( true );
}

//---------------------------------------------------------
/**
* Select a data type from the choices list after it has been
* initialized. Useful e.g. when adjusting a default data type
* in CSG_Tool::On_Parameters_Changed() to a changed input data
* selection.
*/
//---------------------------------------------------------
bool CSG_Parameter_Data_Type::Set_Data_Type(TSG_Data_Type Value)
{
	for(int i=0; i<Get_Count(); i++)
	{
		if( Value == SG_Data_Type_Get_Type(Get_Item_Data(i)) )
		{
			return( Set_Value(i) );
		}
	}

	return( false );
}

//---------------------------------------------------------
/**
* This function returns the selected data type. If an additional
* 'user' option has been added and is selected, the data type
* returned is the one given as 'Default' argument. This is useful
* e.g. if you want to return a data type that comes from an input
* data set.
*/
//---------------------------------------------------------
TSG_Data_Type CSG_Parameter_Data_Type::Get_Data_Type(TSG_Data_Type Default)	const
{
	TSG_Data_Type Type = SG_Data_Type_Get_Type(Get_Data());

	return( Type == SG_DATATYPE_Undefined ? Default : Type );
}

//---------------------------------------------------------
bool CSG_Parameter_Data_Type::_Assign(CSG_Parameter *pSource)
{
	return( CSG_Parameter_Choice::_Assign(pSource) );
}

//---------------------------------------------------------
bool CSG_Parameter_Data_Type::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	return( CSG_Parameter_Choice::_Serialize(Entry, bSave) );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Choices                         //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Choices::CSG_Parameter_Choices(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_Choices::_Set_Value(const CSG_String &Value)
{
	CSG_String_Tokenizer	Tokens(Value, ";");

	m_Selection.Destroy();

	while( Tokens.Has_More_Tokens() )
	{
		int	Index;

		if( Tokens.Get_Next_Token().asInt(Index) )
		{
			Select(Index);
		}
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
void CSG_Parameter_Choices::_Set_String(void)
{
	m_String.Clear();

	for(size_t i=0; i<m_Selection.Get_uSize(); i++)
	{
		m_String	+= CSG_String::Format("%d;", m_Selection[i]);
	}
}

//---------------------------------------------------------
void CSG_Parameter_Choices::Set_Items(const CSG_String &Items)
{
	Del_Items();

	CSG_String_Tokenizer	Tokens(Items, "|");

	while( Tokens.Has_More_Tokens() )
	{
		Add_Item(Tokens.Get_Next_Token());
	}
}

//---------------------------------------------------------
void CSG_Parameter_Choices::Set_Items(const CSG_Strings &Items)
{
	Del_Items();

	for(int i=0; i<Items.Get_Count(); i++)
	{
		Add_Item(Items[i]);
	}
}

//---------------------------------------------------------
CSG_String CSG_Parameter_Choices::Get_Items(void) const
{
	CSG_String	Items;

	for(int i=0; i<m_Items[0].Get_Count(); i++)
	{
		if( i > 0 )
		{
			Items	+= "|";
		}

		Items	+= m_Items[0][i];
	}

	return( Items );
}

//---------------------------------------------------------
void CSG_Parameter_Choices::Del_Items(void)
{
	m_Items[0].Clear();
	m_Items[1].Clear();

	m_Selection.Destroy();
}

//---------------------------------------------------------
void CSG_Parameter_Choices::Add_Item(const CSG_String &Item, const CSG_String &Data)
{
	m_Items[0]	+= Item;
	m_Items[1]	+= Data;
}

//---------------------------------------------------------
bool CSG_Parameter_Choices::is_Selected(int Index)
{
	for(size_t i=0; i<m_Selection.Get_uSize(); i++)
	{
		if( Index == m_Selection[i] )
		{
			return( true );
		}
	}

	return( false );
}

//---------------------------------------------------------
bool CSG_Parameter_Choices::Select(int Index, bool bSelect)
{
	if( Index >= 0 && Index < Get_Item_Count() )
	{
		if( bSelect && !is_Selected(Index) )
		{
			m_Selection	+= Index;
		}
		else if( !bSelect )
		{
			for(size_t i=0; i<m_Selection.Get_uSize(); i++)
			{
				if( Index == m_Selection[i] )
				{
					for(size_t j=i+1; j<m_Selection.Get_uSize(); i++, j++)
					{
						m_Selection[i]	= m_Selection[j];
					}

					m_Selection.Dec_Array();
				}
			}
		}

		return( true );
	}

	return( false );
}

//---------------------------------------------------------
bool CSG_Parameter_Choices::Clr_Selection(void)
{
	m_Selection.Destroy();

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Choices::_Assign(CSG_Parameter *pSource)
{
	m_Items[0]	= pSource->asChoices()->m_Items[0];
	m_Items[1]	= pSource->asChoices()->m_Items[1];

	m_Selection	= pSource->asChoices()->m_Selection;

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Choices::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Content(asString());

		return( true );
	}
	else
	{
		return( _Set_Value(Entry.Get_Content()) != 0 );
	}
}


///////////////////////////////////////////////////////////
//                                                       //
//                       String                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_String::CSG_Parameter_String(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_bPassword	= false;
}

//---------------------------------------------------------
bool CSG_Parameter_String::is_Valid(void)	const
{
	return( !m_String.is_Empty() );
}

//---------------------------------------------------------
void CSG_Parameter_String::Set_Password(bool bOn)
{
	m_bPassword	= bOn;
}

//---------------------------------------------------------
bool CSG_Parameter_String::is_Password(void)	const
{
	return( m_bPassword );
}

//---------------------------------------------------------
int CSG_Parameter_String::_Set_Value(const CSG_String &Value)
{
	if( m_String.Cmp(Value) )
	{
		m_String	= Value;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
bool CSG_Parameter_String::_Assign(CSG_Parameter *pSource)
{
	m_String	= ((CSG_Parameter_String *)pSource)->m_String;
	m_bPassword	= ((CSG_Parameter_String *)pSource)->m_bPassword;

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_String::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Content(m_String);
	}
	else
	{
		m_String	= Entry.Get_Content();
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Text                            //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Text::CSG_Parameter_Text(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_String(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}


///////////////////////////////////////////////////////////
//                                                       //
//                      FilePath                         //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_File_Name::CSG_Parameter_File_Name(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_String(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Filter.Printf("%s|*.*", _TL("All Files"));

	m_bSave			= false;
	m_bMultiple		= false;
	m_bDirectory	= false;
}

//---------------------------------------------------------
void CSG_Parameter_File_Name::Set_Filter(const SG_Char *Filter)
{
	if( Filter )
	{
		m_Filter	= Filter;
	}
	else
	{
		m_Filter.Printf("%s|*.*", _TL("All Files"));
	}
}

const SG_Char *  CSG_Parameter_File_Name::Get_Filter(void)	const
{
	return( m_Filter.c_str() );
}

//---------------------------------------------------------
void CSG_Parameter_File_Name::Set_Flag_Save(bool bFlag)
{
	m_bSave			= bFlag;
}

void CSG_Parameter_File_Name::Set_Flag_Multiple(bool bFlag)
{
	m_bMultiple		= bFlag;
}

void CSG_Parameter_File_Name::Set_Flag_Directory(bool bFlag)
{
	m_bDirectory	= bFlag;
}

//---------------------------------------------------------
bool CSG_Parameter_File_Name::Get_FilePaths(CSG_Strings &FilePaths)	const
{
	FilePaths.Clear();

	if( m_String.Length() > 0 )
	{
		if( !m_bMultiple )
		{
			FilePaths.Add(m_String);
		}
		else if( m_String[0] != '\"' )
		{
			FilePaths.Add(m_String);
		}
		else
		{
			CSG_String	s(m_String);

			while( s.Length() > 2 )
			{
				s	= s.AfterFirst('\"');
				FilePaths.Add(s.BeforeFirst('\"'));
				s	= s.AfterFirst('\"');
			}
		}
	}

	return( FilePaths.Get_Count() > 0 );
}

//---------------------------------------------------------
bool CSG_Parameter_File_Name::_Assign(CSG_Parameter *pSource)
{
	CSG_Parameter_String::_Assign(pSource);

	Set_Filter(((CSG_Parameter_File_Name *)pSource)->m_Filter.c_str());

	m_bSave			= pSource->asFilePath()->m_bSave;
	m_bMultiple		= pSource->asFilePath()->m_bMultiple;
	m_bDirectory	= pSource->asFilePath()->m_bDirectory;

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Font                            //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Font::CSG_Parameter_Font(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	Restore_Default();
}

//---------------------------------------------------------
bool CSG_Parameter_Font::Restore_Default(void)
{
	m_Color  = SG_GET_RGB(0, 0, 0);
#ifdef __WXMAC__
	m_String = ".applesystemuifont 11 utf-8";
#else
	m_String = "0;-12;0;0;0;400;0;0;0;0;3;2;1;34;Arial";
#endif

	return( true );
}

//---------------------------------------------------------
int CSG_Parameter_Font::_Set_Value(int Value)
{
	if( m_Color != Value )
	{
		m_Color = Value;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
int CSG_Parameter_Font::_Set_Value(const CSG_String &Value)
{
	if( Value.is_Empty() )
	{
		Restore_Default();

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	m_String = Value;

	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
int CSG_Parameter_Font::_asInt(void)	const
{
	return( m_Color );
}

//---------------------------------------------------------
void * CSG_Parameter_Font::_asPointer(void)	const
{
	return( (void *)m_String.c_str() );
}

//---------------------------------------------------------
bool CSG_Parameter_Font::_Assign(CSG_Parameter *pSource)
{
	m_Color  = ((CSG_Parameter_Font *)pSource)->m_Color;
	m_String = ((CSG_Parameter_Font *)pSource)->m_String;

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Font::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Add_Child("COLOR", CSG_String::Format("R%03d G%03d B%03d",
			SG_GET_R(m_Color), SG_GET_G(m_Color), SG_GET_B(m_Color)
		));

		Entry.Add_Child("FONT", m_String);
	}
	else
	{
		if( Entry("COLOR") != NULL )
		{
			_Set_Value((int)SG_GET_RGB(
				Entry("COLOR")->Get_Content().AfterFirst('R').asInt(),
				Entry("COLOR")->Get_Content().AfterFirst('G').asInt(),
				Entry("COLOR")->Get_Content().AfterFirst('B').asInt()
			));
		}

		if( Entry("FONT") != NULL )
		{
			_Set_Value(Entry("FONT")->Get_Content());
		}
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Color                           //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Color::CSG_Parameter_Color(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Int(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_Color::_Set_Value(const CSG_String &Value)
{
	long	l;

	if( SG_Color_From_Text(Value, l) )
	{
		return( CSG_Parameter_Int::_Set_Value((int)l) );
	}

	int		i;

	if( Value.asInt(i) )
	{
		return( CSG_Parameter_Int::_Set_Value(i) );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
bool CSG_Parameter_Color::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Fmt_Content("R%03d G%03d B%03d", SG_GET_R(m_Value), SG_GET_G(m_Value), SG_GET_B(m_Value));
	}
	else
	{
		m_Value	= SG_GET_RGB(
			Entry.Get_Content().AfterFirst('R').asInt(),
			Entry.Get_Content().AfterFirst('G').asInt(),
			Entry.Get_Content().AfterFirst('B').asInt()
		);
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Colors                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Colors::CSG_Parameter_Colors(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_Colors::_Set_Value(int Value)
{
	if( Value >= 0 && Value < CSG_Colors::Get_Predefined_Count() )
	{
		if( m_Colors.Create(0, Value) )
		{
			return( SG_PARAMETER_DATA_SET_CHANGED );
		}
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
int CSG_Parameter_Colors::_Set_Value(const CSG_String &Value)
{
	CSG_Colors Colors;

	if( Colors.Load(Value) )
	{
		m_Colors = Colors;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
int CSG_Parameter_Colors::_Set_Value(void *Value)
{
	try
	{
		if( Value && m_Colors.Create(*(CSG_Colors *)Value) )
		{
			return( SG_PARAMETER_DATA_SET_CHANGED );
		}
	}
	catch(...)
	{
	}

	return( SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
void CSG_Parameter_Colors::_Set_String(void)
{
	m_String.Printf("%d %s", m_Colors.Get_Count(), _TL("colors"));
}

//---------------------------------------------------------
int CSG_Parameter_Colors::_asInt(void)	const
{
	return( m_Colors.Get_Count() );
}

//---------------------------------------------------------
void * CSG_Parameter_Colors::_asPointer(void)	const
{
	return( (void *)&m_Colors );
}

//---------------------------------------------------------
bool CSG_Parameter_Colors::_Assign(CSG_Parameter *pSource)
{
	return( m_Colors.Assign(pSource->asColors()) );
}

//---------------------------------------------------------
bool CSG_Parameter_Colors::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		for(int i=0; i<m_Colors.Get_Count(); i++)
		{
			Entry.Add_Child("COLOR", CSG_String::Format("R%03d G%03d B%03d",
				m_Colors.Get_Red  (i),
				m_Colors.Get_Green(i),
				m_Colors.Get_Blue (i))
			);
		}
	}
	else
	{
		if( Entry.Get_Children_Count() <= 1 )
		{
			return( false );
		}

		m_Colors.Set_Count(Entry.Get_Children_Count());

		for(int i=0; i<m_Colors.Get_Count(); i++)
		{
			CSG_String	s(Entry(i)->Get_Content());

			m_Colors.Set_Red  (i, s.AfterFirst('R').asInt());
			m_Colors.Set_Green(i, s.AfterFirst('G').asInt());
			m_Colors.Set_Blue (i, s.AfterFirst('B').asInt());
		}
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                     FixedTable                        //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Fixed_Table::CSG_Parameter_Fixed_Table(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Table.Set_Name(_TL("Table"));
}

//---------------------------------------------------------
int CSG_Parameter_Fixed_Table::_Set_Value(void *Value)
{
	if( Value && m_Table.Assign_Values((CSG_Table *)Value) )
	{
		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
void CSG_Parameter_Fixed_Table::_Set_String(void)
{
	m_String.Printf("%s (%s: %d, %s: %lld)", m_Table.Get_Name(), _TL("columns"), m_Table.Get_Field_Count(), _TL("rows"), m_Table.Get_Count());
}

//---------------------------------------------------------
void * CSG_Parameter_Fixed_Table::_asPointer(void)	const
{
	return( (void *)&m_Table );
}

//---------------------------------------------------------
bool CSG_Parameter_Fixed_Table::_Assign(CSG_Parameter *pSource)
{
	return( m_Table.Create(*pSource->asTable()) );
}

//---------------------------------------------------------
bool CSG_Parameter_Fixed_Table::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	int	iField;

	if( bSave )
	{
		CSG_MetaData	*pNode	= Entry.Add_Child("FIELDS");

		for(iField=0; iField<m_Table.Get_Field_Count(); iField++)
		{
			CSG_MetaData	*pEntry	= pNode->Add_Child("FIELD", m_Table.Get_Field_Name(iField));

			pEntry->Set_Property("type", gSG_Data_Type_Identifier[m_Table.Get_Field_Type(iField)]);
		}

		pNode	= Entry.Add_Child("RECORDS");

		for(sLong iRecord=0; iRecord<m_Table.Get_Count(); iRecord++)
		{
			CSG_MetaData	*pEntry	= pNode->Add_Child("RECORD");

			CSG_Table_Record	*pRecord	= m_Table.Get_Record(iRecord);

			for(iField=0; iField<m_Table.Get_Field_Count(); iField++)
			{
				pEntry->Add_Child("FIELD", pRecord->asString(iField));
			}
		}
	}
	else
	{
		CSG_MetaData	*pNode;

		if( (pNode = Entry("FIELDS")) == NULL )
		{
			return( false );
		}

		CSG_Table	Table;

		for(iField=0; iField<pNode->Get_Children_Count(); iField++)
		{
			TSG_Data_Type	type	= SG_DATATYPE_String;

			CSG_String	s;

			if( pNode->Get_Child(iField)->Get_Property("type", s) )
			{
				type	= SG_Data_Type_Get_Type(s);
			}

			Table.Add_Field(pNode->Get_Child(iField)->Get_Content(), type == SG_DATATYPE_Undefined ? SG_DATATYPE_String : type);
		}

		if( (pNode = Entry("RECORDS")) == NULL )
		{
			return( false );
		}

		for(int iRecord=0; iRecord<pNode->Get_Children_Count(); iRecord++)
		{
			CSG_MetaData	*pEntry	= pNode->Get_Child(iRecord);

			CSG_Table_Record	*pRecord	= Table.Add_Record();

			for(iField=0; iField<pEntry->Get_Children_Count(); iField++)
			{
				pRecord->Set_Value(iField, pEntry->Get_Child(iField)->Get_Content());
			}
		}

		return( m_Table.Assign_Values(&Table) );
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                     Grid_System                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Grid_System::CSG_Parameter_Grid_System(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_Grid_System::_Set_Value(const CSG_String &Value)
{
	CSG_Grid_System System;

	return( System.Create(Value) ? _Set_Value(&System) : SG_PARAMETER_DATA_SET_FALSE );
}

//---------------------------------------------------------
int CSG_Parameter_Grid_System::_Set_Value(void *Value)
{
	CSG_Grid_System System;

	if( Value != NULL )
	{
		System.Create(*((CSG_Grid_System *)Value));
	}

	if( m_System == System )
	{
		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	m_System = System;

	//-----------------------------------------------------
	bool bCallback = Get_Parameters()->Set_Callback(false); // only update grid parameter objects in 1st loop...

	for(int i=0; i<Get_Children_Count(); i++)
	{
		CSG_Parameter *pParameter = Get_Child(i);

		if( pParameter->is_DataObject() )
		{
			CSG_Data_Object *pObject = pParameter->asDataObject();

			if( pObject != DATAOBJECT_NOTSET && pObject != DATAOBJECT_CREATE )
			{
				bool bInvalid = !m_System.is_Valid() || !(Get_Manager() && Get_Manager()->Exists(pObject));

				if( !bInvalid )
				{
					switch( pObject->Get_ObjectType() )
					{
					case SG_DATAOBJECT_TYPE_Grid : bInvalid = !m_System.is_Equal(((CSG_Grid  *)pObject)->Get_System()); break;
					case SG_DATAOBJECT_TYPE_Grids: bInvalid = !m_System.is_Equal(((CSG_Grids *)pObject)->Get_System()); break;
					default: break;
					}
				}

				if( bInvalid )
				{
					pParameter->Set_Value(DATAOBJECT_NOTSET);
				}
			}
		}

		//-------------------------------------------------
		else if( pParameter->is_DataObject_List() )
		{
			CSG_Parameter_List *pList = pParameter->asList();

			if( !m_System.is_Valid() )
			{
				pList->Del_Items();
			}
			else for(int j=pList->Get_Item_Count()-1; j>=0; j--)
			{
				CSG_Data_Object *pObject = pList->Get_Item(j);

				bool bInvalid = !(Get_Manager() && Get_Manager()->Exists(pObject));

				if( !bInvalid && pObject != DATAOBJECT_NOTSET && pObject != DATAOBJECT_CREATE )
				{
					switch( pObject->Get_ObjectType() )
					{
					case SG_DATAOBJECT_TYPE_Grid : bInvalid = !m_System.is_Equal(((CSG_Grid  *)pObject)->Get_System()); break;
					case SG_DATAOBJECT_TYPE_Grids: bInvalid = !m_System.is_Equal(((CSG_Grids *)pObject)->Get_System()); break;
					default: break;
					}
				}

				if( bInvalid )
				{
					pList->Del_Item(j);
				}
			}
		}
	}

	Get_Parameters()->Set_Callback(bCallback);

	if( bCallback ) // ...process On_Parameter_Changed()/On_Parameters_Enable() in a 2nd loop!
	{
		for(int i=0; i<Get_Children_Count(); i++)
		{
			CSG_Parameter *pParameter = Get_Child(i);

			if( pParameter->is_DataObject() || pParameter->is_DataObject_List() )
			{
				pParameter->has_Changed();
			}
		}
	}

	//-----------------------------------------------------
	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
void CSG_Parameter_Grid_System::_Set_String(void)
{
	m_String = m_System.Get_Name();
}

//---------------------------------------------------------
void * CSG_Parameter_Grid_System::_asPointer(void)	const
{
	return( (void *)&m_System );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_System::_Assign(CSG_Parameter *pSource)
{
	m_System = ((CSG_Parameter_Grid_System *)pSource)->m_System;

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_System::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Add_Child("CELLSIZE", m_System.Get_Cellsize());
		Entry.Add_Child("XMIN"    , m_System.Get_Extent().Get_XMin());
		Entry.Add_Child("YMIN"    , m_System.Get_Extent().Get_YMin());
		Entry.Add_Child("XMAX"    , m_System.Get_Extent().Get_XMax());
		Entry.Add_Child("YMAX"    , m_System.Get_Extent().Get_YMax());
	}
	else
	{
		m_System.Create(
			Entry("CELLSIZE")->Get_Content().asDouble(),
			Entry("XMIN"    )->Get_Content().asDouble(),
			Entry("YMIN"    )->Get_Content().asDouble(),
			Entry("XMAX"    )->Get_Content().asDouble(),
			Entry("YMAX"    )->Get_Content().asDouble()
		);
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                    Table Field                        //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Table_Field::CSG_Parameter_Table_Field(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Int(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Default	= -1;
	m_Value		= -1;
}

//---------------------------------------------------------
bool CSG_Parameter_Table_Field::Add_Default(double Value, double Minimum, bool bMinimum, double Maximum, bool bMaximum)
{
	if( m_Default < 0 && is_Optional() )
	{
		m_Default	= Get_Children_Count();

		Get_Parameters()->Add_Double(Get_Identifier(), CSG_String::Format("%s_DEFAULT", Get_Identifier()),
			_TL("Default"), _TL("default value if no attribute has been selected"),
			Value, Minimum, bMinimum, Maximum, bMaximum
		);
	}

	return( m_Default >= 0 );
}

//---------------------------------------------------------
CSG_Table * CSG_Parameter_Table_Field::Get_Table(void)	const
{
	CSG_Table	*pTable	= Get_Parent() ? Get_Parent()->asTable() : NULL;

	return( pTable && pTable != DATAOBJECT_CREATE && pTable->Get_Field_Count() > 0 ? pTable : NULL );
}

//---------------------------------------------------------
int CSG_Parameter_Table_Field::_Set_Value(int Value)
{
	CSG_Table	*pTable	= Get_Table();

	if( pTable != NULL && pTable->Get_Field_Count() > 0 && Value >= 0 )
	{
		if( Value >= pTable->Get_Field_Count() )
		{
			Value	= !is_Optional() ? pTable->Get_Field_Count() - 1 : -1;
		}
	}
	else
	{
		Value	= -1;
	}

	if( Get_Child(m_Default) )
	{
		Get_Child(m_Default)->Set_Enabled(Value < 0);
	}

	if( m_Value != Value )
	{
		m_Value	= Value;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
int CSG_Parameter_Table_Field::_Set_Value(const CSG_String &Value)
{
	CSG_Table	*pTable	= Get_Table();

	if( pTable != NULL )
	{
		int	Index;

		for(Index=0; Index<pTable->Get_Field_Count(); Index++)
		{
			if( !Value.CmpNoCase(pTable->Get_Field_Name(Index)) )
			{
				return( _Set_Value(Index) );
			}
		}

		if( Value.asInt(Index) )
		{
			return( _Set_Value(Index) );
		}
	}

	return( _Set_Value(-1) );
}

//---------------------------------------------------------
void CSG_Parameter_Table_Field::_Set_String(void)
{
	CSG_Table	*pTable	= Get_Table();

	if( !pTable || pTable->Get_Field_Count() < 1 )
	{
		m_String	= _TL("<no attributes>");
	}
	else if( m_Value < 0 || m_Value >= pTable->Get_Field_Count() )
	{
		m_String	= _TL("<not set>");
	}
	else
	{
		m_String	= pTable->Get_Field_Name(m_Value);
	}
}

//---------------------------------------------------------
double CSG_Parameter_Table_Field::_asDouble(void) const
{
	return( Get_Child(m_Default) ? Get_Child(m_Default)->asDouble() : 0. );
}

//---------------------------------------------------------
bool CSG_Parameter_Table_Field::_Assign(CSG_Parameter *pSource)
{
	m_Value		= ((CSG_Parameter_Table_Field *)pSource)->m_Value;
	m_Default	= ((CSG_Parameter_Table_Field *)pSource)->m_Default;

	_Set_String();

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Table_Field::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Property("index", asInt());
		Entry.Set_Content(asString());

		return( true );
	}
	else
	{
		int	Index;

		if( Entry.Get_Property("index", Index) )	// we require this check for backward compatibility, "index" was first introduced with SAGA 2.2.3 (r2671)
		{
			return( _Set_Value(Index) != 0 );
		}

		return( _Set_Value(Entry.Get_Content()) != 0 );
	}
}

//---------------------------------------------------------
CSG_String CSG_Parameter_Table_Field::Get_Choices(const CSG_Table &Table, bool bAllowNone)
{
	CSG_String Choices;

	for(int i=0; i<Table.Get_Field_Count(); i++)
	{
		if( i > 0 ) { Choices += "|"; }

		Choices += Table.Get_Field_Name(i);
	}

	if( bAllowNone )
	{
		if( Table.Get_Field_Count() ) { Choices += "|"; }

		Choices += _TL("<not set>");
	}

	return( Choices );
}


///////////////////////////////////////////////////////////
//                                                       //
//                     Table Fields                      //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Table_Fields::CSG_Parameter_Table_Fields(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_nFields	= 0;
	m_Fields	= NULL;
}

//---------------------------------------------------------
CSG_Parameter_Table_Fields::~CSG_Parameter_Table_Fields(void)
{
	SG_FREE_SAFE(m_Fields);
}

//---------------------------------------------------------
int CSG_Parameter_Table_Fields::_Set_Value(const CSG_String &Value)
{
	CSG_Table	*pTable	= Get_Table();

	if( !pTable || pTable->Get_Field_Count() <= 0 )
	{
		SG_FREE_SAFE(m_Fields);
		m_nFields	= 0;
		m_String	= _TL("<no attributes>");

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	m_Fields	= (int *)SG_Realloc(m_Fields, pTable->Get_Field_Count() * sizeof(int));

	memset(m_Fields, 0, pTable->Get_Field_Count() * sizeof(int));

	//-----------------------------------------------------
	int		iField;

	CSG_String	List(Value);	List.Replace(";", ",");

	while( List.Length() > 0 )
	{
		CSG_String	sValue	= List.BeforeFirst(',');

		if( sValue.asInt(iField) && iField >= 0 && iField < pTable->Get_Field_Count() )
		{
			m_Fields[iField]	= 1;
		}
		else if( sValue.Length() > 0 )
		{
			sValue.Trim();

			if( sValue[0] == '[' )
			{
				sValue	= sValue.AfterFirst('[').BeforeLast(']');
			}

			for(iField=0; iField<pTable->Get_Field_Count(); iField++)
			{
				if( sValue.CmpNoCase(pTable->Get_Field_Name(iField)) == 0 )
				{
					m_Fields[iField]	= 1;

					break;
				}
			}
		}

		List	= List.AfterFirst(',');
	}

	//-----------------------------------------------------
	m_String.Clear();

	for(iField=0, m_nFields=0; iField<pTable->Get_Field_Count(); iField++)
	{
		if( m_Fields[iField] != 0 )
		{
			m_Fields[m_nFields++]	= iField;

			m_String	+= CSG_String::Format(m_String.is_Empty() ? "%d" : ",%d", iField);
		}
	}

	if( m_nFields <= 0 )
	{
		m_String	= _TL("<no attributes>");
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
int CSG_Parameter_Table_Fields::_asInt(void)	const
{
	return( m_nFields );
}

//---------------------------------------------------------
void * CSG_Parameter_Table_Fields::_asPointer(void)	const
{
	return( m_Fields );
}

//---------------------------------------------------------
CSG_Table * CSG_Parameter_Table_Fields::Get_Table(void)	const
{
	CSG_Table	*pTable	= Get_Parent() ? Get_Parent()->asTable() : NULL;

	return( pTable && pTable != DATAOBJECT_CREATE && pTable->Get_Field_Count() > 0 ? pTable : NULL );
}

//---------------------------------------------------------
bool CSG_Parameter_Table_Fields::_Assign(CSG_Parameter *pSource)
{
	return( _Set_Value(pSource->asString()) != 0 );
}

//---------------------------------------------------------
bool CSG_Parameter_Table_Fields::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		Entry.Set_Content(m_String);
	}
	else
	{
		m_String	= Entry.Get_Content();
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                      DataObject                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Data_Object::CSG_Parameter_Data_Object(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_pDataObject	= NULL;
}

//---------------------------------------------------------
bool CSG_Parameter_Data_Object::is_Valid(void)	const
{
	return(	is_Optional() || (m_pDataObject && m_pDataObject->is_Valid()) );
}

//---------------------------------------------------------
int CSG_Parameter_Data_Object::_Set_Value(void *Value)
{
	if( m_pDataObject != Value )
	{
		m_pDataObject	= (CSG_Data_Object *)Value;

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
void CSG_Parameter_Data_Object::_Set_String(void)
{
	if( m_pDataObject == DATAOBJECT_NOTSET )
	{
		m_String	= is_Output() && !is_Optional() ? _TL("<create>") : _TL("<not set>");
	}
	else if( m_pDataObject == DATAOBJECT_CREATE )
	{
		m_String	= _TL("<create>");
	}
	else
	{
		m_String	= m_pDataObject->Get_Name();
	}
}

//---------------------------------------------------------
void * CSG_Parameter_Data_Object::_asPointer(void)	const
{
	return( m_pDataObject );
}

//---------------------------------------------------------
bool CSG_Parameter_Data_Object::_Assign(CSG_Parameter *pSource)
{
	m_pDataObject	= ((CSG_Parameter_Data_Object *)pSource)->m_pDataObject;

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Data_Object::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		if(	m_pDataObject == DATAOBJECT_CREATE )
		{
			Entry.Set_Content("CREATE");

			return( true );
		}

		if( m_pDataObject == DATAOBJECT_NOTSET )//|| !SG_File_Exists(m_pDataObject->Get_File_Name(false)) )
		{
			Entry.Set_Content("NOT SET");

			return( true );
		}

		if( !m_pDataObject->Get_Owner() )
		{
			Entry.Set_Content(m_pDataObject->Get_File_Name(false));

			return( true );
		}

		if( m_pDataObject->Get_Owner()->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grids )
		{
			CSG_Grids	*pGrids	= m_pDataObject->Get_Owner()->asGrids();

			for(int i=0; i<pGrids->Get_NZ(); i++)
			{
				if( pGrids->Get_Grid_Ptr(i) == m_pDataObject )
				{
					Entry.Set_Content(m_pDataObject->Get_Owner()->Get_File_Name(false));

					Entry.Add_Property("index", i);

					return( true );
				}
			}
		}
	}
	else
	{
		CSG_Data_Object	*pDataObject = NULL; int Index = -1;

		if( Entry.Cmp_Content("CREATE") )
		{
			_Set_Value(DATAOBJECT_CREATE);

			return( true );
		}

		if( Entry.Cmp_Content("NOT SET") || !Get_Manager() || !(pDataObject = Get_Manager()->Find(Entry.Get_Content(), false)) )
		{
			_Set_Value(DATAOBJECT_NOTSET);

			return( true );
		}

		if( !Entry.Get_Property("index", Index) )
		{
			_Set_Value(pDataObject);

			return( true );
		}

		if( pDataObject->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grids )
		{
			_Set_Value(pDataObject->asGrids()->Get_Grid_Ptr(Index));

			return( true );
		}
	}

	return( false );
}


///////////////////////////////////////////////////////////
//                                                       //
//                  DataObject_Output                    //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Data_Object_Output::CSG_Parameter_Data_Object_Output(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Data_Object(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Type	= SG_DATAOBJECT_TYPE_Undefined;
}

//---------------------------------------------------------
int CSG_Parameter_Data_Object_Output::_Set_Value(void *Value)
{
	CSG_Data_Object *pDataObject = (CSG_Data_Object *)Value;

	if( m_pDataObject != pDataObject )
	{
		if( pDataObject == DATAOBJECT_NOTSET || pDataObject == DATAOBJECT_CREATE )
		{
			m_pDataObject = pDataObject;
		}
		else if( pDataObject->Get_ObjectType() == m_Type )
		{
			m_pDataObject = pDataObject;

			if( Get_Manager() )
			{
				Get_Manager()->Add(m_pDataObject);

				if( Get_Manager() == &SG_Get_Data_Manager() )	// prevent that local data manager send their data objects to gui
				{
					SG_UI_DataObject_Add(m_pDataObject, false);
				}
			}
		}

		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
bool CSG_Parameter_Data_Object_Output::Set_DataObject_Type(TSG_Data_Object_Type Type)
{
	if( m_Type == SG_DATAOBJECT_TYPE_Undefined )	// m_Type should not be changed after set once!!!...
	{
		switch( Type )
		{
		case SG_DATAOBJECT_TYPE_Grid      :
		case SG_DATAOBJECT_TYPE_Grids     :
		case SG_DATAOBJECT_TYPE_Table     :
		case SG_DATAOBJECT_TYPE_Shapes    :
		case SG_DATAOBJECT_TYPE_TIN       :
		case SG_DATAOBJECT_TYPE_PointCloud:
			m_Type	= Type;

			return( true );

		default:
			return( false );
		}
	}

	return( false );
}


///////////////////////////////////////////////////////////
//                                                       //
//                         Grid                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Grid::CSG_Parameter_Grid(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Data_Object(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Type = SG_DATATYPE_Undefined; m_Default = -1;
}

//---------------------------------------------------------
void CSG_Parameter_Grid::Set_Preferred_Type(TSG_Data_Type Type)
{
	m_Type = Type;
}

//---------------------------------------------------------
CSG_Grid_System * CSG_Parameter_Grid::Get_System(void)	const
{
	return( Get_Parent() ? Get_Parent()->asGrid_System() : NULL );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid::Add_Default(double Value, double Minimum, bool bMinimum, double Maximum, bool bMaximum)
{
	if( m_Default < 0 && is_Input() && is_Optional() )
	{
		m_Default = Get_Children_Count();

		Get_Parameters()->Add_Double(Get_Identifier(), CSG_String::Format("%s_DEFAULT", Get_Identifier()),
			_TL("Default"), _TL("default value if no grid has been selected"),
			Value, Minimum, bMinimum, Maximum, bMaximum
		);
	}

	return( m_Default >= 0 );
}

//---------------------------------------------------------
int CSG_Parameter_Grid::_Set_Value(void *Value)
{
	if( Value == m_pDataObject ) // nothing to do
	{
		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	//-----------------------------------------------------
	if( Value != DATAOBJECT_NOTSET && Value != DATAOBJECT_CREATE && Get_System() ) // check grid system compatibility
	{
		CSG_Grid_System System = Get_Type() == PARAMETER_TYPE_Grid
			? ((CSG_Grid  *)Value)->Get_System()
			: ((CSG_Grids *)Value)->Get_System();

		if( System.is_Valid() == false )
		{
			if( is_Input() )
			{
				return( SG_PARAMETER_DATA_SET_FALSE );
			}
		}
		else if( !Get_System()->is_Equal(System) )
		{
			if( Get_System()->is_Valid() )
			{
				for(int i=0; i<Get_Parent()->Get_Children_Count(); i++)
				{
					CSG_Parameter *pChild = Get_Parent()->Get_Child(i);

					if( pChild->is_Output() && !Get_Parameters()->has_GUI() )
					{
						continue;
					}

					if( pChild->Get_Type() == PARAMETER_TYPE_Grid
					||  pChild->Get_Type() == PARAMETER_TYPE_Grids )
					{
						if( pChild->asDataObject() != DATAOBJECT_NOTSET
						&&  pChild->asDataObject() != DATAOBJECT_CREATE
						&&  pChild->asDataObject() != m_pDataObject
						&&  pChild->asDataObject() != Value )
						{
							return( SG_PARAMETER_DATA_SET_FALSE );
						}
					}

					if( pChild->is_DataObject_List() && pChild->asList()->Get_Item_Count() > 0 )
					{
						if( (pChild->Get_Type() == PARAMETER_TYPE_Grid_List  && pChild->asGridList ()->Get_System())
						||  (pChild->Get_Type() == PARAMETER_TYPE_Grids_List && pChild->asGridsList()->Get_System()) )
						{
							return( SG_PARAMETER_DATA_SET_FALSE );
						}
					}
				}
			}

			Get_Parent()->Set_Value((void *)&System);
		}
	}

	//-----------------------------------------------------
	m_pDataObject = (CSG_Data_Object *)Value;

	if( Get_Child(m_Default) )
	{
		Get_Child(m_Default)->Set_Enabled(m_pDataObject == DATAOBJECT_NOTSET);
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
int	CSG_Parameter_Grid::_asInt(void) const
{
	return( Get_Child(m_Default) ? Get_Child(m_Default)->asInt   () :  0 );
}

//---------------------------------------------------------
double CSG_Parameter_Grid::_asDouble(void) const
{
	return( Get_Child(m_Default) ? Get_Child(m_Default)->asDouble() : 0. );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid::_Assign(CSG_Parameter *pSource)
{
	m_Type    = ((CSG_Parameter_Grid *)pSource)->m_Type;
	m_Default = ((CSG_Parameter_Grid *)pSource)->m_Default;

	return( _Set_Value(pSource->asPointer()) != 0 );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Grids                           //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Grids::CSG_Parameter_Grids(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Grid(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Table                           //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Table::CSG_Parameter_Table(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Data_Object(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_Table::_Set_Value(void *Value)
{
	if( m_pDataObject == Value )
	{
		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	m_pDataObject = (CSG_Data_Object *)Value;

	for(int i=0; i<Get_Children_Count(); i++)
	{
		CSG_Parameter *pChild = Get_Child(i);

		if( pChild->Get_Type() == PARAMETER_TYPE_Table_Field )
		{
			pChild->Set_Value(m_pDataObject && pChild->is_Optional() ? ((CSG_Table *)m_pDataObject)->Get_Field_Count() : 0);
		}
		else if( pChild->Get_Type() == PARAMETER_TYPE_Table_Fields )
		{
			pChild->Set_Value(CSG_String(""));
		}
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}


///////////////////////////////////////////////////////////
//                                                       //
//                        Shapes                         //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Shapes::CSG_Parameter_Shapes(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Data_Object(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Type = SHAPE_TYPE_Undefined;
}

//---------------------------------------------------------
int CSG_Parameter_Shapes::_Set_Value(void *Value)
{
	if( (is_Input() || Get_Parameters()->has_GUI()) && Value != DATAOBJECT_NOTSET && Value != DATAOBJECT_CREATE
	&&	m_Type != SHAPE_TYPE_Undefined && m_Type != ((CSG_Shapes *)Value)->Get_Type() )
	{
		return( SG_PARAMETER_DATA_SET_FALSE );
	}

	if( m_pDataObject == Value )
	{
		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	m_pDataObject = (CSG_Data_Object *)Value;

	for(int i=0; i<Get_Children_Count(); i++)
	{
		CSG_Parameter *pChild = Get_Child(i);

		if(	pChild->Get_Type() == PARAMETER_TYPE_Table_Field )
		{
			pChild->Set_Value(m_pDataObject && m_pDataObject != DATAOBJECT_CREATE && pChild->is_Optional() ? ((CSG_Table *)m_pDataObject)->Get_Field_Count() : 0);
		}
		else if( pChild->Get_Type() == PARAMETER_TYPE_Table_Fields )
		{
			pChild->Set_Value("");
		}
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
void CSG_Parameter_Shapes::Set_Shape_Type(TSG_Shape_Type Type)
{
	m_Type = Type;
}

//---------------------------------------------------------
bool CSG_Parameter_Shapes::_Assign(CSG_Parameter *pSource)
{
	m_Type = ((CSG_Parameter_Shapes *)pSource)->m_Type;

	return( CSG_Parameter_Data_Object::_Assign(pSource) );
}


///////////////////////////////////////////////////////////
//                                                       //
//                          TIN                          //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_TIN::CSG_Parameter_TIN(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Data_Object(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_TIN::_Set_Value(void *Value)
{
	if( m_pDataObject == Value )
	{
		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	m_pDataObject = (CSG_Data_Object *)Value;

	for(int i=0; i<Get_Children_Count(); i++)
	{
		CSG_Parameter *pChild = Get_Child(i);

		if( pChild->Get_Type() == PARAMETER_TYPE_Table_Field )
		{
			pChild->Set_Value(m_pDataObject && pChild->is_Optional() ? ((CSG_Table *)m_pDataObject)->Get_Field_Count() : 0);
		}
		else if( pChild->Get_Type() == PARAMETER_TYPE_Table_Fields )
		{
			pChild->Set_Value("");
		}
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}


///////////////////////////////////////////////////////////
//                                                       //
//                      PointCloud                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_PointCloud::CSG_Parameter_PointCloud(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_Data_Object(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
int CSG_Parameter_PointCloud::_Set_Value(void *Value)
{
	if( m_pDataObject == Value )
	{
		return( SG_PARAMETER_DATA_SET_TRUE );
	}

	m_pDataObject = (CSG_Data_Object *)Value;

	for(int i=0; i<Get_Children_Count(); i++)
	{
		CSG_Parameter *pChild = Get_Child(i);

		if( pChild->Get_Type() == PARAMETER_TYPE_Table_Field )
		{
			pChild->Set_Value(m_pDataObject && pChild->is_Optional() ? ((CSG_Table *)m_pDataObject)->Get_Field_Count() : 0);
		}
		else if( pChild->Get_Type() == PARAMETER_TYPE_Table_Fields )
		{
			pChild->Set_Value("");
		}
	}

	return( SG_PARAMETER_DATA_SET_CHANGED );
}

//---------------------------------------------------------
bool CSG_Parameter_PointCloud::_Assign(CSG_Parameter *pSource)
{
	return( CSG_Parameter_Data_Object::_Assign(pSource) );
}


///////////////////////////////////////////////////////////
//                                                       //
//                        List                           //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_List::CSG_Parameter_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
bool CSG_Parameter_List::Add_Item(CSG_Data_Object *pObject)
{
	if( pObject != DATAOBJECT_NOTSET && pObject != DATAOBJECT_CREATE && m_Objects.Add(pObject) )
	{
		_Set_String();

		return( true );
	}

	return( false );
}

bool CSG_Parameter_List::Del_Item(CSG_Data_Object *pObject, bool bUpdateData)
{
	if( m_Objects.Del(pObject) > 0 )
	{
		if( bUpdateData )
		{
			_Set_String();
		}

		return( true );
	}

	return( false );
}

bool CSG_Parameter_List::Del_Item(int Index, bool bUpdateData)
{
	if( m_Objects.Del(Index) )
	{
		if( bUpdateData )
		{
			_Set_String();
		}

		return( true );
	}

	return( false );
}

bool CSG_Parameter_List::Del_Items(void)
{
	if( m_Objects.Set_Array(0) )
	{
		_Set_String();

		return( true );
	}

	return( false );
}

//---------------------------------------------------------
int CSG_Parameter_List::_Set_Value(void *Value)
{
	if( Value == NULL && Get_Item_Count() > 0 && Del_Items() )
	{
		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	if( Value != NULL && Add_Item((CSG_Data_Object *)Value) )
	{
		return( SG_PARAMETER_DATA_SET_CHANGED );
	}

	return( SG_PARAMETER_DATA_SET_TRUE );
}

//---------------------------------------------------------
void CSG_Parameter_List::_Set_String(void)
{
	if( Get_Item_Count() > 0 )
	{
		m_String.Printf("%d %s (", Get_Item_Count(), Get_Item_Count() == 1 ? _TL("object") : _TL("objects"));

		for(int i=0; i<Get_Item_Count(); i++)
		{
			if( i > 0 )
			{
				m_String	+= ", ";
			}

			m_String	+= Get_Item(i)->Get_Name();
		}

		m_String	+= ")";
	}
	else
	{
		m_String	= _TL("No objects");
	}
}

//---------------------------------------------------------
int CSG_Parameter_List::_asInt(void)	const
{
	return( Get_Item_Count() );
}

//---------------------------------------------------------
void * CSG_Parameter_List::_asPointer(void)	const
{
	return( m_Objects.Get_Array() );
}

//---------------------------------------------------------
bool CSG_Parameter_List::_Assign(CSG_Parameter *pSource)
{
	Del_Items();

	for(int i=0; i<((CSG_Parameter_List *)pSource)->Get_Item_Count(); i++)
	{
		if( Get_Manager() != &SG_Get_Data_Manager() || SG_Get_Data_Manager().Exists(((CSG_Parameter_List *)pSource)->Get_Item(i)) )
		{
			Add_Item(((CSG_Parameter_List *)pSource)->Get_Item(i));
		}
	}

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_List::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( bSave )
	{
		for(int i=0; i<Get_Item_Count(); i++)
		{
			CSG_String	File	= Get_Item(i)->Get_File_Name(false);

			if( File.BeforeFirst(':').Cmp("PGSQL") || SG_File_Exists(File) )
			{
				Entry.Add_Child("DATA", File);
			}
		}
	}
	else
	{
		Del_Items();

		for(int i=0; i<Entry.Get_Children_Count(); i++)
		{
			CSG_Data_Object	*pObject	= Get_Manager() ? Get_Manager()->Find(Entry.Get_Content(i), false) : NULL;

			if( pObject )
			{
				Add_Item(pObject);
			}
		}
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                       Grid_List                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Grid_List::CSG_Parameter_Grid_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_List(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
CSG_Grid_System * CSG_Parameter_Grid_List::Get_System(void) const
{
	if( Get_Parent() && Get_Parent()->Get_Type() == PARAMETER_TYPE_Grid_System )
	{
		return( Get_Parent()->asGrid_System() );
	}

	return( NULL );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_List::Add_Item(CSG_Data_Object *pObject)
{
	if( pObject == DATAOBJECT_NOTSET || pObject == DATAOBJECT_CREATE
	|| (pObject->Get_ObjectType() != SG_DATAOBJECT_TYPE_Grid
	&&  pObject->Get_ObjectType() != SG_DATAOBJECT_TYPE_Grids)  )
	{
		return( false );
	}

	//-----------------------------------------------------
	if( Get_System() ) // check grid system compatibility
	{
		CSG_Grid_System System = pObject->Get_ObjectType() == SG_DATAOBJECT_TYPE_Grid
			? ((CSG_Grid  *)pObject)->Get_System()
			: ((CSG_Grids *)pObject)->Get_System();

		if( System.is_Valid() == false && is_Input() )
		{
			return( false );
		}

		if( !Get_System()->is_Valid() )
		{
			Get_Parent()->Set_Value((void *)&System);
		}
		else if( !Get_System()->is_Equal(System) )
		{
			for(int i=0; i<Get_Parent()->Get_Children_Count(); i++)
			{
				CSG_Parameter *pChild = Get_Parent()->Get_Child(i);

				if( pChild->Get_Type() == PARAMETER_TYPE_Grid
				||  pChild->Get_Type() == PARAMETER_TYPE_Grids )
				{
					if( pChild->asDataObject() != DATAOBJECT_NOTSET
					&&  pChild->asDataObject() != DATAOBJECT_CREATE )
					{
						return( false );
					}
				}

				if( pChild->is_DataObject_List() && pChild->asList()->Get_Item_Count() > 0 )
				{
					if( (pChild->Get_Type() == PARAMETER_TYPE_Grid_List  && pChild->asGridList ()->Get_System())
					||  (pChild->Get_Type() == PARAMETER_TYPE_Grids_List && pChild->asGridsList()->Get_System()) )
					{
						return( false );
					}
				}
			}

			Get_Parent()->Set_Value((void *)&System);
		}
	}

	return( CSG_Parameter_List::Add_Item(pObject) && Update_Data() );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_List::Del_Item(CSG_Data_Object *pItem, bool bUpdateData)
{
	return( CSG_Parameter_List::Del_Item(pItem, bUpdateData) );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_List::Del_Item(int Index, bool bUpdateData)
{
	return( CSG_Parameter_List::Del_Item(Index, bUpdateData) );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_List::Del_Items(void)
{
	return( CSG_Parameter_List::Del_Items() && Update_Data() );
}

//---------------------------------------------------------
bool CSG_Parameter_Grid_List::Update_Data(void)
{
	m_Grids.Set_Array(0);

	for(int i=0; i<Get_Item_Count(); i++)
	{
		switch( Get_Item(i)->Get_ObjectType() )
		{
		case SG_DATAOBJECT_TYPE_Grid: {
			m_Grids.Add(Get_Item(i));
			break; }

		case SG_DATAOBJECT_TYPE_Grids: {
			CSG_Grids *pGrids = (CSG_Grids *)Get_Item(i);

			for(int j=0; j<pGrids->Get_Grid_Count(); j++)
			{
				m_Grids.Add(pGrids->Get_Grid_Ptr(j));
			}
			break; }

		default: {
			break; }
		}
	}

	if( !m_Grids.Get_Size() && !Get_Parameters()->has_GUI() )
	{
		if( Get_Parent() && Get_Parent()->Get_Type() == PARAMETER_TYPE_Grid_System && Get_Parent()->Get_Children_Count() == 1 )
		{
			Get_Parent()->asGrid_System()->Destroy();
		}
	}

	return( true );
}


///////////////////////////////////////////////////////////
//                                                       //
//                     Grids_List                        //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Grids_List::CSG_Parameter_Grids_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_List(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}

//---------------------------------------------------------
CSG_Grid_System * CSG_Parameter_Grids_List::Get_System(void) const
{
	if( Get_Parent() && Get_Parent()->Get_Type() == PARAMETER_TYPE_Grid_System )
	{
		return( Get_Parent()->asGrid_System() );
	}

	return( NULL );
}

//---------------------------------------------------------
bool CSG_Parameter_Grids_List::Add_Item(CSG_Data_Object *pObject)
{
	if( pObject == NULL || pObject->Get_ObjectType() != SG_DATAOBJECT_TYPE_Grids )
	{
		return( false );
	}

	//-----------------------------------------------------
	CSG_Grid_System *pSystem = Get_System();

	if( pSystem )	// check grid system compatibility
	{
		CSG_Grid_System	System	= Get_Type() == PARAMETER_TYPE_Grid_List
			? ((CSG_Grid  *)pObject)->Get_System()
			: ((CSG_Grids *)pObject)->Get_System();

		if( !pSystem->is_Valid() )
		{
			Get_Parent()->Set_Value((void *)&System);
		}
		else if( !pSystem->is_Equal(System) )
		{
			for(int i=0; i<Get_Parent()->Get_Children_Count(); i++)
			{
				CSG_Parameter	*pChild	= Get_Parent()->Get_Child(i);

				if( pChild->Get_Type() == PARAMETER_TYPE_Grids )
				{
					if( pChild->asDataObject() != DATAOBJECT_NOTSET
					&&  pChild->asDataObject() != DATAOBJECT_CREATE )
					{
						return( false );
					}
				}

				if( pChild->is_DataObject_List() && pChild->asList()->Get_Item_Count() > 0 )
				{
					if( (pChild->Get_Type() == PARAMETER_TYPE_Grids_List && pChild->asGridsList()->Get_System()) )
					{
						return( false );
					}
				}
			}

			Get_Parent()->Set_Value((void *)&System);
		}
	}

	return( CSG_Parameter_List::Add_Item(pObject) );
}


///////////////////////////////////////////////////////////
//                                                       //
//                      Table_List                       //
//                                                       //
///////////////////////////////////////////////////////////


//---------------------------------------------------------
CSG_Parameter_Table_List::CSG_Parameter_Table_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_List(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}


///////////////////////////////////////////////////////////
//                                                       //
//                      Shapes_List                      //
//                                                       //
///////////////////////////////////////////////////////////


//---------------------------------------------------------
CSG_Parameter_Shapes_List::CSG_Parameter_Shapes_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_List(pOwner, pParent, ID, Name, Description, Constraint)
{
	m_Type	= SHAPE_TYPE_Undefined;
}

//---------------------------------------------------------
void CSG_Parameter_Shapes_List::Set_Shape_Type(TSG_Shape_Type Type)
{
	m_Type	= Type;
}

//---------------------------------------------------------
bool CSG_Parameter_Shapes_List::_Assign(CSG_Parameter *pSource)
{
	m_Type	= ((CSG_Parameter_Shapes_List *)pSource)->m_Type;

	return( CSG_Parameter_List::_Assign(pSource) );
}


///////////////////////////////////////////////////////////
//                                                       //
//                      TIN_List                         //
//                                                       //
///////////////////////////////////////////////////////////


//---------------------------------------------------------
CSG_Parameter_TIN_List::CSG_Parameter_TIN_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_List(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}


///////////////////////////////////////////////////////////
//                                                       //
//                    PointCloud_List                    //
//                                                       //
///////////////////////////////////////////////////////////


//---------------------------------------------------------
CSG_Parameter_PointCloud_List::CSG_Parameter_PointCloud_List(CSG_Parameters *pOwner, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter_List(pOwner, pParent, ID, Name, Description, Constraint)
{
	// nop
}


///////////////////////////////////////////////////////////
//                                                       //
//                     Parameters                        //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
CSG_Parameter_Parameters::CSG_Parameter_Parameters(CSG_Parameters *pParameters, CSG_Parameter *pParent, const CSG_String &ID, const CSG_String &Name, const CSG_String &Description, int Constraint)
	: CSG_Parameter(pParameters, pParent, ID, Name, Description, Constraint)
{
	m_pParameters	= new CSG_Parameters(pParameters->Get_Owner(), Name, Description, ID);
}

CSG_Parameter_Parameters::~CSG_Parameter_Parameters(void)
{
	delete(m_pParameters);
}

//---------------------------------------------------------
bool CSG_Parameter_Parameters::Restore_Default(void)
{
	return( m_pParameters->Restore_Defaults() );
}

//---------------------------------------------------------
void CSG_Parameter_Parameters::_Set_String(void)
{
	m_String.Printf("%d %s", m_pParameters->Get_Count(), _TL("parameters"));
}

//---------------------------------------------------------
void * CSG_Parameter_Parameters::_asPointer(void)	const
{
	return( m_pParameters );
}

//---------------------------------------------------------
bool CSG_Parameter_Parameters::_Assign(CSG_Parameter *pSource)
{
	m_pParameters->Assign(pSource->asParameters());

	return( true );
}

//---------------------------------------------------------
bool CSG_Parameter_Parameters::_Serialize(CSG_MetaData &Entry, bool bSave)
{
	if( m_pParameters->Serialize(Entry, bSave) )
	{
		if( bSave )
		{
			Entry.Set_Property("id"  , Get_Identifier     ());
			Entry.Set_Property("type", Get_Type_Identifier());
		}

		return( true );
	}

	return( false );
}


///////////////////////////////////////////////////////////
//                                                       //
//                                                       //
//                                                       //
///////////////////////////////////////////////////////////

//---------------------------------------------------------
