/*------------------------------------------------------------------------------*
 * File Name:TreeEditControl.h													*
 * Creation: CPY 6/21/2003														*
 * Purpose: OriginC Header file for general vsFlexGrid based TreeEditor			*
 * Copyright (c) Originlab Corp. 2003, 2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS							*
 *	CPY v7.5723 QA70-5376 GETNBOX_ADD_SIG_DIGITS_SUPPORT						*
 *------------------------------------------------------------------------------*/

#include "GridControl.h"

#define	EDITOR_ID			101
#define EDIT_COL_INDEX 		1
#define LABEL_COL_INDEX		0

//---- CPY v7.5723 QA70-5376 GETNBOX_ADD_SIG_DIGITS_SUPPORT
#define JUSTIFICATION_CHECKBOX	flexPicAlignCenterCenter
#define JUSTIFICATION_NUM		flexPicAlignLeftCenter	//flexPicAlignRightCenter
#define JUSTIFICATION_STR		flexPicAlignLeftCenter
//----

class TreeEditControl : public GridListControl
{
public:
	void Init(int nID, bool bFlatDlgDisplay, bool bSubBranch, PEVENT_FUNC pfn, Dialog& dlg)
	{
		m_dwEditor = 0;
		
		m_bIsFlatDialogDisplay = bFlatDlgDisplay;
		GridListControl::Init(nID, dlg);
		m_bDataReady = false;

//WAIT_BUG_FIX
//		m_dlg = dlg;
		m_pdlg = &dlg;
		m_pfnEvent = pfn;
		
		m_strNumFormat = "*"; //CPY v7.5723 QA70-5376 GETNBOX_ADD_SIG_DIGITS_SUPPORT
		
		m_flx.Rows = 0;
		m_flx.FixedRows = 0;//hide the Col heading
		m_flx.Cols = 2;
		m_flx.FixedCols = 0;//hide the Row heading

		
		m_flx.SelectionMode = flexSelectionFree;//flexSelectionByRow;			//Forces selections to span entire rows.
		m_flx.Editable = flexEDKbdMouse;
		
		//flx.GridLines = flexGridInsetHorz;
	
		m_flx.OwnerDraw = flexODContent;	//flexODOver;
		m_flx.AllowSelection = false;
		//m_flx.ExplorerBar = flexExSortShow;
		m_flx.AllowUserResizing = flexResizeColumns;
		if(!m_bIsFlatDialogDisplay)
		{
			m_flx.GridLines = flexGridNone;
			SetAlternateRowColors();
			m_flx.ExtendLastCol = true;
		}
		else
		{
			m_flx.ExtendLastCol = false;
		}
		if(bSubBranch)
		{
			m_flx.OutlineCol = 0;
			m_flx.OutlineBar = flexOutlineBarSimpleLeaf;
			m_flx.MergeCells = flexMergeSpill;
			m_bIsOutlineTree = true;
			m_bIsFlatDialogDisplay = false;
		}
		else
			m_bIsOutlineTree = false;
		
		RemoveSelection();
	}
	//----CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
	bool IsResizeOnCollapse(int nRow, int nState)
	{
		if(nRow < 0)
			return true;
		DWORD dwTemp = m_flx.RowData(nRow);
		if(dwTemp)
		{
			if((GETNBRANCH_KEEP_SIZE_ON_COLLAPSE & dwTemp) && flexOutlineCollapsed == nState)
				return false;
			if((GETNBRANCH_KEEP_SIZE_ON_EXPAND & dwTemp) && nState < flexOutlineCollapsed)
				return false;
		}
		return true;// default is to resize
	}
	//----
	void SetGridLines(int nOption)
	{
		m_flx.GridLines = nOption; 
	}
	void OnDestroy(void)
	{
		Cleanup();
	}
	
