/*------------------------------------------------------------------------------*
 * 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>

// 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;
	tree_dump(tr, strLabel);
	tr.mynode.dVal = 3.5;
	tree_dump(tr, strLabel);
	tr.mynode.strVal = "This is a string value";
	tree_dump(tr, strLabel);
	tr.mynode.Text = "-8.9";
	tree_dump(tr, strLabel);

	// 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 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("Iterate 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";
	tree_dump(tr, "\nTree with Edge nodes");

	// 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);
	tree_dump(tr, "\nTree with Fill nodes added");

	// 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
	tree_dump(tr, "\nTree with Fill child nodes removed");

	// Replace childless Fill node by copy of Fill node...
	tr.Fill.Replace(trCopy.Fill);
	tree_dump(tr, "\nTree with Fill child nodes replaced from copy");	

	// Remove entire Fill node...
	tr.RemoveChild(tr.Fill); // Remove Fill node by node
	tree_dump(tr, "\nTree with Fill node removed");

	// Reset entire tree removing all nodes...
	tr.Reset();
	tree_dump(tr, "\nReset tree will no nodes");
}

// 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;
	tree_dump(tr, "\nOriginal tree");

	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
	tree_dump(tr, "\nOriginal tree (modified)");
	tree_dump(tnReference, "\nReference to original tree (also modified)");
	tree_dump(tnClone, "\nClone (copy) of tree (not modified)");
}	

// 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;
	tree_dump(tr, "\nOriginal tree");
	
	// Print tree as XML string
	printf("\nXML file as string\n%s\n",tr.XML);

	// Save tree
	tr.Save(GetAppPath() + "Samples\\Programming\\Origin C Files\\MyTree.XML");

	// Load tree using Tree constructor
	string str = GetAppPath() + "Samples\\Programming\\Origin C Files\\MyTree.XML";
	Tree trConstructor(str);
	tree_dump(trConstructor, "\nCopy of Original tree loaded using Tree constructor");

	// Load tree using Load constructor
	Tree trLoad;
	trLoad.Load(GetAppPath() + "Samples\\Programming\\Origin C Files\\MyTree.XML");
	tree_dump(trLoad, "\nCopy of Original tree loaded using Load method");
}

// 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);

	tree_dump(tr, "Results:");
}

// 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;
}

// 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]); 
}