/*------------------------------------------------------------------------------*
 * File Name: TreeEx.C		 													*
 * Creation: GJL 8/3/03															*
 * Purpose: OriginC Source C file containing Tree examples.						*
 * Copyright (c) OriginLab Corp.	2003, 2004, 2005, 2006, 2007, 2008		 	*
 * All Rights Reserved															*
 *------------------------------------------------------------------------------*/
 
#include <Origin.h>

#include <tree_utils.h>

// Demonstrate the different values of a TreeNode 
void ValuesOfATreeNodeEx()
{
	Tree tr;

	// Set common node properties
	tr.mynode.ID = 200; 
	tr.mynode.Show = 1;
	tr.mynode.Enable = 1;
	string strLabel; // tagName is read only
	strLabel.Format("\ntree_dump of Tree having TreeNode named %s", tr.mynode.tagName);

	// Set node properties
	tr.mynode.nVal = 6;	
	out_tree(tr);
	
	tr.mynode.dVal = 3.5;	
	out_tree(tr);
	
	tr.mynode.strVal = "This is a string value";	
	out_tree(tr);
	
	tr.mynode.Text = "-8.9";	
	out_tree(tr);

	// Get and print all node properties
	int iID = tr.mynode.ID; 
	int iShow = tr.mynode.Show;
	int iEnable = tr.mynode.Enable;
	int nVal = tr.mynode.nVal;
	double dVal = tr.mynode.dVal;
	string strVal = tr.mynode.strVal;
	string strText = tr.mynode.Text;
	printf("\nID = %d, Show = %d, Enable = %d, nVal = %d, dVal = %g, strVal = %s, Text = %s",
		iID, iShow, iEnable, nVal, dVal, strVal, strText);
}

// Demonstrate assigning vectors to and from TreeNodes
void VectorsInTreeNodeEx()
{
	int ii;
	Tree tr; // Tree declaration and definition
	vector<float> vFloats1 = { -1.5, 2.4, 0, 7.8 }, vFloats2; // Declare two vectors, initialize one
	vector<short> vShorts1 = { -1, 2, 0, 7 }, vShorts2; // Declare two vectors, initialize one

	tr.VecOfFloats.fVals = vFloats1; // Save vector in TreeNode
	vFloats2 = tr.VecOfFloats.fVals; // Get vector from TreeNode
	printf("\n");
	for(ii = 0; ii < vFloats1.GetSize(); ii++ )
		printf("vFloats1[%d]=%g\tvFloats2[%d]=%g\n", ii, vFloats1[ii], ii, vFloats2[ii]); 

	tr.VecOfShorts.sVals = vShorts1; // Save vector in TreeNode
	vShorts2 = tr.VecOfShorts.sVals; // Get vector from TreeNode
	printf("\n");
	for(ii = 0; ii < vFloats1.GetSize(); ii++ )
		printf("vShorts1[%d]=%d\tvShorts2[%d]=%d\n", ii, vShorts1[ii], ii, vShorts2[ii]); 
}

// Demonstrate assigning a Structure to a TreeNode
// This function assumes the active layer is a worksheet having three columns
//   with x-y data in columns 1 and 2
void AssignStructureToTreeNodeEx()
{
	// Get active worksheet
	Worksheet wks = Project.ActiveLayer();
	if( !wks )
		return;
	
	// Use first two columns for data curve
	XYRange xy;
	xy.Add("X", wks, 0, 0, -1, 0);
	xy.Add("Y", wks, 0, 1, -1, 1);
	
	// Use third column for output curve
	DataRange drResultCurve;
	drResultCurve.Add("X", wks, 0, 2, -1, 2);
	
	if(!xy || !drResultCurve)
		return;

	// Declare structure to hold integration result and call function to integrate
	IntegrationResult irResult;	
	vector vX, vY, vResultCurve;
	xy.GetData(vX, 0);
	xy.GetData(vY, 1);
	vResultCurve.SetSize(vX.GetSize());
	bool bRet = ocmath_integrate(vX, vY, 0, vX.GetSize()-1, &irResult, vResultCurve);
	
	vector vData;
	DWORD dwPlotID;
	drResultCurve.GetData(DRR_GET_MISSING | DRR_NO_FACTORS, 0, &dwPlotID, NULL, &vData);

	drResultCurve.SetData(vResultCurve);
	
	if(bRet )
		printf("Integration Error!\n");

	// The Integrated curve will be in third column
	// To see result values such as area copy structure to tree and output
	Tree trResult;
	trResult = irResult;
	out_tree(trResult);	
}