	bool Update(TreeNode& tr, bool bResize = true, bool bInit = false)
	{
		m_trEdit = tr;
		//--- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
		string strTemp;
		if(m_trEdit.GetAttribute(STR_ATTRIB_VERT_GRID_LINES, strTemp))
		{
			SetGridLines(atoi(strTemp));
		}
		if(m_trEdit.GetAttribute(STR_ATTRIB_NUMFMT, strTemp))
			m_strNumFormat = strTemp;	
		//---
		m_flx.Redraw = flexRDNone;
		if(bInit)
		{
			Cleanup();
	
			m_flx.Rows = m_flx.FixedRows;	//delete all but headers
	
			addTreeNodes(tr);
		}
	    prepareGridForDisplay(bResize, bInit);
	    
		m_flx.Redraw = flexRDBuffered;
		if(bInit)
		{
			RemoveSelection();
			m_bDataReady = true;
		}

		return true;
	}
	void Cleanup()
	{
		EditorManager	trNodeManager;
		int nCol = EDIT_COL_INDEX;
		DWORD dwTemp;
		
		for(int nRow = 0; nRow < m_flx.Rows; nRow++)
		{
			// clean up Row Data
			dwTemp = m_flx.Cell(flexcpData, nRow, nCol);
			trNodeManager.Delete(dwTemp);
			m_flx.Cell(flexcpData, nRow, nCol) = 0;
		}
	}
	//virtual 
	void ClearAll()
	{
		Cleanup();
		GridListControl::ClearAll();
	}

	void GetGridSize(int& nx, int& ny)
	{
		GridListControl::GetGridSize(nx, ny);
		if(!m_bIsFlatDialogDisplay)
		{
			ny += 3; // somehow needs spaces for the edge or something
			nx += 24;
		}
		else
		{
			ny += 3;
			nx += 21;
		}
	}		
	BOOL OnReconstructGrid(UINT wParam, UINT lParam)
	{
		BOOL bRet = FALSE;// return TRUE to indicate need for resize
		bool bNeedResize = (wParam & GRID_CHANGE_SHOW)? true : false;
		m_bDataReady = false;
		if(bNeedResize)
		{
			int nRow = m_flx.Row;
			int nCol = m_flx.Col;
			RemoveSelection();
			Update(m_trEdit, false);
			bRet = TRUE;
			if(nCol > 0 && nRow >= 0)
			{
				m_flx.Select(nRow,nCol);
			}
		}
		else
		{
			if(wParam & GRID_CHANGE_ENABLE)
				updateGridEnableSettings();
			
			//----  CPY 5/30/03 QA70-4577 EVENT_HANDLER_NEED_DIALOG_AND_VALUE_UPDATE
			if(wParam & GRID_CHANGE_VALUE)
				bRet = updateGridValues();
			if(wParam & GRID_CHANGE_SIZE)
				bRet = true;
			//---- end 
		}

		m_bDataReady = true;
		return bRet;
	}
	///// vsFlexGrid events
	BOOL OnSetFocus()
	{
		m_flx.Col=1;
		m_flx.Row=0;
		return true;
	}
	
	BOOL OnEditorKillFocus( uint wParam = 0, uint lParam=0 )
	{
		_DBINT("On OnEditorKillFocus, ", m_dwEditor)
		
		if(0==m_dwEditor)
		{
			if(lParam)
			{
				_DBSTR("OnEditorKillFocus Error, this should not happen.");
			}
			return TRUE;
		}
		if(lParam && m_dwEditor != lParam)
		{
			// debug
			//printf("m_dwEditor=%X, lParam = %X\n", m_dwEditor, lParam);
		}
		
		m_flx.Row = m_nEditRow;
		m_flx.Col = m_nEditCol;
		
		OnAfterEdit(m_nEditRow, m_nEditCol);
			
		
		EditorManager	trNodeManager;
		trNodeManager.DestroyEditor(m_dwEditor);
		m_dwEditor = 0;
		
		return TRUE;
	}

