/*------------------------------------------------------------------------------*
 * File Name: XFWiz.c		 													*
 * Creation: Sim 03-20-2007														*
 * Purpose: OriginC Source C file												*
 * Copyright (c) ABCD Corp.	2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010		*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING								*
 *	Sim 11-07-2008 FIX_REOPEN_PA_OPJ_FILE_TO_RECALCULATE						*
 *	Sim 11-14-2008 SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5							*
 *	Sim 11-17-2008 FIX_SAVE_SHARED_VALUE_ON_PA_WIZ_THEME_TREE					*
 *	Sim 11-27-2008 FIX_REFRESH_POPUP_THEME_NAME_LIST_MENU						*
 *	Folger 12/10/08 v8.0984d REMOVE_ANALYSIS_MARKER_WHEN_CLICK_CANCEL_IN_WIZARD	*
 *	Sim 12-29-2008 QA80-12798 XF_WIZ_THEME_COMPARE								*
 *	Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE				*
 *	Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE				*
 *	Sim 01-14-2009 FIX_XFWIZ_OP_DISPLAY_THEME_NAME								*
 *	Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS			*
 *	Folger 02/01/09 v8.0968b WIZ_OP_IS_REMOVED_IF_OPEN_NEW_PA_FROM_GRAPH_WITH_OP*
 *	Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT							*
 *	Folger 11/03/09 BETTER_CHECKING_FOR_RUNNING_PA_FROM_AUTO_UPDATE				*
 *------------------------------------------------------------------------------*/
 
////////////////////////////////////////////////////////////////////////////////////
// Including the system header file Origin.h should be sufficient for most Origin
// applications and is recommended. Origin.h includes many of the most common system
// header files and is automatically pre-compiled when Origin runs the first time.
// Programs including Origin.h subsequently compile much more quickly as long as
// the size and number of other included header files is minimized. All NAG header
// files are now included in Origin.h and no longer need be separately included.
//
// Right-click on the line below and select 'Open "Origin.h"' to open the Origin.h
// system header file.
#include <Origin.h>
////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////////
// Include your own header files here.
//#include <Array.h>
#include <xfutils.h>
#include <XFBase.h> ///---Sim 12-29-2008 QA80-12798 XF_WIZ_THEME_COMPARE
#include <GetNBox.h>
#include <..\OriginLab\theme_utils.h>
#include <..\OriginLab\XFWiz.h>

////////////////////////////////////////////////////////////////////////////////////
// Start your functions here.
//#define STR_NODE_DATARANGE	"DataRange"
#define STR_NODE_INPUT	"Inputs"
#define STR_NODE_OUTPUT	"Outputs"

//#define STR_NODE_INPUT_DATARANGE	"Input"
//#define STR_NODE_OUTPUT_DATARANGE	"Output"

#define STR_NODE_INFO			"Info"

#define STR_NODE_XF_NAME			"XFNames"
//#define STR_NODE_VAR				"Var"

#define STR_NODE_TARGET_PAGE		"TargetPage"
//#define STR_NODE_OP_OWNER			"OperationOwner"

/*
// old
	//trInputsOutputs
		//|--Inputs
			//|--Input1
			//|--Input2
			//|--....
		//|--Outputs
			//|--Output1
			//|--Output2
			//|--....
		//|--Info
			//|--Inputs
				//|--Input1
					//|--XFName
					//|--Var
				//|--Input2
					//|--XFName
					//|--Var
				//|--....
			//|--Outputs
				//|--Output1
					//|--XFName
					//|--Var
				//|--Output2
					//|--XFName
					//|--Var
				//|--....
			//|--TargetPage
			
	trInputsOutputs
		|--Inputs (uids, .nVals)
		|--Outputs (uids, .nVals)
		|--Info
			|--Inputs
				|--XFNames (.strVals)
			|--Outputs
				|--XFNames (.strVals)
			|--TargetPage
*/
///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
XFWizInputOutputRange::XFWizInputOutputRange()
{
}
XFWizInputOutputRange::XFWizInputOutputRange(const TreeNode& trInputsOutputs)
{
	SetTree(trInputsOutputs);
}
///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE

bool XFWizInputOutputRange::SetTree(const TreeNode& trInputsOutputs)
{
	if ( !trInputsOutputs )
		return false;
	Reset();
	
	TreeNode trInputs = trInputsOutputs.GetNode(STR_NODE_INPUT);
	TreeNode trOutputs = trInputsOutputs.GetNode(STR_NODE_OUTPUT);
	
	TreeNode trInfos = trInputsOutputs.GetNode(STR_NODE_INFO);
	if ( !trInfos )
		return false;
	TreeNode trInputsInfo = trInfos.GetNode(STR_NODE_INPUT);
	TreeNode trOutputsInfo = trInfos.GetNode(STR_NODE_OUTPUT);
	
	
	SetRangeTree(trInputs, trInputsInfo, true);
	SetRangeTree(trOutputs, trOutputsInfo, false);
	
	TreeNode trTargetPage = trInfos.GetNode(STR_NODE_TARGET_PAGE);
	if ( trTargetPage )
	{
		Page pg(trTargetPage.strVal);
		SetTargetPage(pg);
	}
	
	//m_bOpOwner = false;
	//TreeNode trOpOwner = trInfos.GetNode(STR_NODE_OP_OWNER);
	//if ( trOpOwner )
		//m_bOpOwner = trOpOwner.nVal;
	
	return true;
}
void XFWizInputOutputRange::SetRangeTree(const TreeNode& trRanges, const TreeNode& trInfos, bool bInput)
{
	//Array<DataRange&> arrdr;
	//arrdr.SetSize(1);
	
	vector<int> vRangeUIDs;
	vRangeUIDs = trRanges.nVals;
	
	vector<string> vXFNames;
	TreeNode trXFName = trInfos.GetNode(STR_NODE_XF_NAME);
	if ( trXFName )
		vXFNames = trXFName.strVals;
	ASSERT( vRangeUIDs.GetSize() == vXFNames.GetSize() );
	
	//for ( int ii = 0; ii < trRanges.GetNodeCount(); ii++)
	for ( int ii = 0; ii < vRangeUIDs.GetSize(); ii++)
	{
		//TreeNode trRange =  trRanges.Children.Item(ii);
		//TreeNode trInfo =  trInfos.Children.Item(ii);
		
		DataRange dr;
		//dr.Create();
		//dr.SetTree(trRange, DRTREE_ONE_DATA);
		dr = (DataRange) Project.GetObject(vRangeUIDs[ii]);
		if ( dr && dr.IsValid() )//&& dr.GetNumData() > 0 )
			AddRange(dr, vXFNames[ii], bInput, true);
		else
		{
			dr.Create();
			AddRange(dr, vXFNames[ii], bInput, false);
			///---Sim 11-07-2008 FIX_REOPEN_PA_OPJ_FILE_TO_RECALCULATE
			// Project file will remove all invalid data range, not need assert to bother customer
			//ASSERT(FALSE);
			///---END FIX_REOPEN_PA_OPJ_FILE_TO_RECALCULATE
		}
		/*
		{
			TreeNode trXFName = trInfo.GetNode(STR_NODE_XF_NAME);
			//TreeNode trVar = trInfo.GetNode(STR_NODE_VAR);
			//if ( trXFName && trVar )
			//{
				//Add(dr, trXFName.strVal, trVar.strVal, bInput);
			//}
			if ( trXFName )
			{
				//arrdr.SetAt(0, dr);
				AddRange(dr, trXFName.strVal, bInput, true);
			}
			
		}
		*/
	}
}

