/*------------------------------------------------------------------------------*
 * File Name:TreeEditInputData.h												*
 * Creation: YuI 6/14/2004														*
 * Purpose: OriginC Header file for InputData branch in TreeEditControl			*
 * Copyright (c) Originlab Corp. 		2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	YuI 7/23/04 v7.5103 QA70-6582 GETN_MULTILINE_TEXT_IMPLEMENTATION			*
 *	YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS				*
 *	ML 3/16/2005 MENUACTION_MENUS												*
 *  DG 3/30/05 v8.0211 VALIDATE_KILL_FOCUS										*
 *  Frank 3/30/05	TREE_EDIT_SUPPORT_MOVE_ROWS								*
 * DG 3/30/05 v8.0212 CLEAN_DUPLICATE_MORE										*
 * CPY 4/25/05 XY_DATA_RANGE_INTERACTIVE_CONTORL_CHANGE_NOTIFICATION			*
 *	YuI 10/10/05 QA70-8158 GENERAL_X_STRING_CONVENTION_TO_ACCESS_OBJECTS		*
 *	CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER								*
 *------------------------------------------------------------------------------*/

// this class has to be place here as OC cannot allow include to be in later part of
// the .h that includes this file
#include "TreeTable.h"
#define STR_BRANCH_LABEL_ATTRIB	TREE_Header

/// TD 9-2-06 QA70-9012 DYNACONTROL_MULTILINEEDIT_BUTTON
///// YuI 7/23/04 v7.5103 QA70-6582 GETN_MULTILINE_TEXT_IMPLEMENTATION
//#define STR_MULTILINE_BUTTON_ID_ATTRIB	"Button_ID"
///// end GETN_MULTILINE_TEXT_IMPLEMENTATION
/// end DYNACONTROL_MULTILINEEDIT_BUTTON

#define	EDITOR_ID			101
#define	EDITOR_INTERACTIVE_BUTTON_ID 102  // temp solution; ID repeated in Ownercombo.c of VC
#define EDIT_COL_INDEX 		1
#define LABEL_COL_INDEX		0

//---- CPY 4/25/05 XY_DATA_RANGE_INTERACTIVE_CONTORL_CHANGE_NOTIFICATION
//wParam for OnKillFocus
#define OKFW_CALL_ON_AFTER_EDIT	0x1000
//----

enum {
	TREE_NONE,
	TREE_STRUCT_CHANGED, 
	TREE_VAL_CHANGED
};


#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER	

typedef	enum	tagDATARANGECONTEXTMENU
{
	DATARANGE_REMOVE,
	
	DATARANGE_LAST_ENTRY
}	DATARANGECONTEXTMENU;

class	TreeEditDataRangeMenu	:	public	MenuBase
{
public:
	TreeEditDataRangeMenu(TreeNode& trInputData, int nRow, int nCol)	:	MenuBase()
	{
		m_trInputData = trInputData;
		Add(_L("Remove"), OnMenuItem);
	}
	//virtual
	int DoTrackPopup(int nx, int ny, HWND hWndParent)
	{
		TrackPopupMenu(0,  nx, ny, hWndParent);
		int nCmd;
		if(!GetCommand(nCmd))
			return 0;
		
		switch( nCmd )
		{
		case DATARANGE_REMOVE:
			TreeNode trParent = m_trInputData.Parent();
			trParent.RemoveChild(m_trInputData);
			return TREE_STRUCT_CHANGED;
			break;
		default:
			out_int("Should never get here, menu id = ", nCmd);
			break;
		}
		return TREE_NONE;
	}
private:
	TreeNode		m_trInputData;	
};

typedef	enum	tagINPUTDATACONTEXTMENU
{
	INPUTDATA_ADD_ALL,
	INPUTDATA_SEPARATOR_1,
	// then follow by index into plot UIDs, 1,2,3,4
	INPUTDATA_ADD_ONE,
	
	INPUTDATA_LAST_ENTRY
}	INPUTDATACONTEXTMENU;


class	TreeEditInputDataMenu	:	public	MenuBase
{
public:
	TreeEditInputDataMenu(TreeNode& trInputData, int nRow, int nCol)	:	MenuBase()
	{
		m_trInputData = trInputData;
		
		vector<uint> vPlotUIDs;
		tree_get_plot_UIDs(trInputData, vPlotUIDs);
		
		Add(_L("Add All Plots"), OnMenuItem);
		Add(NULL, OnMenuItem);//--------------- separator
		//next add individual plots from the active layer
		vector<string> vsDPdescriptions;
		if(get_layer_plots(m_vnMenuPlotIndex, vsDPdescriptions, vPlotUIDs))
		{
			for(int ii = 0; ii < m_vnMenuPlotIndex.GetSize(); ii++)
			{
				if( ii < 9 )
				{
					string strMenuItem = _L("Add");
					strMenuItem += " ";
					strMenuItem += vsDPdescriptions[ii];
					Add(strMenuItem, OnMenuItem);
				}
				else
				{
					Add(_L("More..."), OnMenuMore);
					break;
				}
			}
		}
	}
	