	void OnDrawCell(UINT hDC, int nRow, int nCol, int nLeft, int nTop, int nRight, int nBottom, BOOL* pDone)
	{
		DWORD	dwTemp = m_flx.Cell(flexcpData, nRow, nCol);
		if(dwTemp)
		{
			EditorManager	trNodeManager;
			BOOL bSelected = nRow == m_flx.RowSel && nCol == m_flx.ColSel? true:false;
			RECT rect;
			SetRect(rect, nLeft, nTop, nRight, nBottom);
			//InflateRect(&rect, -m_nHaldGridLineWidth, -m_nHaldGridLineWidth);
			rect.right -= m_nHaldGridLineWidth;
			rect.bottom -= m_nHaldGridLineWidth;
			//_DBINT("in Drawcell, bSelected=", bSelected)
			*pDone = trNodeManager.DrawCell(dwTemp, hDC, &rect, bSelected); 
			return;
		}
		*pDone = FALSE;// let VSFlex grid to finish drawing cell
	}
	void OnComboCloseUp(int nRow, int nCol, BOOL* pFinishEdit)
	{
		TreeNode trNode = get_tree_node(nRow);
		if(trNode && (TRGP_ENUM_COMBO == trNode.ID || TRGP_STR_LIST ==trNode.ID) )
		{
			*pFinishEdit = true;
		}
	}
	void OnBeforeMouseDown(short nButton, short nShift, float X, float Y, BOOL* pCancel)
	{
		int iRow = m_flx.MouseRow;
		int iCol = m_flx.MouseCol;
		
		OnEditorKillFocus();
		
		if(iCol == 0 && !m_bIsOutlineTree) // label col
		{
			_DBINT("Quite at ", iRow)
			RemoveSelection();
			*pCancel = TRUE;
			return;
		}
		TreeNode trNode = get_tree_node(iRow);
		if(!trNode)
		{
			out_int("no tree node at row = ", iRow);
			*pCancel = TRUE;
			return;
		}
		
		if(iCol == 0 && trNode.ID != TRGP_BRANCH)
		{
			RemoveSelection();
			*pCancel = TRUE;
			return;
		}
		GridListControl::OnBeforeMouseDown(nButton, nShift, X, Y, pCancel);
	}
	void OnButtonClick(int nRow, int nCol)
	{
		TreeNode trNode = get_tree_node(nRow);
		PEVENT_FUNC pfn = getEventHandler(trNode);
		
		if(pfn && trNode.IsValid())
		{
			if(pfn(m_trEdit, nRow, trNode.ID, *m_pdlg)) //CPY 5/30/03 QA70-4577 EVENT_HANDLER_NEED_DIALOG_AND_VALUE_UPDATE, add *this
			{
				string strOldVal = m_flx.Cell(flexcpText, nRow, nCol);
				m_flx.Cell(flexcpText, nRow, nCol) = trNode.Text;
				if(updateGridColWidth(nRow, strOldVal))
					PostDlgMessage(WM_USER_RECONSTRUCT, GRID_CHANGE_SIZE);
			}
		}
				
	}
	void OnRowColChange()
	{
		if(!m_bDataReady)
			return;
		
		int nRow = m_flx.Row;
		TreeNode trNode = get_tree_node(nRow);
		if(trNode)
		{
			switch(trNode.ID)
			{
			case TRGP_CHECK:
			case TRGP_STR_LIST:
			case TRGP_COLOR:
			case TRGP_RANGE:
			case TRGP_STR_BUTTON:
				break;
			default:
				DWORD	dwTemp = m_flx.Cell(flexcpData, nRow, EDIT_COL_INDEX);
				if(0 == dwTemp) // if there is a Propty object, then we should pass this along, for now, lets just ignore them
				{
					m_flx.EditCell();
					m_flx.EditSelStart = 0;
					m_flx.EditSelLength = 30000;  // try to select all
				}
				break;
			}
		}
	}
	void OnValidateEdit(int nRow, int nCol, BOOL* pCancel)
	{
		string strEdit = m_flx.EditText;
		DWORD	dwTemp = m_flx.Cell(flexcpData, nRow, nCol);
		if(dwTemp)
		{
			EditorManager	trNodeManager;
			if(!trNodeManager.ValidateEdit(dwTemp, strEdit))
				*pCancel = TRUE;
	
			return;
		}
	
		TreeNode trNode = get_tree_node(nRow);
		if(trNode)
		{
			if(is_node_need_numeric_validation(trNode))
			{
				if(!is_numeric(strEdit))
					*pCancel = true;
			}
		}
	}
	void OnBeforeEdit(long nRow, long nCol, BOOL* pCancel)
	{		
		if(nCol != EDIT_COL_INDEX)
		{
			*pCancel = TRUE;
			return;
		}
		
		TreeNode trNode = get_tree_node(nRow);
		if(trNode)
		{
			if(trNode.Enable == 0 || TRGP_BRANCH == trNode.ID)
			{
				*pCancel = TRUE;
				return;
			}
		}
		DWORD	dwTemp = m_flx.Cell(flexcpData, nRow, nCol);
		if(dwTemp)
		{
			*pCancel = TRUE;
			if(m_dwEditor) // busy, possible due to come messaging problem
			{
				_DBINT("OnBeforeEdit, should be NULL, but has ", m_dwEditor)
				return;
			}
			if(nRow != m_flx.MouseRow || nCol != m_flx.MouseCol)
			{
				_DBSTR("Custom Editor must be initiated from mouse click only")
				return;
			}

			RECT rect;
			GetCellRect(nRow, nCol, rect);
			string strFontName = m_flx.Cell(flexcpFontName, nRow, nCol);
			int nFontSize = m_flx.Cell(flexcpFontSize, nRow, nCol);
			EditorManager	trNodeManager;
			string strCombo, strEditMask;
			m_flx.ComboSearch = trNodeManager.GetEditInfo(dwTemp, strCombo, strEditMask);
			m_flx.ComboList = strCombo;
			m_flx.EditMask = strEditMask;
			//	DWORD	CreateEditor(DWORD dwData, const RECT * lpcRect, HWND hwndOwner, UINT nControlID=100, LPCTSTR lpcszFontName=NULL, int nFontSize=0);
			m_dwEditor = trNodeManager.CreateEditor(dwTemp, &rect, GetDlgSafeHwnd(), EDITOR_ID, strFontName, nFontSize);
			int nOK = trNodeManager.StartEdit(dwTemp, nRow);
			if(m_dwEditor)
			{
				_DBINT("Start Edit returns ", nOK)
			}
			else
			{
				*pCancel = FALSE; // no editor created, allow grid's own editor
			}
			m_nEditRow = nRow;
			m_nEditCol = nCol;
			return;
		}
		else
		{
			string str = m_flx.EditMask;
			if(!str.IsEmpty())
			{
				str.Empty();
				m_flx.EditMask = str;
			}
		}
		
		if(nCol != EDIT_COL_INDEX || NULL == trNode) // col(0) parameter labels, cannot edit 
		{
			*pCancel = TRUE;
			return;
		}
		
		m_flx.ComboList = get_node_combo_str(trNode);
	}

