/*--------------------------------------------------------------------------*
 * File Name:	matrixObj.cpp												*
 * Purpose:		Demonstrate how to access an Origin matrix					*
 * Creation:	March 24, 2000												*
 * Copyright Microcal Software Inc. 2000									*
 *																			*
 * Modification Log:														*
 *	CPY v6.0297 t8155 7/5/00 FASTER_DATASET_ACCESS_FROM_MOCA				*
 *--------------------------------------------------------------------------*/      


#include "matrixObj.h"

//---------------------------------------------------------------------------
// MOCA_ENTRY_POINT( <main object class> )
//
// The MOCA_ENTRY_POINT macro is used to define the exported function that
// Origin will use to communicate with your DLL.  The macro takes a single
// argument, the class name of your main object.
//---------------------------------------------------------------------------
MOCA_ENTRY_POINT(CMatrixDemo)


//---------------------------------------------------------------------------
// Property Map:
//
// The Property Map is for declaring the properties of your LabTalk object.
//
// A property is mapped to Get and Set function.  These functions allow
// you to do error checking or any necessary conversions.  A read-only
// property can be declared by using the _GET macro.
//
// MOCA_PROP_INT( <GetFunction>,<SetFunction>,<PropertyNameStr> )
// MOCA_PROP_REAL( <GetFunction>,<SetFunction>,<PropertyNameStr> )
// MOCA_PROP_STR( <GetFunction>,<SetFunction>,<PropertyNameStr> )
// MOCA_PROP_INT_GET( <GetFunction>,<PropertyNameStr> )
// MOCA_PROP_REAL_GET( <GetFunction>,<PropertyNameStr> )
// MOCA_PROP_STR_GET( <GetFunction>,<PropertyNameStr> )
//
// A Simple Property is mapped to a data member.  There are no Get/Set
// functions for a Simple Property.  MOCA will take care of the assignment.
// A simple read-only property can be declared by using the _GET macro.
//
// MOCA_SIMPLE_PROP_INT( <DataMember>,<PropertyNameStr> )
// MOCA_SIMPLE_PROP_REAL( <DataMember>,<PropertyNameStr> )
// MOCA_SIMPLE_PROP_STR( <DataMember>,<PropertyNameStr> )
// MOCA_SIMPLE_PROP_INT_GET( <DataMember>,<PropertyNameStr> )
// MOCA_SIMPLE_PROP_REAL_GET( <DataMember>,<PropertyNameStr> )
// MOCA_SIMPLE_PROP_STR_GET( <DataMember>,<PropertyNameStr> )
//---------------------------------------------------------------------------
MOCA_BEGIN_PROP_MAP(CMatrixDemo, CMOCAObjBase)
	MOCA_SIMPLE_PROP_STR(m_MatrixName, "MatrixName")
	MOCA_PROP_INT(GetDataType, SetDataType, "DataType")
	MOCA_PROP_INT_GET(GetNumColumns, "NumColumns")
	MOCA_PROP_INT_GET(GetNumRows, "NumRows")
	MOCA_PROP_REAL_GET(GetXMin, "XMin")
	MOCA_PROP_REAL_GET(GetXMax, "XMax")
	MOCA_PROP_REAL_GET(GetYMin, "YMin")
	MOCA_PROP_REAL_GET(GetYMax, "YMax")
MOCA_END_PROP_MAP(CMatrixDemo, CMOCAObjBase)


//---------------------------------------------------------------------------
// Method Map:
//
// INPORTANT: To have a Method Map or a SubObject Map, you must
// have a property map.  A property map can be empty.
//
// MOCA_METH_ENTRY( <MemberFunction>,<MethodNameStr> )
//
// <MemberFunction> must be declared as "BOOL foo(double &, CStringArray &);"
// The double is used for storing LabTalk's return value.
// The CStringArray contains the arguments passed from LabTalk.
//---------------------------------------------------------------------------
MOCA_BEGIN_METH_MAP(CMatrixDemo, CMOCAObjBase)
	MOCA_METH_ENTRY(MethodGetValue, "GetValue")	
	MOCA_METH_ENTRY(MethodSetValue, "SetValue")	
	MOCA_METH_ENTRY(MethodGetRows, "GetRows")	
	MOCA_METH_ENTRY(MethodGetColumns, "GetColumns")	
	MOCA_METH_ENTRY(MethodSetDims, "SetDims")	
	MOCA_METH_ENTRY(MethodSetXY, "SetXY")
	MOCA_METH_ENTRY(MethodFillValues, "Fill")