	void OnMenuMore(UINT nPos)
	{
		GraphLayer gl = Project.ActiveLayer();
		vector<string> arrStrings;
		if( gl )
		{
			foreach(DataPlot dp in gl.DataPlots )
			{
				DataPlotStrings dps;
				int nType = dp.GetPlotType(&dps);
				arrStrings.Add(dps.szPlotDesigDescription);
				ListInputBox(&arrStrings, "");
			}
		}
	}
	//-------- CPY 6/14/04 
	//virtual
	int DoTrackPopup(int nx, int ny, HWND hWndParent)
	{
		TrackPopupMenu(0,  nx, ny, hWndParent);
		int nCmd;
		if(!GetCommand(nCmd))
			return 0;
		switch( nCmd )
		{			
		case INPUTDATA_ADD_ALL:
			addAllPlots();
			return TREE_STRUCT_CHANGED; // change is needed
			//break;
		default:
			// adding a specific data plot
			addPlot(nCmd - INPUTDATA_ADD_ONE);
			return TREE_STRUCT_CHANGED; // change is needed
		}
		return 0;
	}
	//--------
private:
	void addAllPlots()
	{
		for(int ii=0; ii<m_vnMenuPlotIndex.GetSize(); ii++)
		{
			int nPlotIndex = m_vnMenuPlotIndex[ii];
			tree_check_add_input_data_branch_active_layer(m_trInputData, nPlotIndex);
		}
	}
	void addPlot(int nPlot)
	{
		if(nPlot >= m_vnMenuPlotIndex.GetSize())
		{
			error_report("TreeEditInputDataMenu::addPlot found wrong menu index");
			return;
		}
		int nPlotIndex = m_vnMenuPlotIndex[nPlot];
		
		tree_check_add_input_data_branch_active_layer(m_trInputData, nPlotIndex);
	}
private:
	TreeNode	m_trInputData;
	vector<int>	m_vnMenuPlotIndex; 
};
#endif //#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER	


//----------- CPY 6/16/04 QA70-6294 OC_INPUT_DATA_NODE_CLEANUP
class TreeEditInputData: public GridTreeControl
{
/// YuI 2/17/05 XYDATARANGE_PROPERTY_IMPLEMENTATION
// I do not see the reson for GetInputDataDescription
// to be prvate
// it is safe function and does not modify class members
// it may even be utility function
// for now I make it public
//private:
public:
	// this is for visualization only
	// we change color of data selector associated with current data range property
#define	DS_ACTIVATED_COLOR		3
#define	DS_DEACTIVATED_COLOR	1

	/// YuI 7/15/04 v7.5909 QA70-6688 OC_TOOLS_IMPLEMENTATION
	// we do not need these functions anymore
	//bool	activateDataSelector(const TreeNode& trInputData, int nRow)
	//{
	//	DataSelector ds;
	//	/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
	//	//	ds = get_data_selector(trInputData, true);
	//	ds = get_data_selector(m_DataRange, getSubRangeIndex(trInputData), true);
	//	/// end DATA_RANGE_MARKERS
	//	/*
	//	if( ds )
	//	{
	//		GraphObject gr = ds;
	//		gr.Line.Color.nVal = DS_ACTIVATED_COLOR;
	//	}
	//	if( ds )
	//	{
	//		DataRange dr;
	//		dr.Create(trInputData);
	//		ds.SetDataRange(dr);
	//		dr.Destroy();
	//		return true;
	//	}
	//	*/
	//	if(ds)
	//		return true;
	//	return false;
	//	}
	/// end OC_TOOLS_IMPLEMENTATION
	