	//virtual
	void OnAfterEdit(int nRow, int nCol)
	{
		//Profiler jj;
		
		GridListControl::OnAfterEdit(nRow, nCol);//m_bMouseDownToggleCheck = false;//---- CPY 5/20/03 CHECK_BOX_CLICK_OUTSIDE_CHECK_TO_TOGGLE
		bool	bCheckCellSizeChange = false; // only certain cell type need checking CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
		TreeNode trNode = get_tree_node(nRow);
		if(trNode)
		{
			string strOldVal = trNode.Text;
			int nVal;
			DWORD	dwTemp = m_flx.Cell(flexcpData, nRow, nCol);
			if(dwTemp)
			{
				EditorManager	trNodeManager;
				BOOL bModified;
				if(m_dwEditor)
					bModified = trNodeManager.AfterEdit(dwTemp);
				else if(TRGP_RANGE == trNode.ID)
				{
					string strCellText = m_flx.Cell(flexcpText, nRow, nCol);
					bModified = trNodeManager.AfterEdit(dwTemp, AFTER_EDIT_USE_STR, strCellText);
					
					string	strNew = trNodeManager.GetText(dwTemp);
					m_flx.Cell(flexcpText, nRow, nCol) = strNew;
					bCheckCellSizeChange = true;//CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
				}
				else // no editor, then possible to be using grid's combo
				{
					bModified = trNodeManager.AfterEdit(dwTemp, m_flx.ComboIndex);
					bCheckCellSizeChange = true;//CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
				}

				_DBINT("After Edit returns ", bModified)
							
				trNode.Text = trNodeManager.GetText(dwTemp);
			}
			else
			{
				switch(trNode.ID)
				{
				case TRGP_CHECK:
					nVal = m_flx.Cell(flexcpChecked, nRow, nCol);
					trNode.nVal = flexUnchecked == nVal? 0:1;
					break;
				default:
					trNode.Text = m_flx.Cell(flexcpText, nRow, nCol);
					bCheckCellSizeChange = true;//CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
					break;
				}
			}
			
			// data changed, OK button should be enabled, which might be disabled by
			// apply button
			string strNewVal = trNode.Text;
			if(strNewVal.Compare(strOldVal) != 0)
			{
				PEVENT_FUNC pfn = getEventHandler(trNode);
				uint wParam = 0;
				if(pfn)
				{
					// we need to know if event handler has changed any .Show 
					vector<int> vSaveShows; tree_get_shows(m_trEdit, vSaveShows);
					vector<int> vSaveEnables; tree_get_enables(m_trEdit, vSaveEnables);
					vector<string> vSaveValues; tree_get_values(m_trEdit, vSaveValues);//CPY 5/30/03 QA70-4577 EVENT_HANDLER_NEED_DIALOG_AND_VALUE_UPDATE
					if(pfn(m_trEdit, nRow, trNode.ID, *m_pdlg))
					{
						//out_str("need to update");
						vector<int> vShows; tree_get_shows(m_trEdit, vShows);
						wParam = is_same(vShows, vSaveShows)? 0 : GRID_CHANGE_SHOW;
						
						vector<int> vEnables; tree_get_enables(m_trEdit, vEnables);
						if(!is_same(vEnables, vSaveEnables))
							wParam |= GRID_CHANGE_ENABLE;
						
						int nChanges = tree_update_changes(m_trEdit, vSaveValues);
						if(nChanges > 0)
							wParam |= GRID_CHANGE_VALUE;
					}
				}
				if(bCheckCellSizeChange && !(wParam & GRID_CHANGE_VALUE) && !(wParam & GRID_CHANGE_SHOW))
				{
					if(updateGridColWidth(nRow, strOldVal))
						wParam |= GRID_CHANGE_SIZE;
				}
				
				if(wParam)
					PostDlgMessage(WM_USER_RECONSTRUCT, wParam);
			}
		}
	}
	
private:
	PEVENT_FUNC getEventHandler(const TreeNode& trNodeRow)
	{
		//--- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
		if(trNodeRow)
		{
			string strTemp;
			if(trNodeRow.GetAttribute(STR_ATTRIB_HANDLER, strTemp) && !strTemp.IsEmpty())
			{
				DWORD dwTemp = atoi(strTemp);
				PEVENT_FUNC pfn = (PEVENT_FUNC)dwTemp;
				if(pfn)
					return pfn;
				return NULL; // if handler is set but not valid, we can diable generic handler 
			}
		}
		PEVENT_FUNC temp_pEventFunc = m_pfnEvent;// wait until we can call member function pointer directly
		TreeNode trNode = m_trEdit;

		if(trNode)
			return temp_pEventFunc;
		
		return NULL;
	}
	//------- CPY 5/15/03 v7.0585 QA70-4477 TREE_BRANCH_SUPPORT
	bool addTreeNodes(TreeNode& tr, int nLevel = -1)
	{
		int nCnt = tr.GetNodeCount();
		if(nCnt < 1) // no children, add leaf
			addTreeRow(tr, nLevel);
		else
		{
			if(nLevel >= 0)
				addTreeRow(tr, nLevel, true);
			
			foreach(TreeNode cNode in tr.Children)
			{
				addTreeNodes(cNode, nLevel+1);
			}
		}
		return true;
	}
	void addTreeRow(TreeNode& cNode, int nLevel, bool bIsBranch = false)
	{
		string strTemp;
		if(!cNode.GetAttribute(STR_LABEL_ATTRIB, strTemp))
			strTemp = cNode.tagName;
		
		if(!bIsBranch)
			strTemp += "\t";
		
		
		m_flx.AddItem(strTemp);
		if(m_bIsOutlineTree && nLevel >= 0)
		{
			int nRow = m_flx.Rows - 1;
			m_flx.IsSubtotal(nRow) = true;
			m_flx.RowOutlineLevel(nRow) = nLevel;
		}
	}
	//------- end TREE_BRANCH_SUPPORT
	void prepareGridForDisplay(bool bResize = true, bool bInit = false)
	{
//		out_str("enter prepareGridForDisplay");
		// make all font size bigger
		double fSizeFactor = 1.00;
		double fRowSizeFactor = fSizeFactor * 1.3;
		double fTempFactor;
		m_flx.Row = 0;
		m_flx.Col = 0;
		int nSize = m_nFontSize;//flx.CellFontSize;
		
		nSize = 0.5 + nSize * fSizeFactor;
		
		vector<int> vnBranchRowsToExpand;//---- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
		for(int ii = 0; ii < m_flx.Rows; ii++)
		{
			fTempFactor = fRowSizeFactor;
			if(prepareEditCell(ii, fTempFactor, vnBranchRowsToExpand))
				m_flx.RowHeight(ii) = 0.5 + m_nRowHeight * fTempFactor;
			else
				m_flx.RowHeight(ii) = 0;
		}
		if(bInit && m_bIsOutlineTree)
		{
			m_flx.Outline(0);// collaps the tree
			//---- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
			for(int jj = 0; jj < vnBranchRowsToExpand.GetSize(); jj++)
				m_flx.IsCollapsed(vnBranchRowsToExpand[jj]) = flexOutlineExpanded;	
			//----
		}
		
		if(bResize)
		{
			//ResizeCols(6.0, 3.0);
			resizeGrid()
		}
		updateGridEnableSettings();
	}
	void resizeGrid()
	{
		ResizeCols(6.0, 3.0);
	}