bool XFWizInputOutputRange::GetTree(Tree& trInputsOutputs)
{
	if ( !trInputsOutputs )
		return false;
	trInputsOutputs.Reset();
	TreeNode trInputs = trInputsOutputs.AddNode(STR_NODE_INPUT);
	TreeNode trOutputs = trInputsOutputs.AddNode(STR_NODE_OUTPUT);
	
	TreeNode trInfos = trInputsOutputs.AddNode(STR_NODE_INFO);
	TreeNode trInputsInfo = trInfos.AddNode(STR_NODE_INPUT);
	TreeNode trOutputsInfo = trInfos.AddNode(STR_NODE_OUTPUT);

	GetRangeTree(trInputs, trInputsInfo, true);
	GetRangeTree(trOutputs, trOutputsInfo, false);
	
	TreeNode trTargetPage = trInfos.AddNode(STR_NODE_TARGET_PAGE);
	if ( trTargetPage )
	{
		Page pg;
		if ( GetTargetPage(pg) )
			trTargetPage.strVal = pg.GetName();
	}
	
	//TreeNode trOpOwner = trInfos.AddNode(STR_NODE_OP_OWNER);
	//if ( trOpOwner )
		//trOpOwner.nVal = m_bOpOwner;
	
	return true;
}
void XFWizInputOutputRange::GetRangeTree(TreeNode& trRanges, TreeNode& trInfos, bool bInput)
{
	vector<int> vRangeUIDs;
	vector<string> vXFNames;
	
	DataRange dr;
	//Array<DataRange&> arrdr;
	string strXFName;
	//string strVar;	
	
	int nIndex = 0;
	//while ( Get(nIndex++, dr, strXFName, strVar, bInput) )
	while ( GetRange(nIndex++, dr, strXFName, bInput) )
	{
		/*
		//for (int ii = 0; ii < arrdr.GetSize(); ii++)
		//{
			//DataRange dr = arrdr.GetAt(ii);
			
			string strTagName = (bInput ? STR_NODE_INPUT_DATARANGE : STR_NODE_OUTPUT_DATARANGE);
			strTagName += nIndex;
			TreeNode trRange = trRanges.AddNode(strTagName);
			TreeNode trInfo =  trInfos.AddNode(strTagName);
			
			dr.GetTree(trRange);
			trInfo.AddTextNode(strXFName, STR_NODE_XF_NAME);
			//trInfo.AddTextNode(strVar, STR_NODE_VAR);
		//}
		*/
		vRangeUIDs.Add(dr.IsValid()? dr.GetUID() : 0);
		vXFNames.Add(strXFName);
	}
	
	trRanges.nVals = vRangeUIDs;
	TreeNode trXFName = trInfos.AddNode(STR_NODE_XF_NAME);
	if ( trXFName )
		trXFName.strVals = vXFNames;
}

/*
// move from blpwiz.c
//static bool _set_SingleRange_treenode(TreeNode trData,  XYRange& dr)
static bool _set_SingleRange_treenode(TreeNode trData,  DataRange& dr)
{
	
	if(!dr.IsValid())
		return false;
	
	Tree tr;
	tr.AddNode(IMPTREE_NODE_DATA_RANGE);
	TreeNode trDataRange = tree_check_get_node(tr, IMPTREE_NODE_DATA_RANGE);
	dr.GetTree(trDataRange);//each ranges as a treenode of the tree
	string strRangeString;
	///---Sim 03-10-2008 FIX_SET_XYRANGE_GETN_TREE
	//dr.GetRuntimeDescription(strRangeString);
	dr.GetRangeString(strRangeString,  NTYPE_ADD_ROW_RANGE);
	///---END FIX_SET_XYRANGE_GETN_TREE
	//strRangeString = dr.GetDescription();
	///Jasmine 01/19/08 MUST_HAS_RANGE1_NODE
	//if(!trData.Range1)
	TreeNode trRange1 = trData.Range1;
	if(!trRange1)
    {
         trData.RemoveChildrenWithPrefix(NULL);
         trRange1 = trData.AddNode("Range1");
    }
         //trData.Range1.Replace(trDataRange, true, true, false);  /////add back by sandy 2007-7-16
         //trData.Replace(trDataRange, true, true, false);
    trRange1.Replace(trDataRange, true, true, false);
	///End MUST_HAS_RANGE1_NODE
    trData.Range1.SetAttribute(STR_DATA_ATTRIB, strRangeString);

	// --------------------------------------------------	
	// this function call is replication of logic of sub-dyna control.
	// it is responsibility of sub-dyna control to update this attribute in the root level
	// you have to do it manually here
	trData.SetAttribute(STR_DATA_ATTRIB, strRangeString);
	// ----------------------------------------------------	
	
	return true;
}

bool XFWizInputOutputRange::ApplyRange(TreeNode& trGetN, LPCSTR lpcszXFName, bool bInput)
{
	DataRange dr;
	string strXFName;
	string strVar;	
	
	int nIndex = 0;
	while ( Get(nIndex++, dr, strXFName, strVar, bInput) )
	{
		if ( 0 == strXFName.CompareNoCase(lpcszXFName) )
		{
			TreeNode trVar = trGetN.GetNode(strVar);
			if ( _set_SingleRange_treenode(trVar, dr) ) //need recode this line
				return false;
		}
	}
	return true;
}
*/
/*
bool XFWizInputOutputRange::GetInput(int& nInputUID, LPCSTR lpcszXFName)
{
	DataRange dr;
	string strXFName;
	string strVar;	
	
	int nIndex = 0;
	while ( Get(nIndex++, dr, strXFName, strVar, true) )
	{
		if ( 0 == strXFName.CompareNoCase(lpcszXFName) )
		{
			nInputUID = dr.GetUID(TRUE);
			return true;
		}
	}
	
	return false;
}
bool XFWizInputOutputRange::GetOutputs(vector<int>& vOutputUIDs, LPCSTR lpcszXFName)
{
	vOutputUIDs.SetSize(0);
	
	DataRange dr;
	string strXFName;
	string strVar;	
	
	int nIndex = 0;
	while ( Get(nIndex++, dr, strXFName, strVar, false) )
	{
		if ( 0 == strXFName.CompareNoCase(lpcszXFName) )
		{
			vOutputUIDs.Add(dr.GetUID(TRUE));
		}
	}
	
	return true;
}
*/
bool XFWizInputOutputRange::GetUIDs(vector<int>& vUIDs, LPCSTR lpcszXFName, bool bInput)
{
	Array<DataRange&> arrdr;
	if ( !Get(&arrdr, lpcszXFName, bInput) )
		return false;
	
	vUIDs.SetSize(0);
	for (int ii = 0; ii < arrdr.GetSize(); ii++)
	{
		DataRange& dr = arrdr.GetAt(ii);
		//vUIDs.Add(dr.GetUID(TRUE));
		vUIDs.Add(dr.IsValid()? dr.GetUID() : 0);
	}
	return true;
}