	/*
	string	getDataSelectorName(DWORD dwRow)
	{
		string strDSName;
		Window* pDlgWnd = GetDialogWindow();
		DWORD dwDlgWnd = (DWORD) pDlgWnd;
		strDSName.Format("%s%s%d%s%d", DR_DATA_SELECTOR_NAME_BASE, DR_DATA_SELECTOR_NAME_SEPARATOR, dwRow, DR_DATA_SELECTOR_NAME_SEPARATOR, dwDlgWnd); 
		return strDSName;
	}
	DataSelector getDataSelector(LPCSTR lpcszName)
	{
		DataSelector dsReturn;
		GraphLayer gl = Project.ActiveLayer();
		if( gl )
		{
			DataSelector grDataSelector;
			dsReturn = gl.GraphObjects(lpcszName);
		}
		
		return dsReturn;
	}
	void	DestroyDataSelector(int nRow)
	{
		DataSelector ds;
		ds = GetDataSelector(nRow);
		if( ds )
		{
			ds.Invalidate();
			ds.Destroy();
		}
	}
	*/
	
	/// YuI 7/15/04 v7.5909 QA70-6688 OC_TOOLS_IMPLEMENTATION
	//	void	deactivateDataSelector(int nRow)
	//	{
	//		/*
	//		DataSelector ds;
	//		ds = GetDataSelector(lpcszName);
	//	if( ds )
	//	{
	//		GraphObject gr = ds;
	//		gr.Line.Color.nVal = DS_DEACTIVATED_COLOR;
	//	}
	//	*/
	//	}
	/// end OC_TOOLS_IMPLEMENTATION
public:
	/// YuI 7/15/04 v7.5909 QA70-6688 OC_TOOLS_IMPLEMENTATION
	/*
	DataSelector GetDataSelector(int nRow = -1)
	{
		DataSelector dsReturn;
		if( nRow < 0 )
			nRow = m_nEditRow;
		if(nRow < 0)
			return dsReturn;
		
		TreeNode trInputSub = get_tree_node(nRow);
		/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
		//	dsReturn = get_data_selector(trInputSub);
		int nSubRange = getSubRangeIndex(trInputSub);
		dsReturn = get_data_selector(m_DataRange, nSubRange);
		/// end DATA_RANGE_MARKERS
		return dsReturn;
	}
	*/
	/// end OC_TOOLS_IMPLEMENTATION
	
	bool	GetEditRowCol(int& nRow, int& nCol)
	{
		if( m_nEditRow >= 0 && m_nEditCol >= 0 )
		{
			nRow = m_nEditRow;
			nCol = m_nEditCol;
			return true;
		}
		
		return false;
	}
public:
	
	/// YuI 7/15/04 v7.5909 QA70-6688 OC_TOOLS_IMPLEMENTATION
	/*
	bool	OnCreateDataRangeDlg()
	{
		if(m_nEditRow < 0)
			return false;
		TreeNode trInputData = get_tree_node(m_nEditRow);
		
		return activateDataSelector(trInputData, m_nEditRow);
	}
	*/

/// end XYDATARANGE_PROPERTY_IMPLEMENTATION
	int GetInputDataDescription(TreeNode& trInputData, string& strDRDesc);

	#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER		
	/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
	// before data selector destroyed - it updates rnage it is asssociated with
	//	bool UpdateFromDataSelector(DataSelector& ds, int nEditRow, bool bDestroyDataSelector = true)
	bool UpdateTreeFromDataRange(int nEditRow)
	/// end DATA_RANGE_MARKERS
	{
		/*
		if(!ds)
		{
			error_report("UpdateFromDataSelector lost data selection, it cannot be found");
			return false;
		}
		
		DataRange dr;
		ds.GetDataRange(dr);
		if(!dr)
			return false;
		*/
		//CPY 6/19/04
		/*
		TreeNode trFromDS;
		ds.GetTree(trFromDS);
		DataRange dr;
		dr.Create(trFromDS);
		string str = dr.GetDescription();//(&dps);
		dr.Destroy();
		
		DataPlotStrings dps;
		*/
		TreeNode trEdit = get_tree_node(nEditRow);
		TreeNode trInputData = trEdit.Parent();
			

		if( trInputData )
		{
			string strOldVal;
			GetInputDataDescription(trEdit, strOldVal);
			m_DataRange.GetTree(trInputData, FALSE);
			//---- CPY 4/25/05 XY_DATA_RANGE_INTERACTIVE_CONTORL_CHANGE_NOTIFICATION
			//tree_set_attribute_to_all_nodes(trEdit, STR_CHANGED_ATTRIB, strOldVal);
			// should test if indeed changed here
			string strNewVal;
			GetInputDataDescription(trEdit, strNewVal);
			
			if(strNewVal.CompareNoCase(strOldVal) != 0) // if changed
			{
				tree_set_attribute_to_all_nodes(trEdit, STR_CHANGED_ATTRIB, strOldVal);
				tree_changed_data(trEdit, 1);
			}
			//---- end 
		}
		
		//trEdit = trFromDS;
		
		//out_str("After");
		//out_tree(trEdit);

		/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
		//	if(bDestroyDataSelector)
		//	{
		//	/*
		//	uint uID = tree_get_plot_uid(trEdit);
		//	DataPlot dp;
		//	if(uID)
		//	{
		//		dp = Project.GetObject(uID);
		//		ds.DetachDataObject(dp);
		//	}
		//	*/
		//	ds.Invalidate();
		//	ds.Destroy();
		//	}
		/// end DATA_RANGE_MARKERS

		return true;
	}
	BOOL	GetDataRange(DataRange& dr, int& nSubRange)
	{
		if(m_nEditRow < 0)
			return FALSE;
		
		TreeNode trInputData = get_tree_node(m_nEditRow, m_nEditCol);
		//nSubRange = getSubRangeIndex(trInputData);
		DataRange& drTemp = m_DataRange;
		dr = drTemp;
		nSubRange = 0;
		TreeNode trTemp = trInputData.PrevNode;
		while(trTemp.IsValid())
		{
			trTemp = trTemp.PrevNode;	
			nSubRange++;
		}
			
		return TRUE;
	}
	/// end OC_TOOLS_IMPLEMENTATION	
#endif
	