	void updateGridEnableSettings()
	{
		uint nColorDisable =  RGB(127, 127, 127);

		for(int ii = 0; ii < m_flx.Rows; ii++)
		{
			TreeNode trNode = get_tree_node(ii);
			if(trNode && trNode.Enable >= 0)
			{
				for(int nC = 0; nC < m_flx.Cols; nC++)
				{
					m_flx.Cell(flexcpForeColor, ii, nC) = trNode.Enable > 0? 0:nColorDisable;
				}
	
			}
		}
	}
	bool updateGridColWidth(int nRow, const string& strOldVal) // -1 to scan all rows
	{
		if(nRow < 0)
			return false; // not supported yet
		int nOldLength = strOldVal.GetLength();
		string str = m_flx.Cell(flexcpText, nRow, EDIT_COL_INDEX);
		int nNewLength = str.GetLength();
		if(nOldLength < 1) nOldLength = 1;
		if((nNewLength - nOldLength) > nOldLength * 0.2 || (nOldLength - nNewLength) > nOldLength * 0.5 )
		{
			resizeGrid();
			return true;
		}
		return false;
	}

	// return flase if cell should be hidden
	bool prepareEditCell(int nRow, double& dbRowSizeFactor, vector<int>& vnBranchRowsToExpand)
	{
		int nCol = EDIT_COL_INDEX;
		m_flx.Row = nRow;
		m_flx.Col = nCol;// last col need to be right aligned
		static int s_ID = 1;
	
		// next we need to setup edit cell according to tree
		
		TreeNode trNode = get_tree_node(nRow);
		
		EditorManager	trNodeManager;
		DWORD	dwTemp;
		string strTemp;
		
		if(trNode)
		{
			int nNodeType = trNode.ID;
			switch(nNodeType)
			{
			case TRGP_BRANCH:
				// default to collaps
				//flx.IsCollapsed(nRow) = flexOutlineSubtotals;
				//---- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
				if(trNode.GetAttribute(STR_ATTRIB_BRANCH, strTemp))
				{
					dwTemp = atoi(strTemp);
					if(dwTemp)
						m_flx.RowData(nRow) = dwTemp;
					if(dwTemp & GETNBRANCH_OPEN)
						vnBranchRowsToExpand.Add(nRow);
				}
				//---- end QA70-5061 ADD_DISPLAY_OPTIONS
				break;
			case TRGP_CHECK:
				m_flx.Cell(flexcpPictureAlignment, nRow, nCol) = JUSTIFICATION_CHECKBOX;//flexPicAlignCenterCenter	;
				break;
			case TRGP_STR_LIST:
			case TRGP_COLOR:
			case TRGP_RANGE:
				dwTemp = trNodeManager.New(nNodeType, nRow, s_ID++, get_node_combo_str(trNode));
				m_flx.Cell(flexcpData, nRow, nCol) = dwTemp;
				dbRowSizeFactor *= trNodeManager.GetCellHeightFactor(dwTemp);
				break;
			case TRGP_DOUBLE:
				m_flx.Cell(flexcpAlignment, nRow, nCol) = JUSTIFICATION_NUM;//flexAlignCenterCenter;
				break;
			default:
				m_flx.Cell(flexcpAlignment, nRow, nCol) = JUSTIFICATION_STR//flexAlignCenterCenter;
			}
			
			setGridCellValue(nRow, nCol, trNode);
			//--- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
			if(trNode.GetAttribute(STR_ATTRIB_LABEL_COLOR, strTemp))
			{
				DWORD dwColor = atoi(strTemp);
				m_flx.Cell(flexcpForeColor, nRow, LABEL_COL_INDEX) = dwColor;
			}
			if(trNode.GetAttribute(STR_ATTRIB_BKGRND_COLOR, strTemp))
			{
				DWORD dwColor = atoi(strTemp);
				m_flx.Cell(flexcpBackColor, nRow, LABEL_COL_INDEX) = dwColor;
			}			
			//---
		}
//		flx.ComboSearch = flexCmbSearchNone;
//		flx.CellAlignment = flexAlignLeftTop; //flexAlignRightCenter;
		if(trNode.IsValid() && trNode.Show == 0)
			return false;
		
		if(m_bIsFlatDialogDisplay)
			m_flx.Cell(flexcpBackColor, nRow, nCol) = RGB(255,255,255);
		return true;
	}
	//--- CPY 5/30/03 QA70-4577 EVENT_HANDLER_NEED_DIALOG_AND_VALUE_UPDATE
	bool updateGridValues()  // ret true to indicate dialog needs resize to fit, grid size has changed
	{
		bool bRet = false;
		for(int ii = 0; ii < m_flx.Rows; ii++)
		{
			TreeNode trNode = get_tree_node(ii);
			if(tree_node_changed(trNode))
			{
				string strOldVal = m_flx.Cell(flexcpData, ii, EDIT_COL_INDEX);
				setGridCellValue(ii, EDIT_COL_INDEX, trNode);
				if(updateGridColWidth(ii, strOldVal))
					bRet = true;
			}
		}
		tree_remove_attribute(m_trEdit, STR_CHANGED_ATTRIB);
		return bRet;
	}
	//--- end CPY 5/30/03 QA70-4577 
	void setGridCellValue(int nRow, int nCol, const TreeNode& trNode)
	{
		EditorManager	trNodeManager;
		DWORD	dwTemp;
		int nNodeType = trNode.ID;
		switch(nNodeType)
		{
		case TRGP_BRANCH:
			// default to collaps
			//flx.IsCollapsed(nRow) = flexOutlineSubtotals;
			break;
		case TRGP_CHECK:
			m_flx.Cell(flexcpChecked, nRow, nCol) = trNode.nVal>0? flexChecked : flexUnchecked;
			break;
		case TRGP_STR_LIST:
		case TRGP_COLOR:
		case TRGP_RANGE:
			dwTemp = m_flx.Cell(flexcpData, nRow, nCol);
			if (nNodeType == TRGP_RANGE)
				trNodeManager.SetText(dwTemp, trNode.Text, OXVT_STRING);
			else
				trNodeManager.SetText(dwTemp, trNode.Text);
			m_flx.Cell(flexcpText, nRow, nCol) = trNodeManager.GetText(dwTemp, FALSE); // get display text
			break;
		case TRGP_DOUBLE:
			{
				//---- CPY v7.5723 QA70-5376 GETNBOX_ADD_SIG_DIGITS_SUPPORT
				// we have to go through this to avoid 1.0 displayed as 1. by generic storage in XML for doubles
				//double val = trNode.dVal;
				//string strVal = val;
				//m_flx.Cell(flexcpText, nRow, nCol) = szTemp;
				char szTemp[MAXLINE];
				DoubleToStr(trNode.dVal, szTemp, MAXLINE, m_strNumFormat);
				m_flx.Cell(flexcpText, nRow, nCol) = szTemp;
				//---- end GETNBOX_ADD_SIG_DIGITS_SUPPORT
			}
			break;
		default:
			m_flx.Cell(flexcpText, nRow, nCol) = trNode.Text;
		}
	}	
	
	TreeNode get_tree_node(int nRow)
	{
		int nIndex = nRow - m_flx.FixedRows;
		return tree_get_node(m_trEdit, nIndex);
	}

private:
	Dialog*		m_pdlg;
	PEVENT_FUNC	m_pfnEvent;
	TreeNode	m_trEdit;// local copy of ref to tree being edited
	int			m_nEditRow;
	int			m_nEditCol;
	bool 		m_bDataReady;
	bool		m_bIsFlatDialogDisplay;// trying to similate dialog look using gray grid lines etc
	bool		m_bIsOutlineTree;
	DWORD		m_dwEditor;
	string		m_strNumFormat;
};