bool XFWizInputOutputRange::Apply(TreeNode& trGetN, LPCSTR lpcszXFName, DWORD dwCtrl)// = APPLY_RULE_INPUT|APPLY_RULE_OUTPUT
{
	/*
	bool bRet = true;
	if ( dwCtrl | APPLY_RULE_INPUT )
		bRet &= ApplyRange(trGetN, lpcszXFName, true);
	if ( dwCtrl | APPLY_RULE_OUTPUT )
		bRet &= ApplyRange(trGetN, lpcszXFName, false);
	return bRet;
	*/
	
	vector<int> vInputUIDs;
	vector<int> vOutputUIDs;
	if ( dwCtrl & APPLY_RULE_INPUT )
		GetUIDs(vInputUIDs, lpcszXFName, true);
	if ( dwCtrl & APPLY_RULE_OUTPUT )
		GetUIDs(vOutputUIDs, lpcszXFName, false);
	
	int nInputUID = (vInputUIDs.GetSize() > 0) ? vInputUIDs[0]: 0;
	bool bRet = false;
	//if ( vOutputUIDs.GetSize() > 0 && vOutputUIDs[0] > 0 ) // temp code
	{
		/// YuI 10/31/08 QA70-12503 EXPAND_D_OPTION_STRING_TO_SUPPORT_ARBITRARY_NAMES
		//	bRet = okxf_update_tree_from_ranges(&trGetN, nInputUID, &vOutputUIDs);
		bRet = okxf_update_tree_from_ranges(&trGetN, nInputUID, &vOutputUIDs, TRUE);
		/// end EXPAND_D_OPTION_STRING_TO_SUPPORT_ARBITRARY_NAMES
	}
		
	return bRet;
	//return true;
}

DataRange* XFWizInputOutputRange::NewRange(const DataRange& dr, bool bCreateUID)// = false
{
	DataRange *pdrNew = new DataRange;
	ASSERT(pdrNew);
	//if ( bReUseUID )
		*pdrNew = dr;
	//else
		//dr.Clone(*pdrNew, TRUE);
		
	if ( bCreateUID )
	{
		if( pdrNew->IsValid() )// && pdrNew->GetNumData() > 0 )
		{
			int uid = pdrNew->GetUID(TRUE); // generate uid
			Project.AddDataRange(*pdrNew);
		}
		else
			ASSERT(FALSE);
	}
	
	return pdrNew;
}
DataRange& XFWizInputOutputRange::GetRange(int nIndex, bool bInput)
{
	if ( bInput )
		return m_drInputs.GetAt(nIndex);
	else
		return m_drOutputs.GetAt(nIndex);
}

void XFWizInputOutputRange::Reset()
{
	m_drInputs.SetSize(0);
	m_saInputXFNames.SetSize(0);
	//m_saInputVars.SetSize(0);
	
	m_drOutputs.SetSize(0);
	m_saOutputXFNames.SetSize(0);
	//m_saOutputVars.SetSize(0);
}
//bool XFWizInputOutputRange::Add(const DataRange& dr, LPCSTR lpcszXFName, LPCSTR lpcszVar, bool bInput)
bool XFWizInputOutputRange::AddRange(const DataRange& dr, LPCSTR lpcszXFName, bool bInput, bool bReUseUID)// = false
{
	if ( !dr.IsValid() || NULL == lpcszXFName )
		return false;
	
	bool bRet = true;
	int nSize;
	
	//DataRange *pdrNew = NewRange(dr, bReUseUID);
	DataRange *pdrNew = NewRange(dr, !bReUseUID);
	//if ( !bReUseUID ) // for else, this data range object is from project by uid
	//{
		//if( pdrNew->IsValid() && pdrNew->GetNumData() > 0 )
			//Project.AddDataRange(*pdrNew);
		//pdrNew->GetUID(TRUE); // generate uid
	//}
	
	if ( bInput )
	{
		bRet &= ( m_drInputs.Add(*pdrNew) >= 0 );
		bRet &= ( m_saInputXFNames.Add(lpcszXFName) >= 0 );
		//bRet &= m_saInputVars.Add(lpcszVar);
	}
	else
	{
		bRet &= ( m_drOutputs.Add(*pdrNew) >= 0 );
		bRet &= ( m_saOutputXFNames.Add(lpcszXFName) >= 0 );
		//bRet &= m_saOutputVars.Add(lpcszVar);
	}
	
	return bRet;	
}
//bool XFWizInputOutputRange::Get(int nIndex, DataRange& dr, string& strXFName, string& strVar, bool bInput)
bool XFWizInputOutputRange::GetRange(int nIndex, DataRange& dr, string& strXFName, bool bInput)
{
	if ( bInput )
	{
		if ( nIndex > m_drInputs.GetSize() - 1 )
			return false;
		
		dr = m_drInputs.GetAt(nIndex);
		strXFName = m_saInputXFNames[nIndex];
		//strVar = m_saInputVars[nIndex];
	}
	else
	{
		if ( nIndex > m_drOutputs.GetSize() - 1 )
			return false;
		
		dr = m_drOutputs.GetAt(nIndex);
		strXFName = m_saOutputXFNames[nIndex];
		//strVar = m_saOutputVars[nIndex];
	}
	
	return true;
}
bool XFWizInputOutputRange::UpdateRange(int nIndex, const DataRange& dr, LPCSTR lpcszXFName, bool bInput)
{
	if ( !dr.IsValid() || NULL == lpcszXFName )
		return false;
	
	if ( bInput )
	{
		if ( nIndex > m_drInputs.GetSize() - 1 )
			return false;
		
		DataRange &drOlder = m_drInputs.GetAt(nIndex);
		dr.Clone(drOlder, TRUE);
		//DataRange *pdrNew = NewRange(dr, true);
		//m_drInputs.SetAt(nIndex, *pdrNew);
		
		m_saInputXFNames[nIndex] = lpcszXFName;
		//strVar = m_saInputVars[nIndex];
	}
	else
	{
		if ( nIndex > m_drOutputs.GetSize() - 1 )
			return false;
		
		DataRange &drOlder = m_drOutputs.GetAt(nIndex);
		dr.Clone(drOlder, TRUE);
		//DataRange *pdrNew = NewRange(dr, true);
		//m_drOutputs.SetAt(nIndex, *pdrNew);
		
		m_saOutputXFNames[nIndex] = lpcszXFName;
		//strVar = m_saOutputVars[nIndex];
	}
	
	return true;
}
bool XFWizInputOutputRange::RemoveRange(int nIndex, bool bInput)
{
	if ( bInput )
	{
		if ( nIndex > m_drInputs.GetSize() - 1 )
			return false;
		
		///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
		//DataRange& dr = m_drInputs.GetAt(nIndex);
		//if ( dr && dr.IsValid() )
			//Project.RemoveDataRange(dr); 
		///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
		m_drInputs.RemoveAt(nIndex);
		m_saInputXFNames.RemoveAt(nIndex);
	}
	else
	{
		if ( nIndex > m_drOutputs.GetSize() - 1 )
			return false;
		
		///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
		//DataRange& dr = m_drOutputs.GetAt(nIndex);
		//if ( dr && dr.IsValid() )
			//Project.RemoveDataRange(dr); 
		///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
		m_drOutputs.RemoveAt(nIndex);
		m_saOutputXFNames.RemoveAt(nIndex);
	}
	
	return true;
}