	/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
	void ClearAll()
	{
		GridTreeControl::ClearAll();
	}
	
	void OnDestroy()
	{
#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER	
		destroyDataRange();
#endif
	}
	
	void Cleanup()
	{
	}
	/// end DATA_RANGE_MARKERS
	
	/// YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS
	BOOL	OnContextUpdate();
	BOOL	DoInteractivePopUp(Window* pOwner, int nX, int nY);
	BOOL	ResolvePopUpSelectionActive(BOOL bResolve);
	BOOL	ResolvePopUpSelectionColumn(Column& col, string& strSel, BOOL bResolve);
	BOOL	DoInteractiveDlg(Window* pOwner, BOOL bModalParent, BOOL bDataRange);
	BOOL	DoXYDataRangeDlg(Window* pOwner, BOOL bModalParent);

	///DG VALIDATE_KILL_FOCUS : make kill focus more general
	/*
	BOOL OnEditorKillFocus( uint wParam = 0, uint lParam=0 )
	{
		_DBSTR("")
		_DBINT3("On OnEditorKillFocus,[Edit Row, Col] ", m_nEditRow, m_nEditCol, m_dwEditor)
		
		if(0==m_dwEditor)
		{
			if(lParam)
			{
				_DBSTR("OnEditorKillFocus Error, this should not happen.");
			}
			return TRUE;
		}
		if(m_nEditRow < 0)
		{
			_DBSTR("OnEditorKillFocus skip, not in edit mode");
			return TRUE;
		}
			
		m_flx.Row = m_nEditRow;
		m_flx.Col = m_nEditCol;
		
		int nTempRow = m_nEditRow;
		int	nTempCol = m_nEditCol;
		if(m_bOnAfterEditNeeded)
			OnAfterEdit(m_nEditRow, m_nEditCol);
			
		EditorManager	trNodeManager;
		
		DWORD dwTemp = m_dwEditor;
		m_dwEditor = 0;
		trNodeManager.DestroyEditor(dwTemp);
		
		OnDestroyEditor(nTempRow, nTempCol);
		return TRUE;
	}
	*/
	BOOL OnKillFocus( uint wParam = 0, uint lParam=0 )
	{
		_DBSTR("")
		_DBINT3("On OnKillFocus,[Edit Row, Col] ", m_nEditRow, m_nEditCol, m_dwEditor)
		
		if(m_nEditRow < 0 || m_nEditCol < 0)
		{
			_DBSTR("OnKillFocus skip, not in edit mode");
			return TRUE;
		}
		//--- CPY 4/3/05
		if(m_nEditRow >= GetRows() || m_nEditCol >= GetCols())
		{
			error_report("OnKillFocus found invalid m_nEditRow or m_nEditCol");
			return true;
		}
		//---
		m_flx.Row = m_nEditRow;
		m_flx.Col = m_nEditCol;
		
		int nTempRow = m_nEditRow;
		int	nTempCol = m_nEditCol;
		//---- CPY 4/25/05 XY_DATA_RANGE_INTERACTIVE_CONTORL_CHANGE_NOTIFICATION
		//if(m_bOnAfterEditNeeded)
		if(m_bOnAfterEditNeeded || (OKFW_CALL_ON_AFTER_EDIT & wParam))
		//----
			OnAfterEdit(m_nEditRow, m_nEditCol);
		
		DWORD dwTemp = m_dwEditor;
		if(dwTemp)
		{
			EditorManager	trNodeManager;
			m_dwEditor = 0;
			trNodeManager.DestroyEditor(dwTemp);
			OnDestroyEditor(nTempRow, nTempCol);
		}
		return TRUE;
	}
	///---end VALIDATE_KILL_FOCUS
	