// Demonstrate how to find and access nodes of a tree
void AccessNodesOfATreeEx()
{
	Tree tr; // Tree declaration and definition
	tr.Edge.Style.strVal = "Solid Line";
	tr.Edge.Color.strVal = "Red";
	tr.Edge.Thickness.strVal = "5";

	// Get child node by name
	TreeNode tn;
	printf("\nGet node by name...\n");
	tn = tr.Edge.GetNode("Color");
	printf("tr.Edge.%s.strVal = %s\n",  tn.tagName, tn.strVal);

	// Foreach loop through all child nodes using Children collection
	printf("\nForeach loop through child nodes...\n");
	foreach(TreeNode tnChild in tr.Edge.Children ) // Foreach child in node...
	{
		printf("tr.Edge.%s.strVal = %s\n",  tnChild.tagName, tnChild.strVal);
	}

	// Loop forward through nodes
	printf("\nIterate forward through nodes...\n");
	tn = tr.Edge.FirstNode; // Get first node
	while( tn.IsValid() ) // While nodes exist...
	{
		printf("tr.Edge.%s.strVal = %s\n",  tn.tagName, tn.strVal);
		tn = tn.NextNode; // Get next node
	}

	// Loop backward through nodes
	printf("\nIterate backward through nodes...\n");
	tn = tr.Edge.LastNode; // Get last node
	while( tn.IsValid() ) // While nodes exist...
	{
		printf("tr.Edge.%s.strVal = %s\n",  tn.tagName, tn.strVal);
		tn = tn.PrevNode; // Get previous node
	}

	// Get parent node
	printf("\nGet parent of node and number of child nodes...\n");
	tn = tr.Edge.Color.Parent();
	printf("tr.%s has %d child nodes\n",  tn.tagName, tn.GetNodeCount());
}

// Add and remove nodes of a tree
void AddAndRemoveNodesOfATreeEx()
{
	Tree tr;

	// Add nodes by assigning values...
	tr.Edge.Style.strVal = "Solid Line";
	tr.Edge.Color.strVal = "Red";
	tr.Edge.Thickness.strVal = "5";
	out_tree(tr);

	// Exlicitly add nodes...
	tr.AddNode("Fill", 200);
	tr.Fill.AddTextNode("Hashing", "Style", 201);
	tr.Fill.AddNumericNode(3.3, "Density", 202);
	tr.Fill.AddTextNode("Pink", "Color", 203);	
	out_tree(tr);

	// Clone tree to make backup copy...
	Tree trCopy;
	trCopy = tr.Clone();

	// Remove specified nodes...
	tr.Fill.Style.Remove(); // Remove Style node by self reference
	tr.Fill.RemoveChild(202); // Remove Density node by ID
	tr.Fill.RemoveChild("Color"); // Remove Color node by name	
	out_tree(tr);

	// Replace childless Fill node by copy of Fill node...
	tr.Fill.Replace(trCopy.Fill);	
	out_tree(tr);

	// Remove entire Fill node...
	tr.RemoveChild(tr.Fill); // Remove Fill node by node	
	out_tree(tr);

	// Reset entire tree removing all nodes...
	tr.Reset();	
	out_tree(tr);
}

// Clone (copy) a tree and reference to a tree	
void TreeNodeCloneVsReferenceEx()
{
	Tree tr; // Tree declaration and definition
	tr.Students.nVal = 453;
	tr.Teachers.nVal = 23;
	tr.Administrators.nVal = 5;
	out_tree(tr);

	TreeNode tnClone, tnReference;
	tnReference = tr; // Assign address of tr
	tnClone = tr.Clone(); // Assign clone (copy) of tree
	
	tr.Students.nVal = 508; // Modify original tree

	// Output original, referenced, and cloned (copied) trees
	out_tree(tr);
	out_tree(tnReference);
	out_tree(tnClone);
}	

// Save a tree to an XML file and reload tree from XML file	
void SaveToAndLoadFromXMLEx()
{
	Tree tr; // Tree declaration and definition
	tr.IntNode.ID = 200;
	tr.IntNode.Show = 1;
	tr.IntNode.Enable = 1;
	tr.IntNode.nVal = 6;
	tr.StrNode.ID = 201;
	tr.StrNode.strVal = "This is a string value";
	tr.DoubleNode.ID = 202;
	tr.DoubleNode.dVal = -8.9;	
	out_tree(tr);
	
	// Print tree as XML string
	printf("\nXML file as string\n%s\n",tr.XML);

	// Save tree
	string strXMLFile = GetAppPath(TRUE) + "Samples\\Origin C Examples\\Programming Guide\\Trees and XML\\MyTree.XML";
	tr.Save(strXMLFile);
	ASSERT( strXMLFile.IsFile() );

	// Load tree using Tree constructor
	Tree trConstructor(strXMLFile);	
	out_tree(trConstructor);

	// Load tree using Load member function
	Tree trLoad;
	trLoad.Load(strXMLFile);	
	out_tree(trLoad);
}

// Demonstrate scalablilty of functions when passing tree as argument  
void ScalableFunctionEx()
{
	Tree tr; // Tree declaration and definition
	tr.Input.Term1.dVal = 3;
	tr.Input.Term2.dVal = 4;
//	tr.Input.Term3.dVal = 6; // ** 3 ** Uncomment to scale calling function

	// Compute sum
	OperateOnTreeArg(tr);

	// ** 2 ** Uncomment code below to modify calling function to compute mean
	//tr.Option.nVal = 1;
	//OperateOnTreeArg(tr);

	out_tree(tr);
}

// Scalable helper function accepting tree as argument
static bool OperateOnTreeArg(TreeNode& trArg)
{
	trArg.Result.Reset();

	trArg.Result.Sum.dVal = 0;
	foreach(TreeNode tn in trArg.Input.Children)
		trArg.Result.Sum.dVal += tn.dVal;
	trArg.Result.NumTerms.dVal = (double) trArg.Input.GetNodeCount();

	// ** 1 ** Uncomment code below to modify called function to compute mean
	//if( trArg.Option.IsValid() )
		//if( trArg.Option.nVal == 1 )
			//trArg.Result.Mean.dVal = trArg.Result.Sum.dVal / trArg.Result.NumTerms.dVal;

	return true;
}