bool XFWizInputOutputRange::Add(const Array<DataRange&> *parrdr, LPCSTR lpcszXFName, bool bInput, bool bUpdateExisting)// = true
{
	int nSize = 0;
	if ( NULL != parrdr )
		nSize = parrdr->GetSize();
	
	int nPosAdded = 0;
	if ( bUpdateExisting )
	{
		DataRange dr;
		string strXFName;
		
		int nIndex = 0;
		while ( GetRange(nIndex, dr, strXFName, bInput) )
		{
			if ( 0 == strXFName.CompareNoCase(lpcszXFName) )
			{
				// temp fix, skip invalid
				while (nPosAdded < nSize)
				{
					DataRange &dr = parrdr->GetAt(nPosAdded);
					if ( dr && dr.IsValid() )// && dr.GetNumData() > 0 )
						break;
					nPosAdded++;
					ASSERT(FALSE);
				}				

				if ( nPosAdded < nSize )
				{
					if ( !UpdateRange(nIndex, parrdr->GetAt(nPosAdded++), lpcszXFName, bInput) )
						return false;
				}
				///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
				// undo xf maybe pass empty vector of io range, but at that time we should change nothing
				//else
				//{
					//if ( !RemoveRange(nIndex, bInput) )
						//return false;
					//nIndex--;
				//}
				///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
			}
			nIndex++;
		}
	}
	
	for (int ii = nPosAdded; ii < nSize; ii++)
	{
		DataRange &dr = parrdr->GetAt(ii);
		if ( dr && dr.IsValid() )//&& dr.GetNumData() > 0 )
		{
			if ( !AddRange(dr, lpcszXFName, bInput) )
				return false;
		}
		else
			ASSERT(FALSE);
	}
	
	return true;
}
bool XFWizInputOutputRange::Get(Array<DataRange&> *parrdr, LPCSTR lpcszXFName, bool bInput)
{
	if ( NULL == parrdr )
		return false;
	
	parrdr->SetSize(0);
	
	DataRange dr;
	string strXFName;
	
	int nIndex = 0;
	while ( GetRange(nIndex, dr, strXFName, bInput) )
	{
		if ( 0 == strXFName.CompareNoCase(lpcszXFName) )
		{
			DataRange *pdr;
			if ( parrdr->IsOwner() )
			{
				pdr = NewRange(dr);
			}
			else
			{
				DataRange &drExisting = GetRange(nIndex, bInput);
				pdr = &drExisting;
			}
			
			if ( parrdr->Add(*pdr) < 0 )
				return false;
		}
		nIndex++;
	}
	
	//return true;
	return ( parrdr->GetSize() > 0 );
}

bool XFWizInputOutputRange::SetTargetPage(const Page& pg)
{
	if ( pg )
	{
		m_pgTarget = pg;
		return true;
	}
	
	return false;
}
bool XFWizInputOutputRange::GetTargetPage(Page& pg)
{
	if ( m_pgTarget )
	{
		pg = m_pgTarget;
		return true;
	}
	
	return false;
}
//void XFWizInputOutputRange::SetAsOperationOwner(bool bOpOwner)
//{
	//m_bOpOwner = bOpOwner;
//}

//------ Folger 12/10/08 v8.0984d REMOVE_ANALYSIS_MARKER_WHEN_CLICK_CANCEL_IN_WIZARD
static	void	_remove_ranges_analysis_markers(Array<DataRange&>& arrRanges)
{
	for ( int ii=0; ii<arrRanges.GetSize(); ++ii )
	{
		DataRange&	dr = arrRanges.GetAt(ii);
		XYRange		xy(dr);
		if ( xy )
		{
			DataPlot dp;
			int nr1 = 0;
			int nr2 = -1;
			int nIndex = 0;
			while ( xy.GetPlot(dp, nIndex, &nr1, &nr2) )
			{
				///------ Folger 02/01/09 v8.0968b WIZ_OP_IS_REMOVED_IF_OPEN_NEW_PA_FROM_GRAPH_WITH_OP
				//GraphLayer gl;
				//dp.GetParent(gl);
				//gl.ClearMarkers(-1, 0);
				xy.Destroy();
				///------ End WIZ_OP_IS_REMOVED_IF_OPEN_NEW_PA_FROM_GRAPH_WITH_OP
				nIndex++;
			}
		}
	}
}

void	XFWizInputOutputRange::RemoveAllRangesAnalysisMarkers()
{
	_remove_ranges_analysis_markers(m_drInputs);
	//_remove_ranges_analysis_markers(m_drOutputs);
}
//------ End REMOVE_ANALYSIS_MARKER_WHEN_CLICK_CANCEL_IN_WIZARD
///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
void	XFWizInputOutputRange::ClearAll()
{
	int nIndex;
	DataRange dr;
	string strXFName;
	
	nIndex = 0;
	while ( GetRange(nIndex++, dr, strXFName, true) ) // input
	{
		if ( dr.IsValid() )
			Project.RemoveDataRange(dr);
	}
	
	nIndex = 0;
	while ( GetRange(nIndex++, dr, strXFName, false) ) // output
	{
		if ( dr.IsValid() )
			Project.RemoveDataRange(dr);
	}
	
	Reset();
}
///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE

///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define STR_WIZ_THEME_INFO "Info"

XFWizTheme::XFWizTheme()
{
	m_saSharedList.Add(STR_NODE_NAME_AUTO_UPDATE); ///---Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
	m_dVersion = DEFAULT_VERSION_NUMBER;
}
///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
XFWizTheme::XFWizTheme(const TreeNode& trThemes)
{
	m_saSharedList.Add(STR_NODE_NAME_AUTO_UPDATE); ///---Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
	m_dVersion = GetVersion(trThemes);
	m_trThemes.GetAttribute(STR_CLASS_OPTION_NAME_ATTRIB, m_strClassName);
	SetTree(trThemes);
}
///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE

bool XFWizTheme::SetTree(const TreeNode& trThemes)
{
	if ( !trThemes )
		return false;
	
	///---Sim 11-14-2008 SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5
	/*
	if ( !CheckVersion(GetVersion(trThemes), m_dVersion, _L("Operation")) )
		return false;
	
	///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
	//return m_trThemes.Replace(trThemes);
	bool bRet;
	bRet = m_trThemes.Replace(trThemes);
	*/
	bool bRet = CheckLoad(trThemes, _L("Operation"));
	///---END SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5
	
	if ( bRet )
		UpdateThemeFilterEdition();
	
	return bRet;
	///---END NEW_PA_81_THEME_FILTER_SETTING
}
bool XFWizTheme::GetTree(Tree& trThemes)
{
	if ( !trThemes )
		return false;
	
	UpdateSetting();
	///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
	//return trThemes.Replace(m_trThemes);
	return trThemes.Replace(m_trThemes, true, true);
	///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
}

///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
bool XFWizTheme::SetThemeFilterTree(const TreeNode& trThemeFilter)
{
	if ( !trThemeFilter )
		return false;
	
	TreeNode trTF = GetThemeFilter();
	if ( !trTF )
		return false;
	
	return trTF.Replace(trThemeFilter);
}
bool XFWizTheme::GetThemeFilterTree(TreeNode& trThemeFilter)
{
	if ( !trThemeFilter )
		return false;
	
	TreeNode trTF = GetThemeFilter(true);
	if ( !trTF )
		return false;
	
	return trThemeFilter.Replace(trTF);
}
///---END NEW_PA_81_THEME_FILTER_SETTING

bool XFWizTheme::IsEmpty()
{
	return m_trThemes.IsEmpty();
}

void XFWizTheme::SetVersion(double dVersion)
{
	m_dVersion = dVersion;
}
double XFWizTheme::GetVersion()
{
	return m_dVersion;
}
	