	/// end VECTORIAL_NUMERIC_FUNCTIONS
	
	/// ML 3/16/2005 MENUACTION_MENUS
	void SetText(int row, int col, LPCSTR lpcszString)
	{
		EditorManager	trNodeManager;
		DWORD			dwTemp = GetCell(flexcpData, row, col);
		trNodeManager.SetText(dwTemp, lpcszString, OXVT_STRING);
		trNodeManager.SetEditorStr(m_dwEditor, lpcszString);	
	}
	
	void	SetEditText(LPCSTR lpcszString)
	{
		SetText(m_nEditRow, m_nEditCol, lpcszString);
	}
	/// end MENUACTION_MENUS

	
protected:	
	///DG VALIDATE_KILL_FOCUS
	bool IsInEditing()
	{
		return m_nEditRow >= 0;
	}
	///end VALIDATE_KILL_FOCUS

	/// YuI 7/23/04 v7.5103 QA70-6582 GETN_MULTILINE_TEXT_IMPLEMENTATION
	//---- CPY 10/06/2004 QA70-6582 v8.0145 GETN_LIST_DROP_DOWN, change ret to bool, false return to indicate no need for editor
	bool	OnBeforeCreateEditor(TreeNode& trInputData, long nRow, long nCol)
	{
		switch( trInputData.ID )
		{
		case TRGP_MULTILINE_TEXT:
		case ONODETYPE_CODE_EDITOR: /// TD 2-16-04 QA70-7368 CODE_EDITOR_IN_DIALOG
			{
				int nButtonID = -1;
				EditorManager	trNodeManager;
				string strTemp;
				trInputData.GetAttribute(STR_MULTILINE_BUTTON_ID_ATTRIB, strTemp);
				if( !strTemp.IsEmpty() )
					nButtonID = atoi(strTemp);
				
				DWORD dwTemp = GetCell(flexcpData, nRow, nCol);
				trNodeManager.SetEditorButtonID(dwTemp, nButtonID);
			}
			break;
		//---- CPY 10/06/2004 QA70-6582 v8.0145 GETN_LIST_DROP_DOWN
		// str list has flexcpData but do not create editor
		case TRGP_ENUM_LIST:
			return false;
		case TRGP_BRANCH:
			//out_str("OnBeforeCreateEditor for branch");
			return false;
		//----
		}
		return true;
	}
	/// end GETN_MULTILINE_TEXT_IMPLEMENTATION

	bool	OnAfterCreateEditor(TreeNode& trInputData, long nRow, long nCol)
	{
#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER		
		switch( trInputData.ID )
		{
		case TRGP_DATA_RANGE:
		case TRGP_XY_DATA_RANGE:/// YuI 2/17/05 XYDATARANGE_PROPERTY_IMPLEMENTATION
			//if(activateDataSelector(trInputData, nRow, true))
			if(1)
			{
				EditorManager	trNodeManager;
				DWORD	dwTemp = GetCell(flexcpData, nRow, nCol);
				//----------- CPY 6/16/04 QA70-6294 OC_INPUT_DATA_NODE_CLEANUP
				//DataRange dr;
				//dr.Create(trNode);
				//trNodeManager.SetEditorStr(m_dwEditor, dr.GetDescription());
				//dr.Destroy();

				string strLabel;
				
				GetInputDataDescription(trInputData, strLabel);
				trNodeManager.SetEditorStr(m_dwEditor, strLabel);
				//-----------
				SetCell(flexcpText, nRow, nCol, "");
				
				return true;
			}
			return false;
		case TRGP_INTERACTIVE:
			Project.EnableGUI(FALSE);
			break;
			
		}
#endif //MOVE_OPERATION_OUT_OF_SYS_FOLDER
		return true;
	}


	
	void	OnDestroyEditor(long nRow, long nCol)
	{
		/// YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS
		//TreeNode trNode = get_tree_node(nRow);
		TreeNode trNode = get_tree_node(nRow, nCol);
		/// end VECTORIAL_NUMERIC_FUNCTIONS
		
		if( trNode ) /// YuI 7/29/04: added to avoid possible runtime errors
		{
			switch( trNode.ID )
			{
			/// YuI 7/15/04 v7.5909 QA70-6688 OC_TOOLS_IMPLEMENTATION
			/*	
			case TRGP_DATA_RANGE:
				deactivateDataSelector(nRow);
				break;
			*/
			/// end OC_TOOLS_IMPLEMENTATION
			
			case TRGP_INTERACTIVE:
				Project.EnableGUI(TRUE);
				break;
			}
		}
	}
	