MOCA_END_METH_MAP(CMatrixDemo, CMOCAObjBase)


//---------------------------------------------------------------------------
// SubObject Map:
//
// IMPORTANT: To have a Method Map or a SubObject Map, you must
// have a property map.  A property map can be empty.
//
// MOCA_SUBOBJ_ENTRY( <m_SubObject>,<SubObjectNameStr> )
//
//---------------------------------------------------------------------------
// This MOCA example has no subobjects.
// The following is an example of how a SubObject table is declared.
//MOCA_BEGIN_SUBOBJ_MAP(CLASSNAME, BASECLASSNAME)
//	MOCA_SUBOBJ_ENTRY(m_SubObject, "SUBOBJECT")
// 	MOCA_SUBOBJ_ENTRY(m_SubObject2, "SUBOBJECT2")
//MOCA_END_SUBOBJ_MAP(CLASSNAME, BASECLASSNAME)


//---------------------------------------------------------------------------
// CMatrixDemo constructors and deconstructors
//---------------------------------------------------------------------------
CMatrixDemo::CMatrixDemo()
{
	m_MatrixName = "Matrix1";
}

CMatrixDemo::~CMatrixDemo()
{
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetDataType
//
// LabTalk Property: DATATYPE
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetDataType(int &iValue)
{
	iValue = -1; // -1 indicates invalid data type

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	// A MoMatrix object should be created on stack and should not be kept
	// around between calls, since the matrix may change by the time a
	// second call is made.
	MoMatrix myMatrix(m_MatrixName);		

	// Check if this object is associated with a valid matrix in Origin.
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	// Get the matrix's data type
	iValue = myMatrix.GetInternalDataType();

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::SetDataType
//
// LabTalk Property: DATATYPE
//---------------------------------------------------------------------------
BOOL CMatrixDemo::SetDataType(int iValue)
{
	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	// Set the matrix's data type
	if( myMatrix.SetInternalDataType(iValue) == -1 )
		return FALSE; // LabTalk command error

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetNumColumns
//
// LabTalk Property: NUMCOLUMNS
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetNumColumns(int &iValue)
{
	iValue = 0;

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	// Get the number of columns
	iValue = myMatrix.nCols();   
	
	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetNumRows
//
// LabTalk Property: NUMROWS
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetNumRows(int &iValue)
{
	iValue = 0;

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	// Get the number of columns
	iValue = myMatrix.nRows();   
	
	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetXMin
//
// LabTalk Property: XMIN
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetXMin(double &dValue)
{
	dValue = NANUM;

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	double dXYMaxMin[4];
	myMatrix.GetMatrixXY(dXYMaxMin);
	dValue = dXYMaxMin[0]; // XMin is the first element

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetXMax
//
// LabTalk Property: XMAX
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetXMax(double &dValue)
{
	dValue = NANUM;

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	double dXYMaxMin[4];
	myMatrix.GetMatrixXY(dXYMaxMin);
	dValue = dXYMaxMin[2]; // XMax is the third element

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetYMin
//
// LabTalk Property: YMIN
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetYMin(double &dValue)
{
	dValue = NANUM;

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	double dXYMaxMin[4];
	myMatrix.GetMatrixXY(dXYMaxMin);
	dValue = dXYMaxMin[1]; // YMin is the second element

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::GetYMax
//
// LabTalk Property: YMAX
//---------------------------------------------------------------------------
BOOL CMatrixDemo::GetYMax(double &dValue)
{
	dValue = NANUM;

	// Create a MoMatrix object for the matrix specified in m_MatrixName.
	MoMatrix myMatrix(m_MatrixName);
	if( !myMatrix.IsValid() )
		return FALSE; // LabTalk command error

	double dXYMaxMin[4];
	myMatrix.GetMatrixXY(dXYMaxMin);
	dValue = dXYMaxMin[3]; // YMax is the fourth element

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::MethodGetValue
//
//---------------------------------------------------------------------------
BOOL CMatrixDemo::MethodGetValue(double &dReturn, CStringArray &argarray)
{
	dReturn = NANUM;

	// Method requires 3 arguments: matrix name, row index, and column index
	if( argarray.GetSize() != 3 )
		return FALSE; // LabTalk command error

	// Get and check matrix name
	CString strMatrixName = argarray[0];
	if( strMatrixName.IsEmpty() )
		strMatrixName = m_MatrixName;

	// Create a reference to a matrix by name
	MoMatrix myMatrix(strMatrixName);
	if( !myMatrix.IsValid() )
	{
		MessageBox(NULL, "GetValue method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}

	// Get and check the row and column index
	int iRowIndex = LabTalkStr2int(argarray[1]); 
	int iColumnIndex = LabTalkStr2int(argarray[2]); 
	if( iRowIndex <= 0 || iColumnIndex <= 0 )
		return FALSE; // LabTalk command error

	// Return the cell's value to LabTalk
	dReturn = myMatrix(iRowIndex - 1, iColumnIndex - 1);

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::MethodSetValue
//
//---------------------------------------------------------------------------
BOOL CMatrixDemo::MethodSetValue(double &dReturn, CStringArray &argarray)
{
	dReturn = NANUM;

	// Method requires 4 arguments: matrix name, row index, column index, value
	if( argarray.GetSize() != 4 )
		return FALSE; // LabTalk command error

	// Get and check matrix name
	CString strMatrixName = argarray[0];
	if( strMatrixName.IsEmpty() )
		strMatrixName = m_MatrixName;

	// Create a reference to a matrix by name
	MoMatrix myMatrix(strMatrixName);
	if( !myMatrix.IsValid() )
	{
		MessageBox(NULL, "SetValue method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}

	// Get and check the row and column index
	int iRowIndex = atoi(argarray[1]); 
	int iColumnIndex = atoi(argarray[2]); 
	if( iRowIndex <= 0 || iColumnIndex <= 0 )
		return FALSE; // LabTalk command error

	// Get the value and set the matrix cell
	double dValue = atof(argarray[3]); 
	myMatrix.SetVal(iRowIndex - 1, iColumnIndex - 1, dValue);
	
	dReturn = 0;

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::MethodGetRows
//
//---------------------------------------------------------------------------
BOOL CMatrixDemo::MethodGetRows(double &dReturn, CStringArray &argarray)
{
	dReturn = NANUM;

	// Method requires 1 arguments: matrix name
	if( argarray.GetSize() != 1 )
		return FALSE; // LabTalk command error

	// Get and check matrix name
	CString strMatrixName = argarray[0];
	if( strMatrixName.IsEmpty() )
		strMatrixName = m_MatrixName;

	// Create a reference to a matrix by name
	MoMatrix myMatrix(strMatrixName);
	if( !myMatrix.IsValid() )
	{
		MessageBox(NULL, "GetRows method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}

	// Return the number of rows to LabTalk
	dReturn = myMatrix.nRows();

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
// CMatrixDemo::MethodGetColumns
//
//---------------------------------------------------------------------------
BOOL CMatrixDemo::MethodGetColumns(double &dReturn, CStringArray &argarray)
{
	dReturn = NANUM;

	// Method requires 1 arguments: matrix name
	if( argarray.GetSize() != 1 )
		return FALSE; // LabTalk command error

	// Get and check matrix name
	CString strMatrixName = argarray[0];
	if( strMatrixName.IsEmpty() )
		strMatrixName = m_MatrixName;

	// Create a reference to a matrix by name
	MoMatrix myMatrix(strMatrixName);
	if( !myMatrix.IsValid() )
	{
		MessageBox(NULL, "GetColumns method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}

	// Return the number of columns to LabTalk
	dReturn = myMatrix.nCols();

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
//CMatrixDemo::MethodSetDims
//
//---------------------------------------------------------------------------
BOOL CMatrixDemo::MethodSetDims(double &dReturn, CStringArray &argarray)
{
	dReturn = NANUM;

	// Method requires 3 arguments: matrix name, x dim, y dim
	if( argarray.GetSize() != 3 )
		return FALSE; // LabTalk command error

	// Get and check matrix name
	CString strMatrixName = argarray[0];
	if( strMatrixName.IsEmpty() )
		strMatrixName = m_MatrixName;

	// Create a reference to a matrix by name
	MoMatrix myMatrix(strMatrixName);
	if( !myMatrix.IsValid() )
	{
		MessageBox(NULL, "SetDims method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}

	// Get and check the X and Y dimensions
	int iXDim = atoi(argarray[1]); 
	int iYDim = atoi(argarray[2]); 
	if( iXDim <= 0 || iYDim <= 0 )
		return FALSE; // LabTalk command error

	// Set the dimensions of the matrix to (x dim * y dim)
	myMatrix.SetDim(iXDim, iYDim);
	
	dReturn = 0;

	return TRUE; // LabTalk command succeeded
}

//---------------------------------------------------------------------------
//CMatrixDemo::MethodSetXY
//
//---------------------------------------------------------------------------
BOOL CMatrixDemo::MethodSetXY(double &dReturn, CStringArray &argarray)
{
	dReturn = NANUM;

	// Method requires 5 arguments: matrix name, x min, y min, x max, y max
	if( argarray.GetSize() != 5 )
		return FALSE; // LabTalk command error

	// Get and check matrix name
	CString strMatrixName = argarray[0];
	if( strMatrixName.IsEmpty() )
		strMatrixName = m_MatrixName;

	// Create a reference to a matrix by name
	MoMatrix myMatrix(strMatrixName);
	if( !myMatrix.IsValid() )
	{
		MessageBox(NULL, "SetXY method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}

	// Get and check the X and Y range values
	double dXY[4];
	for( int i = 1; i <= 4; i++ )
	{
		dXY[i - 1] = atof(argarray[i]);
		if( dXY[i - 1] < 0 )
			return FALSE; // LabTalk command error
	}

	// Set the X and Y range for plotting
	myMatrix.SetXY(dXY);
	
	dReturn = 0;

	return TRUE; // LabTalk command succeeded
}

// test setting matrix values using direct assignment
// ma.fill(); init to some values and set datatype to short
BOOL CMatrixDemo::MethodFillValues(double &dReturn, CStringArray &argarray)
{
	MoMatrix mm(m_MatrixName);
	if( !mm.IsValid() )
	{
		MessageBox(NULL, "MethodFillValues method received invalid matrix", "MOCA Matrix Example", MB_OK);
		return FALSE; // LabTalk command error
	}
	OCELL_VALUE	cell;

	if(argarray.GetSize() == 0) // no arguemnt, init matrix
	{
		mm.SetInternalDataType(2); // set to short int
		cell.wFlags = OCV_SET | OCV_NO_CHK_BOUND;
		for(UINT ii = 0; ii < mm.nCols(); ii++)
			for(UINT jj = 0; jj < mm.nRows(); jj++)
			{
				cell.sValue = jj+3*ii;
				//mm.SetVal(jj, ii, value);
				cell.index = mm.GetInternalIndex(jj, ii);
				mm.DirectValue(&cell);
			}
	}
	else   // just need one argument, a number to add to each cell
	{
		int AddAmount = atoi(argarray[0]); 
		for(UINT ii = 0; ii < mm.nCols(); ii++)
			for(UINT jj = 0; jj < mm.nRows(); jj++)
			{
				cell.index = mm.GetInternalIndex(jj, ii);
				cell.wFlags = OCV_NO_CHK_BOUND;
				mm.DirectValue(&cell);
				cell.sValue += AddAmount;
				cell.wFlags = OCV_SET | OCV_NO_CHK_BOUND;
				mm.DirectValue(&cell);
			}
	}
	dReturn = 0;
	return TRUE;
}