#define STR_THEME_PATH_NODE		"Path"
bool XFWizTheme::GetXFList(StringArray& saXFs)
{
	///---Sim 12-29-2008 QA80-12798 XF_WIZ_THEME_COMPARE
	//TreeNode trPath = tree_get_node_by_tagname(m_trThemes, STR_THEME_PATH_NODE, true);
	TreeNode trPath = GetPath();
	///---END QA80-12798 XF_WIZ_THEME_COMPARE
	if (trPath)
	{
		saXFs = trPath.strVals;
		//return true; ///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	}
	///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	else
	{
		saXFs = m_saDefaultXFNames;
	}
	//return false;
	// now no reason failed to get steps, as when current steps are empty, will get default steps
	return true;
	///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
}
bool XFWizTheme::SetXFList(const StringArray& saXFs)
{
	///---Sim 12-29-2008 QA80-12798 XF_WIZ_THEME_COMPARE
	//TreeNode trPath = tree_check_get_node(m_trThemes, STR_THEME_PATH_NODE);
	TreeNode trPath = GetPath(true);
	///---END QA80-12798 XF_WIZ_THEME_COMPARE
	if (trPath)
	{
		trPath.strVals = saXFs;
		return true;
	}
	return false;
}
///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
void  XFWizTheme::SetDefaultSteps(const StringArray& saDefaultXFNames)
{
	m_saDefaultXFNames = saDefaultXFNames;
}
///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS

TreeNode XFWizTheme::GetXFTheme(LPCSTR lpcszXFName, bool bCheckAddNode) // = false
{
	TreeNode trTheme = m_trThemes.FindNodeByAttribute(STR_XF_NAME_ATTRIB, lpcszXFName);
	if ( !trTheme && bCheckAddNode )
	{
		string strValidTag = lpcszXFName;
		strValidTag.MakeValidCName('_');
		trTheme = tree_check_get_node(m_trThemes, strValidTag);
		trTheme.SetAttribute(STR_XF_NAME_ATTRIB, lpcszXFName);
	}
	
	return trTheme;
}

/*
int XFWizTheme::Apply2GetN(TreeNode& trGetN, LPCSTR lpcszXFName)
{
	TreeNode trTheme = GetXFTheme(lpcszXFName);
	if ( !trTheme )
		return NONE_THEME;
		
	if ( !theme_tree_to_getn_tree(trTheme, trGetN, true)) // keep up runtime getn info when go to previous xf,
																		// m_bRestoreXFMode is a flag for is it previous or next.
		return FAILED_APPLY_THEME;
	return SUCCESS_APPLY_THEME;
}
int XFWizTheme::UpdateFromGetN(const TreeNode& trGetN, LPCSTR lpcszXFName)
{
	TreeNode trTheme = GetXFTheme(lpcszXFName, true);
	if ( !trTheme )
		return NONE_THEME;
		
	if ( !theme_tree_from_getn_tree(trTheme, trGetN, true)) // keep up runtime getn info when go to previous xf,
																		// m_bRestoreXFMode is a flag for is it previous or next.
		return FAILED_APPLY_THEME;
	return SUCCESS_APPLY_THEME;
}
*/
//virtual
int XFWizTheme::Update(const TreeNode& trGetN, LPCSTR lpcszXFName, bool bToGetN)
{
	int nRet = SUCCESS_APPLY_THEME; ///---Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
	TreeNode trTheme = GetXFTheme(lpcszXFName, !bToGetN);
	if ( !trTheme )
	///---Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
		//return NONE_THEME;
		nRet = NONE_THEME;
	else
	{
	///---END QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
		if ( bToGetN )
		{
			///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
			//if ( !theme_tree_to_getn_tree(trTheme, trGetN, true)) // keep up runtime getn info when go to previous xf,
			//																	// m_bRestoreXFMode is a flag for is it previous or next.
				//return FAILED_APPLY_THEME;
			Tree trGetNBackup;
			vector<int> vnGUIID;
			vector<int> vnThemeFilterID;
			if ( !m_trLoadedThemeFilter.IsEmpty() && GetThemeFilterMapIDs(vnGUIID, vnThemeFilterID, trGetN, lpcszXFName) )
			{
				// backup and changed theme apply attribute
				trGetNBackup.Replace(trGetN);
				theme_setup_theme_filter_setting(trGetN, m_trLoadedThemeFilter, vnGUIID, vnThemeFilterID);
			}
			
			bool bRet;
			bRet = theme_tree_to_getn_tree(trTheme, trGetN, true); // keep up runtime getn info when go to previous xf,
																				// m_bRestoreXFMode is a flag for is it previous or next.
			if ( !trGetNBackup.IsEmpty() )
			{
				// restore theme apply attribute, which was changed by theme filter setting
				octree_remove_attribute(&trGetN, STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB);
				octree_copy_atts_by_id(&trGetNBackup, &trGetN, STR_XVARIABLE_THEME_APPLICABILITY_ATTRIB);
			}
																						
			if ( !bRet )
				return FAILED_APPLY_THEME;
			///---END NEW_PA_81_THEME_FILTER_SETTING
			
		}
		else
		{
			if ( !theme_tree_from_getn_tree(trTheme, trGetN, true)) // keep up runtime getn info when go to previous xf,
																				// m_bRestoreXFMode is a flag for is it previous or next.
				return FAILED_APPLY_THEME;
		}
	///---Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
	}
	
	if ( !UpdateSharedValues(trGetN, bToGetN) )
		return FAILED_APPLY_THEME;
	//return SUCCESS_APPLY_THEME;
	return nRet;
	///---END QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
}

void XFWizTheme::SetClassName(LPCSTR lpcszClassName)
{
	m_strClassName = lpcszClassName;
}
string XFWizTheme::GetThemeFileName(LPCSTR lpcszThemeName)
{
	string strThemeFileName;
	if ( !m_strClassName.IsEmpty() && lpcszThemeName )
	{
		strThemeFileName = theme_get_settings_file(lpcszThemeName, m_strClassName, tree_get_theme_type(m_trThemes));
	}
	
	return strThemeFileName;
}

bool XFWizTheme::LoadFile(LPCSTR lpcszThemeName)
{
	Tree trThemes;
	if ( themes_tree_from_file(trThemes, GetThemeFileName(lpcszThemeName)) )
	{
		///---Sim 11-14-2008 SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5
		/*
		if ( CheckVersion(GetVersion(trThemes), m_dVersion, lpcszThemeName) )
			m_trThemes.Replace(trThemes);
			tree_set_theme_file_name(m_trThemes, GetThemeFileName(lpcszThemeName));
			return true;
		}
		*/
		if ( CheckLoad(trThemes, lpcszThemeName) )
		{
			tree_set_theme_file_name(m_trThemes, GetThemeFileName(lpcszThemeName));
			return true;
		}
		///---END SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5
	}
	
	return false;
}
bool XFWizTheme::SaveFile(LPCSTR lpcszThemeName)
{
	return themes_tree_to_file(m_trThemes, GetThemeFileName(lpcszThemeName));
}

//bool XFWizTheme::IsDefault(LPCSTR lpcszThemeName)
//{
	//return ( is_theme_default(lpcszThemeName) || theme_is_factory_default(lpcszThemeName) );
//}
bool XFWizTheme::DefaultTheme(int nOp)
{
	//m_trThemes.SetAttribute(STR_CLASS_OPTION_NAME_ATTRIB, m_strClassName);
	UpdateSetting(); // default management required all attributes in trGetN
	bool bRet = theme_default_setting_management(m_trThemes, nOp, NULL, true);
	///Sim, no reason for clean theme tree if no <default> theme
	/*
	if ( !bRet && THEME_DEFAULT_GET == nOp )
	{
		m_trThemes.Reset();
		bRet = true;
	}
	*/
	
	return bRet;
}

bool XFWizTheme::Load(LPCSTR lpcszThemeName)
{
	///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
	//if ( IsDefault(lpcszThemeName) )
		//return DefaultTheme(THEME_DEFAULT_GET);
	
	//return LoadFile(lpcszThemeName);
	bool bRet;
	//if ( IsDefault(lpcszThemeName) )
	// Sim, factory default is special, no need process when load theme
	if ( theme_is_factory_default(lpcszThemeName) )
	{
		m_trThemes.Reset();
		bRet = true;
	}
	else if ( is_theme_default(lpcszThemeName) )
		bRet =  DefaultTheme(THEME_DEFAULT_GET);
	else
		bRet = LoadFile(lpcszThemeName);
	
	if ( bRet )
		UpdateThemeFilterEdition();
	
	return bRet;
	///---END NEW_PA_81_THEME_FILTER_SETTING
}
bool XFWizTheme::Save(LPCSTR lpcszThemeName)
{
	// Sim, factory default can't saved
	if ( theme_is_factory_default(lpcszThemeName) )
		return false;
	
	UpdateSetting();
	//if ( IsDefault(lpcszThemeName) )
	if ( is_theme_default(lpcszThemeName) )
		return DefaultTheme(THEME_DEFAULT_SET);
	
	return SaveFile(lpcszThemeName);
}

///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
//#define STR_WIZ_THEME_SHARED "Shared"
#define STR_WIZ_THEME_SHARED		STR_XF_WIZ_THEME_SHARED
///---END NEW_PA_81_THEME_FILTER_SETTING
TreeNode XFWizTheme::GetShared(bool bCheckAddNode)// = false
{
	TreeNode trShared = m_trThemes.GetNode(STR_WIZ_THEME_SHARED);
	if ( !trShared && bCheckAddNode )
		trShared = tree_check_get_node(m_trThemes, STR_WIZ_THEME_SHARED);

	return trShared;
}
///---Sim 12-29-2008 QA80-12798 XF_WIZ_THEME_COMPARE
TreeNode XFWizTheme::GetPath(bool bCheckAddNode)// = false
{
	TreeNode trPath = m_trThemes.GetNode(STR_THEME_PATH_NODE);
	if ( !trPath && bCheckAddNode )
		trPath = tree_check_get_node(m_trThemes, STR_THEME_PATH_NODE);

	return trPath;	
}
///---END QA80-12798 XF_WIZ_THEME_COMPARE

///------ Folger 11/03/09 BETTER_CHECKING_FOR_RUNNING_PA_FROM_AUTO_UPDATE
// #define STR_WIZ_THEME_OP_HOOK "OpHook"
// void XFWizTheme::SetHookOperation(bool bIsHooked)// = true);
// {
// 	TreeNode trInfo = tree_check_get_node(m_trThemes, STR_WIZ_THEME_INFO);
// 	if ( trInfo )
// 	{
// 		TreeNode trOpHook = tree_check_get_node(trInfo, STR_WIZ_THEME_OP_HOOK);
// 		if ( trOpHook )
// 			trOpHook.nVal = bIsHooked;
// 	}	
// }
// bool XFWizTheme::IsHookOperation()
// {
// 	bool bRet = false;
// 	
// 	TreeNode trInfo = m_trThemes.GetNode(STR_WIZ_THEME_INFO);
// 	if ( trInfo )
// 	{
// 		TreeNode trOpHook = trInfo.GetNode(STR_WIZ_THEME_OP_HOOK);
// 		if ( trOpHook )
// 			bRet = trOpHook.nVal;
// 	}
// 	
// 	return bRet;
// }
///------ End BETTER_CHECKING_FOR_RUNNING_PA_FROM_AUTO_UPDATE

void XFWizTheme::UpdateSetting()
{
	m_trThemes.SetAttribute(STR_WIZARD_VERSION, m_dVersion);
	///---Sim 11-27-2008 FIX_REFRESH_POPUP_THEME_NAME_LIST_MENU
	m_trThemes.SetAttribute(STR_CLASS_OPTION_NAME_ATTRIB, m_strClassName);
	///---END FIX_REFRESH_POPUP_THEME_NAME_LIST_MENU
	///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
	// before save theme file, setup theme filter if it is empty
	GetThemeFilter(true);
	///---END NEW_PA_81_THEME_FILTER_SETTING
}

double XFWizTheme::GetVersion(TreeNode& trThemes)
{
	double dVersion;
	if ( !trThemes.GetAttribute(STR_WIZARD_VERSION, dVersion) )
		dVersion = DEFAULT_VERSION_NUMBER;
	return dVersion;	
}
bool XFWizTheme::CheckVersion(double dVer, double dRefVer, LPCSTR lpcszThemeName)
{
	string strVersion = dVer;
	string strRefVersion = dRefVer;
	///---Sim 12-12-2008 IMPROVE_XF_WIZARD_FAILED_LOAD_THEME_ERROR_MESSAGE
	//return theme_check_version_show_warning(strVersion, strRefVersion, lpcszThemeName, _L("Wizard version"));
	return theme_check_version_show_warning(strVersion, strRefVersion, lpcszThemeName, theme_get_full_xf_wizard_name(m_strClassName));
	///---END IMPROVE_XF_WIZARD_FAILED_LOAD_THEME_ERROR_MESSAGE
}
///---Sim 11-14-2008 SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5
bool XFWizTheme::CheckLoad(TreeNode& trThemes, LPCSTR lpcszThemeName)
{
	Tree trThemesNew;
	trThemesNew.Replace(trThemes);
	
	bool bAcceptable = !is_integer_part_less_then(GetVersion(trThemesNew), m_dVersion);
	if ( !bAcceptable )
		bAcceptable = ConvertVersion(trThemesNew);
	
	if ( !bAcceptable )
	{
		CheckVersion(GetVersion(trThemes), m_dVersion, lpcszThemeName); // only show error
		return false;
	}
	
	return m_trThemes.Replace(trThemesNew);
}

//virtual
bool  XFWizTheme::ConvertVersion(TreeNode& trThemes)
{
	return false;
}
///---END SUPPORT_PA_THEME_SR4_CONVERT_TO_SR5

bool XFWizTheme::IsFromFile(string& strFileName)
{
	return tree_get_theme_file_name(m_trThemes, strFileName);
}

void XFWizTheme::ClearRuntimeInfo()
{
	foreach(TreeNode trNode in m_trThemes.Children)
	{
		trNode.RemoveChild(STR_XFBAR_MULITIMODE_RUNTIME_INFO_TREE);
		//trNode.RemoveChild(STR_XFBAR_MULITIMODE_EXEC_VALUE_TREE);
	}
	///---Sim 11-17-2008 FIX_SAVE_SHARED_VALUE_ON_PA_WIZ_THEME_TREE
	//m_trThemes.RemoveChild(STR_WIZ_THEME_SHARED);
	///---END FIX_SAVE_SHARED_VALUE_ON_PA_WIZ_THEME_TREE
}

///---Sim 10-13-2008 NEW_PA_81_THEME_FILTER_SETTING
////virtual
//bool XFWizTheme::ConstructThemeFilter(TreeNode& trThemeFilter)
//{
	//return false;
//}
////virtual
//bool XFWizTheme::GetThemeFilterMapIDs(vector<int>& vnGUIID, vector<int>& vnThemeFilterID, TreeNode& trGetN, LPCSTR lpcszXFName)
//{
	//return false;
//}

TreeNode XFWizTheme::GetThemeFilter(bool bCheckAddNode) // = false
{
	TreeNode trThemeFilter = tree_get_node_by_id(m_trThemes, IDE_DS_THEME_FILTER);
	if ( !trThemeFilter && bCheckAddNode )
	{
		Tree trDefaultThemeFilter;
		if ( ConstructThemeFilter(trDefaultThemeFilter) )
		{
			trThemeFilter = m_trThemes.AddNode("ThemeFilter");
			trThemeFilter.Replace(trDefaultThemeFilter, true, true, false); // keep and attribute from specified theme filter tree
			trThemeFilter.DataID = IDE_DS_THEME_FILTER;
		}
	}
	
	return trThemeFilter;
}

void XFWizTheme::UpdateThemeFilterEdition()
{
	// keep value only, convert to current display style
	TreeNode trThemeFilter = GetThemeFilter();
	if ( trThemeFilter )
	{
		Tree trThemeFilterTmp;
		if ( ConstructThemeFilter(trThemeFilterTmp) )
		{
			tree_copy_values_by_id(trThemeFilter, trThemeFilterTmp);
			trThemeFilter.Replace(trThemeFilterTmp, true, true, false); // keep and attribute from specified theme filter tree		
			trThemeFilter.DataID = IDE_DS_THEME_FILTER;
		}
		
		m_trLoadedThemeFilter.Replace(trThemeFilter); // keep original theme setting when load theme
	}
	else
		m_trLoadedThemeFilter.Reset(); // keep original theme setting when load theme
}
///---END NEW_PA_81_THEME_FILTER_SETTING

///---Sim 12-29-2008 QA80-12798 XF_WIZ_THEME_COMPARE
bool XFWizTheme::CompareTheme(XFWizTheme *pXFWizTheme, TreeNode& trDiff)
{
	UpdateSetting();
	pXFWizTheme->UpdateSetting();
	
	//Tree trRefTheme;
	//pXFWizTheme->GetTree(trRefTheme);

	bool bRet = true;
	
	vector<string> vsPathCommon;
	//bRet = ( bRet && comparePath(trRefTheme, trDiff, vsPathCommon) );
	//bRet = ( bRet && compareShared(trRefTheme, trDiff) );
	//bRet = ( bRet && compareFilter(trRefTheme, trDiff) );
	//bRet = ( bRet && compareXFs(vsPathCommon, trRefTheme, trDiff) );
	bRet = ( bRet && comparePath(pXFWizTheme, trDiff, vsPathCommon) );
	bRet = ( bRet && compareShared(pXFWizTheme, trDiff) );
	bRet = ( bRet && compareFilter(pXFWizTheme, trDiff) );
	bRet = ( bRet && compareXFs(vsPathCommon, pXFWizTheme, trDiff) );
	
	return bRet;
}

#define STR_LABEL_XFWIZ_THEME_DIFF_PATH		"Step"
//bool XFWizTheme::comparePath(TreeNode& trRefThemes, TreeNode& trDiff, vector<string> &vsPathCommon)
bool XFWizTheme::comparePath(XFWizTheme *pXFWizTheme, TreeNode& trDiff, vector<string> &vsPathCommon)
{
	//TreeNode trPathDest = tree_get_node_by_tagname(m_trThemes, STR_THEME_PATH_NODE, true);
	//TreeNode trPathRef = tree_get_node_by_tagname(trRefThemes, STR_THEME_PATH_NODE, true);
	///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	//TreeNode trPathDest = GetPath();
	//TreeNode trPathRef = pXFWizTheme->GetPath();
	//if ( !trPathDest || !trPathRef )
		//return false;
	///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	
	int nStep;
	vector<string> vsPathDest, vsPathRef;
	Tree treePathDest, treePathRef;
	
	///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	//vsPathDest = trPathDest.strVals;
	GetXFList(vsPathDest);
	///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	for ( nStep = 0; nStep < vsPathDest.GetSize(); nStep++ )
		treePathDest.AddTextNode(vsPathDest[nStep], STR_LABEL_XFWIZ_THEME_DIFF_PATH + (nStep+1));
		
	///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	//vsPathRef = trPathRef.strVals;
	pXFWizTheme->GetXFList(vsPathRef);
	///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
	for ( nStep = 0; nStep < vsPathRef.GetSize(); nStep++ )
		treePathRef.AddTextNode(vsPathRef[nStep], STR_LABEL_XFWIZ_THEME_DIFF_PATH + (nStep+1));
	
	Tree treeDiff;
	int nRet = treeDiff.CreateDiff(treePathDest, treePathRef, TRDIFF_KEEP_INDIVI_TARGET | TRDIFF_KEEP_INDIVI_REF | TRDIFF_KEEP_REF_VALUES);
	if ( nRet < 0 )
		return false;
	if ( nRet > 0 )
	{
		TreeNode tr = trDiff.AddNode(STR_THEME_PATH_NODE);
		if ( tr )
			tr.Replace(treeDiff, true, true);
	}
	
	vsPathCommon.SetSize(0);
	for ( nStep = 0; nStep < vsPathDest.GetSize(); nStep++ )
	{
		if ( 0 <= vsPathRef.Find(vsPathDest[nStep]) )
			vsPathCommon.Add(vsPathDest[nStep]);
	}
	
	return true;
}
//bool XFWizTheme::compareShared(TreeNode& trRefThemes, TreeNode& trDiff)
bool XFWizTheme::compareShared(XFWizTheme *pXFWizTheme, TreeNode& trDiff)
{
	//TreeNode trSharedDest = tree_get_node_by_tagname(m_trThemes, STR_WIZ_THEME_SHARED, true);
	//TreeNode trSharedRef = tree_get_node_by_tagname(trRefThemes, STR_WIZ_THEME_SHARED, true);
	TreeNode trSharedDest = GetShared();
	TreeNode trSharedRef = pXFWizTheme->GetShared();
	
	// shared value is optional, so they may be empty or none
	Tree treeEmpty;
	if ( !trSharedDest )
		trSharedDest = treeEmpty;
	if ( !trSharedRef )
		trSharedRef = treeEmpty;
	
	Tree treeDiff;
	int nRet = treeDiff.CreateDiff(trSharedDest, trSharedRef, TRDIFF_KEEP_INDIVI_TARGET | TRDIFF_KEEP_INDIVI_REF | TRDIFF_KEEP_REF_VALUES);
	if ( nRet < 0 )
		return false;
	if ( nRet > 0 )
	{
		TreeNode tr = trDiff.AddNode(STR_WIZ_THEME_SHARED);
		if ( tr )
			tr.Replace(treeDiff, true, true);
	}
	
	return true;
}
//bool XFWizTheme::compareFilter(TreeNode& trRefThemes, TreeNode& trDiff)
bool XFWizTheme::compareFilter(XFWizTheme *pXFWizTheme, TreeNode& trDiff)
{
	//TreeNode trThemeFilterDest = tree_get_node_by_id(m_trThemes, IDE_DS_THEME_FILTER);
	//TreeNode trThemeFilterRef = tree_get_node_by_id(trRefThemes, IDE_DS_THEME_FILTER);
	TreeNode trThemeFilterDest = GetThemeFilter();
	TreeNode trThemeFilterRef = pXFWizTheme->GetThemeFilter();	
	
	// theme filter is optional, so they may be empty or none
	Tree treeEmpty;
	if ( !trThemeFilterDest )
		trThemeFilterDest = treeEmpty;
	if ( !trThemeFilterRef )
		trThemeFilterRef = treeEmpty;
	
	Tree treeDiff;
	int nRet = treeDiff.CreateDiff(trThemeFilterDest, trThemeFilterRef, TRDIFF_KEEP_INDIVI_TARGET | TRDIFF_KEEP_INDIVI_REF | TRDIFF_KEEP_REF_VALUES);
	if ( nRet < 0 )
		return false;
	if ( nRet > 0 )
	{
		TreeNode tr = trDiff.AddNode("ThemeFilter");
		if ( tr )
			tr.Replace(treeDiff, true, true);
	}
	
	return true;
}
//bool XFWizTheme::compareXFs(const vector<string> &vsPathCommon, TreeNode& trRefThemes, TreeNode& trDiff)
bool XFWizTheme::compareXFs(const vector<string> &vsPathCommon, XFWizTheme *pXFWizTheme, TreeNode& trDiff)
{
	Tree treeDiff;
	
	for ( int nStep = 0; nStep < vsPathCommon.GetSize(); nStep++ )
	{
		//TreeNode trXFDest = m_trThemes.FindNodeByAttribute(STR_XF_NAME_ATTRIB, vsPathCommon[nStep]);
		//TreeNode trXFRef = trRefThemes.FindNodeByAttribute(STR_XF_NAME_ATTRIB, vsPathCommon[nStep]);
		TreeNode trXFDest = GetXFTheme(vsPathCommon[nStep]);
		TreeNode trXFRef = pXFWizTheme->GetXFTheme(vsPathCommon[nStep]);
		
		///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
		//if ( !trXFRef )
			//return false;
		///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
		
		XFBase xf(vsPathCommon[nStep]);
		if ( !xf )
		{
			string strErr;
			strErr.Format("Fail to load xfunction %s!", vsPathCommon[nStep]);
			return error_report_to_user_and_developer(strErr);
		}
		
		Tree trRootGetN;
		TreeNode trGetN;
		if ( !xf.GetGUI(trRootGetN, trGetN, XFGETN_EX_NONE, XFGETN_EX_NONE) )
		{
			string strErr;
			strErr.Format("Fail to load GetN tree of xfunction %s!", vsPathCommon[nStep]);
			return error_report_to_user_and_developer(strErr);
		}
		
		vector<int> vnGUIID;
		vector<int> vnThemeFilterID;
		bool bThemeFilterID = GetThemeFilterMapIDs(vnGUIID, vnThemeFilterID, trGetN, vsPathCommon[nStep]);
		
		Tree trGetNRef;
		trGetNRef = trGetN;
		
		// current value may be not set in time, it assume defualt values
		if ( trXFDest )
		{
			if ( !m_trLoadedThemeFilter.IsEmpty() && bThemeFilterID ) // m_trLoadedThemeFilter is real filter to apply current dialog theme
				theme_setup_theme_filter_setting(trGetN, m_trLoadedThemeFilter, vnGUIID, vnThemeFilterID);
			if ( !theme_tree_to_getn_tree(trXFDest, trGetN, false) )
				return false;
		}
		
		if ( trXFRef )
		{
			TreeNode trThemeFilter = tree_get_node_by_id(m_trThemes, IDE_DS_THEME_FILTER);
			if ( trThemeFilter && bThemeFilterID )
				theme_setup_theme_filter_setting(trGetNRef, trThemeFilter, vnGUIID, vnThemeFilterID);
			if ( !theme_tree_to_getn_tree(trXFRef, trGetNRef, false) )
				return false;
		}
		
		Tree treeXFDiff;
		int nRet = treeXFDiff.CreateDiff(trGetN, trGetNRef, TRDIFF_KEEP_INDIVI_TARGET | TRDIFF_KEEP_INDIVI_REF | TRDIFF_KEEP_REF_VALUES);
		if ( nRet < 0 )
			return false;
		if ( nRet > 0 )
		{
			///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
			//TreeNode tr = treeDiff.AddNode(trXFRef.tagName);
			string strValidTag = vsPathCommon[nStep];
			strValidTag.MakeValidCName('_');
			TreeNode tr = treeDiff.AddNode(strValidTag);
			///---END FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
			if ( tr )
			{
				tr.Replace(treeXFDiff, true, true);
				tr.SetAttribute(STR_LABEL_ATTRIB, vsPathCommon[nStep]); ///---Sim 01-14-2009 FIX_XFWIZ_COMPARE_DEFAULT_THEME_MISS_DEFAULT_STEPS
			}
		}
	}
	
	if ( !treeDiff.IsEmpty() )
	{
		TreeNode tr = trDiff.AddNode("Steps");
		if ( tr )
			tr.Replace(treeDiff, true, true);
	}
	
	return true;
}
///---END QA80-12798 XF_WIZ_THEME_COMPARE

///---Sim 01-12-2009 QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE
bool XFWizTheme::UpdateSharedValues(TreeNode& trGetN, bool bToGetN)
{
	TreeNode trShared = GetShared(!bToGetN);
	if ( bToGetN && !trShared )
		return true; // only skip shared value at first aplly getn tree
	if ( !trShared || !trGetN )
		return false;
	
	int nSharedNum = m_saSharedList.GetSize();
	for (int ii = 0; ii < nSharedNum; ii++ )
	{
		TreeNode trGetNShared = trGetN.GetNode(m_saSharedList[ii]);
		TreeNode trThemeShared = trShared.GetNode(m_saSharedList[ii]);
		if ( !trThemeShared && trGetNShared && !bToGetN )
			trThemeShared = tree_check_get_node(trShared, m_saSharedList[ii]);
		
		if ( trThemeShared && trGetNShared )
		{
			///Sophy 10/21/2008 FIX_FAIL_TO_APPLY_THEME_FOR_DUPLICATED_NODE_DATAID_IN_THEME_WITH_BASELINE_MODE
			// When save theme with user-define baseline mode, trGetN has subnodes with duplicated DataID
			// This will cause apply theme failure, so just copy values here to avoid importing an existing DataID to different node
			//if ( bToGetN )
				//trGetNShared.Replace(trThemeShared);
			//else
				//trThemeShared.Replace(trGetNShared);
			if ( bToGetN )
				trGetNShared.Replace(trThemeShared, true, true, true );
			else
				trThemeShared.Replace(trGetNShared, true, true, true );
			///end FIX_FAIL_TO_APPLY_THEME_FOR_DUPLICATED_NODE_DATAID_IN_THEME_WITH_BASELINE_MODE
		}
		
	}
	
	return true;
}
///---END QA80-12946 XFWIZ_SUPPORT_CHANGE_RECALCULATE_MODE

///---Sim 01-13-2009 XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE
int XFWizTheme::GetAutoUpdateMode()
{
	///---Sim 06-23-2009 NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
	//int nAutoUpdate = AU_ON_COMMAND;
	int nAutoUpdate = AU_NONE; // if no turn on autoupdate mode, defualt don't support autoupdate
	///---END NANOSIZER_WIZ_AUTO_UPDATE_SUPPORT
	TreeNode trShared = GetShared(false);
	if ( trShared )
	{
		TreeNode trAutoUpdate = trShared.GetNode(STR_NODE_NAME_AUTO_UPDATE);
		if ( trAutoUpdate )
			nAutoUpdate = trAutoUpdate.nVal;
	}
	
	return nAutoUpdate;	
}
void XFWizTheme::SetAutoUpdateMode(int nAutoUpdate)
{
	TreeNode trShared = GetShared(true);
	if ( trShared )
	{
		TreeNode trAutoUpdate = tree_check_get_node(trShared, STR_NODE_NAME_AUTO_UPDATE);
		if ( trAutoUpdate )
			trAutoUpdate.nVal = nAutoUpdate;
	}
}
///---END XFWIZ_CHANGE_PARAM_MAY_CHANGE_THEME_AND_IO_RANGE

///---Sim 01-14-2009 FIX_XFWIZ_OP_DISPLAY_THEME_NAME
void XFWizTheme::ClearThemeName()
{
	tree_set_theme_file_name(m_trThemes, GetThemeFileName(STR_THEME_NONE));
}
///---END FIX_XFWIZ_OP_DISPLAY_THEME_NAME


bool error_report_to_user_and_developer(LPCSTR lpcszErr)
{
	warning_msg_box(lpcszErr, true);
	return error_report(lpcszErr);
}