	/// YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS
	/*
	TreeNode get_tree_node(int nRow)
	{
		int nIndex = nRow - m_flx.FixedRows;
		return tree_get_node(m_trEdit, nIndex);
	}
	*/
public:
	///Frank 3/30/05	TREE_EDIT_SUPPORT_MOVE_ROWS
	bool	ResetTreeTable()
	{
		if(!m_trEdit)
			return false;
		
		return m_trTable.SetTree(m_trEdit, NULL, true, m_bTranspose);

	}
	///End	TREE_EDIT_SUPPORT_MOVE_ROWS
	TreeNode get_tree_node(int nRow, int nCol=-1)
	{
		TreeNode trNULL;
		if(!m_trEdit)
			return trNULL;
		
		int nRowIndex = nRow - m_flx.FixedRows;
		int nColIndex = nCol - m_flx.FixedCols;
		if(IsTreeView())
		{
			///Danice 11/10/04 SUPPORT_EMPTY_TREENODE_AND_LABEL_CONTROL
			//when m_trEdit is only leave, tree_get_node() return junk, so as to support leave shown, return m_trEdit directly
			//return tree_get_node(m_trEdit, nRowIndex);
			if(m_trEdit.GetNodeCount() < 1 && 0 == nRowIndex)
				return m_trEdit;
			else
				return tree_get_node(m_trEdit, nRowIndex);
			///END
		}
		else
		{
			return m_trTable.GetTreeNode(nColIndex, nRowIndex);
		}
	}
	/// end VECTORIAL_NUMERIC_FUNCTIONS
	///------Frank 5/26/05	GETN_EVENT_SUPPORT_GRID_VIEW
	void getViewColRow(int nTreeRow, int &nViewRow, int &nViewCol )
	{
		if(nTreeRow < 0)
			return ;
		if(IsTreeView())
		{
			nViewRow = nTreeRow;
			nViewCol = -1;
		}
		else
			m_trTable.GetTreeTableRowCol(nTreeRow, nViewRow, nViewCol);
	}
	///------End	GETN_EVENT_SUPPORT_GRID_VIEW
protected:
#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER	

	void PrepareInputDataBranch(int nNodeType, int nRow, int nId, TreeNode& trNode, double& dbRowSizeFactor)
	{
		string strComboStr = get_node_combo_str(trNode);
		int nCol = EDIT_COL_INDEX;
		EditorManager	trNodeManager;
		DWORD dwTemp = trNodeManager.New(nNodeType, nRow, nId, strComboStr);
		SetCell(flexcpData, nRow, nCol, dwTemp);
		dbRowSizeFactor *= trNodeManager.GetCellHeightFactor(dwTemp);
		string strDRDesc;
		int nLines = GetInputDataDescription(trNode, strDRDesc);
		if( nLines > 1 )
			dbRowSizeFactor += (nLines - 2);

		/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
		// createAddDataRange(trNode);
		/// end DATA_RANGE_MARKERS
	}
	
	/// YuI 07/21/06 CRASH_IN_F10_DIALOG_FOR_XYRANGE
	void SetInputDataBranchValue(int nRow, int nCol, const TreeNode& trNode, BOOL bTreeToCell = TRUE)
	/// end CRASH_IN_F10_DIALOG_FOR_XYRANGE
	{
		string strLabel;
		/// YuI 07/21/06 CRASH_IN_F10_DIALOG_FOR_XYRANGE
		/*
		GetInputDataDescription(trNode, strLabel);
		m_flx.Cell(flexcpText, nRow, nCol) = strLabel;
		*/
		EditorManager	trNodeManager;
		if( trNode.ID == TRGP_XY_DATA_RANGE || trNode.ID == TRGP_XYZ_DATA_RANGE || trNode.ID == TRGP_XY_COMPLEX_DATA_RANGE )
		{
			if( bTreeToCell )
			{
				if( trNodeManager.GetCompositeRangeString(trNode, strLabel) )
					SetCell(flexcpText, nRow, nCol, strLabel);
			}
			else
			{
				strLabel = GetCell(flexcpText, nRow, nCol);
				trNodeManager.SetCompositeRangeString(trNode, strLabel);
			}
		}
		else
		{
			GetInputDataDescription(trNode, strLabel);
			SetCell(flexcpText, nRow, nCol, strLabel);
		}
		/// end CRASH_IN_F10_DIALOG_FOR_XYRANGE
		
		/// YuI 10/10/05 QA70-8158 GENERAL_X_STRING_CONVENTION_TO_ACCESS_OBJECTS
		if( IsTreeView() )
		{
			DWORD dwTemp;
			foreach( TreeNode trChild in trNode.Children )
			{
				nRow++;
				try {
					SetCell(flexcpText, nRow, nCol, trChild.strVal);
					trNodeManager.SetText(GetCell(flexcpData, nRow, nCol), trChild.strVal, OXVT_STRING);
				} 
				catch (int nErr)
				{
					printf("SetInputDataBranchValue err at nRow = %d\n", nRow);
				}
			}
		}
		/// end GENERAL_X_STRING_CONVENTION_TO_ACCESS_OBJECTS
	}
	

/// YuI 10/28/04 INPUT_DATA_RANGE_INCAPSULATION
//	private:
protected:
	
/// end INPUT_DATA_RANGE_INCAPSULATION
	/// YuI 6/16/04 v7.5891 QA70-6556 DATA_RANGE_MARKERS
	// this function given subrange tree
	// returns index of subrange in m_DataRange
	int	getSubRangeIndex(TreeNode& trInputData)
	{
		if( !m_DataRange.IsValid() )
			return -1;
		
		vector<uint> vRangePlotUIDs;
		m_DataRange.GetPlots(vRangePlotUIDs);
		uint nTreePlotUID = tree_get_plot_uid(trInputData);
		
		for( int ii = 0; ii < vRangePlotUIDs.GetSize(); ii++ )
		{
			if( vRangePlotUIDs[ii] == nTreePlotUID )
				return ii;
		}
		
		return -1;
	}

	void	createAddDataRange(TreeNode& tr)
	{
		/*
		DataRange drTemp;
		drTemp.Create(trInputData);
		m_DataRange.Merge(drTemp); //if m_DataRange is not created yet it will. drTemp is not valid from now on (it became part of m_DataRange)
		
		m_DataRange.Invalidate();
		//Project.AddDataRange(m_DataRange);
		addDataRangeToProject(m_DataRange); // for some reason it is not working otherwise
		// this is the place where we want to hide DataSelector data ranges on all plots that are in m_DataRange
		if( m_DataRange.IsValid() )
		{
			m_DataRange.SetVisible(TRUE);
			
			/// YuI 10/26/04 NEED_TO_HIDE_INPUT_RANGE_OF_OPERATION
			string strTemp;
			TreeNode trTemp = trInputData.Parent();
			if( trTemp && trTemp.GetAttribute(STR_DATARANGE_UID_ATTRIB, strTemp) )
			{
				int	uidInputDataRange = atoi(strTemp);
				if(uidInputDataRange)
				{
					DataRange irng;
					irng = (DataRange)Project.GetObject(uidInputDataRange);
					if(!irng)
						error_report("DataRange UID stored in InputData is bad");
					else
					{
						irng.SetVisible(FALSE);
						m_nSourceDataRangeUID = uidInputDataRange;
					}
				}		
			}
			/// end NEED_TO_HIDE_INPUT_RANGE_OF_OPERATION
		}
		*/
		/*
		if( m_DataRange.IsValid() )
		{
			m_DataRange.SetTree(tr);
		}
		else
		{
			if( m_DataRange.Create(tr) && m_DataRange.IsValid() )
			{
				DataRange& dr = m_DataRange;
				Project.AddDataRange(dr);
			}
		}
		*/
		if( !m_DataRange.IsValid() )
		{
			m_DataRange.Create();
			Project.AddDataRange(m_DataRange);
		}
	
		TreeNode trDataRange = tr.FindNodeByAttribute(STR_ID_ATTRIB, TRGP_DATA_RANGE);
		if( trDataRange.IsValid() )
		{
			TreeNode trInputDataBranch = trDataRange.Parent();
			if( trInputDataBranch.IsValid() )
			{
				m_DataRange.SetTree(trInputDataBranch, FALSE);
			}
			else
			{
				m_DataRange.SetTree(trDataRange, TRUE);
			}
		}
		
		if( m_DataRange.IsValid() )
		{
			m_DataRange.SetVisible(TRUE);
			int uidInputDataRange = get_data_range_UID_in_tree(tr);
			if( uidInputDataRange > 0 )
			{
				DataRange irng;
				irng = (DataRange)Project.GetObject(uidInputDataRange);
				if(!irng)
					error_report("DataRange UID stored in InputData is bad");
				else
				{
					irng.SetVisible(FALSE);
					m_nSourceDataRangeUID = uidInputDataRange;
				}
			}
		}
	}
	
	void	destroyDataRange()
	{
		// this is the place where we want to show DataSelector data ranges on all plots that are in m_DataRange
		if( m_DataRange.IsValid() )
		{
			/*
			vector<uint> vPlotUIDs;
			m_DataRange.GetPlots(vPlotUIDs);
			for( int ii = 0; ii < vPlotUIDs.GetSize(); ii++ )
			{
				DataPlot dp;
				dp = (DataPlot) Project.GetObject(vPlotUIDs[ii]);
				if( dp )
					dp.ShowDataSelectorDataRange();
			}
			*/

			m_DataRange.Invalidate();
			m_DataRange.Destroy();
			
			
			/// YuI 10/26/04 NEED_TO_HIDE_INPUT_RANGE_OF_OPERATION
			if( m_nSourceDataRangeUID > 0 )
			{
				DataRange irng;
				irng = (DataRange)Project.GetObject(m_nSourceDataRangeUID);
				if( irng )
					irng.SetVisible(TRUE);
				m_nSourceDataRangeUID = 0;
			}
			/// end NEED_TO_HIDE_INPUT_RANGE_OF_OPERATION
		}
	}
	/// end DATA_RANGE_MARKERS
protected:
	DataRange	m_DataRange;

#else
/// YuI 11/10/06
void SetInputDataBranchValue(int nRow, int nCol, const TreeNode& trNode, BOOL bTreeToCell = TRUE);
/// end YuI
#endif //#ifdef _INTERACTIVE_CNTRL_IN_FLEX_GRID //---- CPY 10/14/06 MOVE_OPERATION_OUT_OF_SYS_FOLDER


protected:
	DWORD		m_dwEditor;
	int			m_nEditRow;
	int			m_nEditCol;
	TreeNode	m_trEdit;// local copy of ref to tree being edited
	
	int			m_nSourceDataRangeUID;// uid of data range that was hidden for the life time of m_DataRange
	/// YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS
	TreeTable	m_trTable;
	/// end VECTORIAL_NUMERIC_FUNCTIONS
	///Frank 3/30/05	TREE_EDIT_SUPPORT_MOVE_ROWS
	bool		m_bTranspose;
	///End	TREE_EDIT_SUPPORT_MOVE_ROWS
	bool		m_bOnAfterEditNeeded; /// YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS
};

///DG 1/26/05 : XFunction move into .cpp file need this, so temp move it to FunctionOrganizer.h
/*
/// YuI 01/03/2005 v7.5183 QA70-7253 VECTORIAL_NUMERIC_FUNCTIONS
#define	XFUNCTION_VARIABLE_NODE_ATTRIB	"_XFUNCTION_VAR"
/// end VECTORIAL_NUMERIC_FUNCTIONS
*/

///DG 4/1/05 CLEAN_DUPLICATE_MORE : move to new file
/*
///DG 2/5/05 
//enum { XF_MENU_ADD, XF_MENU_DEL };
enum { XF_MENU_ADD, XF_MENU_INSERT,XF_MENU_SEPARATOR, XF_MENU_DEL, XF_MENU_SEPARATOR1, XF_MENU_ENLARGE, XF_MENU_SHRINK };
class XFControlMenu : public MenuBase
{
public:
	XFControlMenu(bool bAllowDel=true, bool bIsXFunctionDialog = false) : MenuBase()
	{
		Add(_L("Add variable"), OnMenuItem);

		if(bAllowDel)
		{
			Add(_L("Insert variable"), OnMenuItem);
			Add(NULL, OnMenuItem);
			Add(_L("Delete"), OnMenuItem);
		}
		if(bIsXFunctionDialog)
		{
			Add(NULL, OnMenuItem);
			Add(_L("Enlarge Pane"), OnMenuItem);
			Add(_L("Shrink Pane"), OnMenuItem);
		}
		
	}

	int DoTrackPopup(int nx, int ny, HWND hWndParent, bool bAllowDel = true)
	{
		TrackPopupMenu(0,  nx, ny, hWndParent);
		int nCmd;
		if(!GetCommand(nCmd))
			return -1;
		
		if(!bAllowDel && nCmd > XF_MENU_ADD)
		{
			nCmd = nCmd + 3;	///because have three offset ....
		}
		return nCmd;
	}

};
///end
*/
///end CLEAN_DUPLICATE_MORE
