/*------------------------------------------------------------------------------*
 * File Name:PlotListControl.h													*
 * Creation: CPY 6/28/2003														*
 * Purpose: OriginC Class for Select Columns for Plotting dialog				*
 * Copyright (c) Originlab Corp. 2003, 2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	CPY 8/19/03 HIDE_STYLE_INFO_COL												*
 *	RVD 8/25/2003 QA70-5042 v7.0674 DATAPLOT_LIMITS_DISPLAY						*
 *	RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY								*
 *	CPY 11/15/03 QA70-5434-P17 v7.5756 MATRIX_BECOME_LOOSE_DATASET				*
 *------------------------------------------------------------------------------*/

#ifndef _PLOT_LIST_CONTROL_H
#define _PLOT_LIST_CONTROL_H

#include <TreeEditor.h> // We need this for the PlotList Control which is using the TreeEditor
#include <oPlotIDs.h> // IDM_PLOT_* ids and related const

//#define COL_INDEX_STYLE_INFO 2		//CPY 8/19/03 HIDE_STYLE_INFO_COL	
////////////////////////////////////////////////////////
// class PlotListControl - DataPlot List (DP)
// this is typically used to hold a Layer Content (DataPlots)    
////////////////////////////////////////////////////////     
class PlotListControl : public GridListControl
{
public:
	void Init(int nID, Dialog& dlg)
	{
		GridListControl::InitControl(nID, dlg);
		m_dpEditor = dlg.GetItem(nID);
		m_flx = m_dpEditor.GetActiveXControl();
		m_nActiveLayer = 0;
		SetFont();
		// testing, maybe not needed
		//m_flx.FixedCols = 1;//Row heading for drag and drop to reorder
		//m_flx.Cols = 2; // test, will need to be dynamic later, 
		//m_flx.FormatString = "|Plot|Range|";
		
		//Tree		tr;
		//make_test_tree_2(tr);	
		
		m_nLastSelRow = m_nLastSelCol = -1;
	}
	/// RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY
	//void OnReady(bool bMakeNewPlots, bool bTemplateLib)
	void OnReady(bool bMakeNewPlots, bool bTemplateLib, DWORD dwView = 0)
	/// end PLOT_RANGE_APPLY
	{
		//HideCol(COL_INDEX_STYLE_INFO);//CPY 8/19/03 HIDE_STYLE_INFO_COL	
		
		int nRow = findLayerRow(m_nActiveLayer);
		if(nRow < 0)
			nRow = findLayerRow();
		m_flx.Row = nRow;
		//if(bTemplateLib)
		/// RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY
		//if(bMakeNewPlots)
		//	m_dpEditor.View = 0;
		//else
		//	m_dpEditor.View = DPEDTVIEW_HIDE_STYLEHOLDERS;
		m_dpEditor.View = dwView;

		if( !bMakeNewPlots )
			m_dpEditor.View |= DPEDTVIEW_HIDE_STYLEHOLDERS;
		/// end PLOT_RANGE_APPLY
	}
	bool	SetTree(TreeNode &tr)
	{
		if (tr && tr.DataPlots.IsValid())
		{
			string strTemp;
			DWORD dwView = m_dpEditor.View;
			vector<byte> vnSaveBranchs;
			int nNumBranches = GetCollapsed(vnSaveBranchs);
			m_dpEditor.Root = tr.DataPlots;
			if(nNumBranches)
				SetCollapsed(vnSaveBranchs);
			m_dpEditor.View = dwView;
			if(tr.DataPlots.GetAttribute(STR_ACTIVE_LAYER, strTemp) && !strTemp.IsEmpty())
				m_nActiveLayer = atoi(strTemp);	
			return true;
		}
		return false;
	}
	bool	GetTree(TreeNode &tr)
	{
		if (tr.DataPlots.IsValid())
			tr.DataPlots.Replace(m_dpEditor.Root);
		else
			tr.AddNode(m_dpEditor.Root);
		return true;
	}
	//---- CPY 9/9/03 WKS_1000_COLS_TOO_SLOW
	bool IsSelSameRow() // when sel change, we need to check if same row selected to prevent event handling
	{
		if(m_flx.Row == m_nLastSelRow)
			return true;
		
		m_nLastSelRow = m_flx.Row;
		m_nLastSelCol = m_flx.Col;
		return false;
	}
	//----
	void OnSelChange(PlotTypeListControl &listPlotTypes, ColListControl& listCols)
	{
		int nSelType = GetSelectedType();
		if(nSelType > DPL_INVALID)
		{
			if(listPlotTypes.OnChangeTarget(nSelType, listCols))
			{
				Tree trTemp;
				if(GetSelectedNode(trTemp))
				{
					string strTemp;
					if(trTemp.GetAttribute(STR_LAYER_TYPE_BITS, strTemp))
					{
						listPlotTypes.SetTargetLayerType(atoi(strTemp));
					}
				}
			}
		}
	}
	//---- CPY 9/25/03 v7.5707 EDIT_PLOT_SHOW_HIGHLIGHT_IN_WKS_LIST
	void OnWksSelChange(ColListControl& listCols)
	{
		int nLayerRow = -1;
		GetSelectedType(&nLayerRow);
		//EndEdit(listCols);
		if(nLayerRow >= 0)
			SelRow(nLayerRow);
	}
	void OnRemove(int nRowToSel = 0)
	{
		SelRow(nRowToSel);
	}
	//----
	bool AddDataPlots(TreeNode& trDPList, BOOL bReplace)
	{
		//if (trDPList && trDPList.DataPlots.IsValid())
		//	return m_dpEditor.Add(trDPList.DataPlots);
		if (trDPList)
		{
			TreeNode	trLayer = trDPList.FirstNode;
			if (trLayer)
			{
				/// RVD 8/25/2003 QA70-5042 v7.0674 DATAPLOT_LIMITS_DISPLAY
				//return m_dpEditor.Add(trLayer, bReplace);
				vector<uint>		arrLayerRows;
				if( m_dpEditor.Add(trLayer, bReplace, &arrLayerRows) )
				{
					updateLayerRescale(arrLayerRows, trLayer);
					return true;
				}
				/// end DATAPLOT_LIMITS_DISPLAY
			}
		}
		return false;
	}
	
	bool AddDataPlots(TreeNode& trDPList, vector<uint> &vnPlotIDs)
	{
		//PROFILE_HRGLASS
		//if (trDPList && trDPList.DataPlots.IsValid())
		//	return m_dpEditor.Add(trDPList.DataPlots);
		if (trDPList)
		{
			TreeNode	trLayer = trDPList.FirstNode;
			if (trLayer)
			{
				/// RVD 8/25/2003 QA70-5042 v7.0674 DATAPLOT_LIMITS_DISPLAY
				//return m_dpEditor.Add(trLayer, vnPlotIDs);
				vector<uint>		arrLayerRows;
				if( m_dpEditor.Add(trLayer, vnPlotIDs, &arrLayerRows) )
				{
					updateLayerRescale(arrLayerRows, trLayer);
					return true;
				}
				/// end DATAPLOT_LIMITS_DISPLAY
			}
		}
		return false;
	}
	bool StartEdit(ColListControl& listCols, PlotTypeListControl &listPlotTypes, WksListControl& listWks)
	{
		string			strGraphLayerName, strGraphGroupName, strWksPageName, strWksLayerName, strColPattern;
		int				nPlotType = 0;
		DWORD			dwAuxTypeInfo = 0;
		vector<uint>	vnColDesignations;
		vector<string>	vsColNames;
		
		DWORD			dwLTPlotInfo = 0;
		BOOL bOK = m_dpEditor.BeginRowEdit(strGraphLayerName, strGraphGroupName, strWksPageName, strWksLayerName, vnColDesignations, vsColNames, nPlotType, dwAuxTypeInfo, dwLTPlotInfo, strColPattern);
		vector<string> vsWksNames;
		if(bOK)
		{
			listCols.OnStartEditPlot(nPlotType, dwAuxTypeInfo, strColPattern);
			int nPageType = getPageType(strWksPageName, strWksLayerName, vsColNames);
			if(EXIST_WKS == nPageType || EXIST_MATRIX == nPageType)
			{
				vsWksNames.Add(strWksPageName);// ignore layer for now, otherwise we need for construct Book1!Sheet2 here
				if(EXIST_MATRIX == nPageType)
				{
					//--- CPY 11/15/03 QA70-5434-P17 v7.5756 MATRIX_BECOME_LOOSE_DATASET
					//	vsColNames.SetSize(0);
					//	vsColNames.Add(strWksPageName);
					//if we are coming from Layer Contents, then vsColNames should be ignore and only strWksPageName should be used
					//but if we are coming here when creating new plot, then strWksPageName is not used and matrix is treated same way as loose dataset
					string strColName = vsColNames[0];
					vsColNames.SetSize(0);
					if(strColName.IsEmpty())
						vsColNames.Add(strWksPageName);
					else
					{
						vsColNames.Add(strColName);
						vsWksNames = vsColNames;
					}	
					//--- end MATRIX_BECOME_LOOSE_DATASET
				}
			}
			else// loose data and function plots, wksname is empty, but we use col names
			{
				vsWksNames = vsColNames;
				//vsColNames.SetSize(0);
			}
			listWks.OnStartEdit(vsWksNames, nPageType);//CPY 9/25/03 v7.5707 EDIT_PLOT_SHOW_HIGHLIGHT_IN_WKS_LIST
			listCols.UpdateList(vsWksNames, false, nPageType);
			listCols.ApplyColDesignations(vsColNames, vnColDesignations);
			listPlotTypes.OnStartEditPlot(strWksPageName, nPlotType, dwAuxTypeInfo, dwLTPlotInfo);
			return true;
		}
		return false;
	}
	
	bool	EndEdit(ColListControl& listCols)
	{
		listCols.OnEndEditPlot();
		return m_dpEditor.EndRowEdit();
	}
	int	GetSelectedType(int* lpnLayerRow = NULL)
	{
		UINT	dw1, dw2;
		vector<uint>		vnRows;
		int	nRowSel = -1;
		if (GetSelRows(vnRows) && 1 == vnRows.GetSize())
		{
			nRowSel = vnRows[0];
			int		nRowSelType = getRowType(nRowSel);
			if(lpnLayerRow)
			{
				*lpnLayerRow = -1;
				for(int iRow = nRowSel; iRow > 0; iRow--)
				{
					if(DPL_LAYER == getRowType(iRow))
					{
						*lpnLayerRow = iRow;
						break;
					}
				}
			}
			return nRowSelType; 
		}
		return -1;
	}
	bool	GetSelectedNode(TreeNode &trNode)
	{
		vector<uint>		vnRows;
		if (GetSelRows(vnRows) && 1 == vnRows.GetSize())
		{
			// use the first only:
			LONG		nRow = vnRows[0];
			
			return m_dpEditor.GetTreeNode(trNode, nRow);
		}
		
		return false;
	}
	bool	GetTreeNode(TreeNode &trNode, int nRow)
	{
		if( m_dpEditor )
			return m_dpEditor.GetTreeNode(trNode, nRow);
		
		return false;

	}
	bool	SetTreeNode(TreeNode &trNode, int nRow)
	{
		if( m_dpEditor )
			return m_dpEditor.SetTreeNode(trNode, nRow);
		
		return false;

	}
	bool	HasStyleHolders()
	{
		if (m_dpEditor)
		{
			return m_dpEditor.GetInfo(TREDTINFOOPTS_HAS_STYLE_HOLDERS);
		}
		
		return false;
	}
	//---- CPY 9/15/03 OK_BUTTON_DISABLE_WHEN_ADDING_NEW_PLOT
	bool HasDataPlots()
	{
		return findDataPlotRow() > 0? true:false;
	}
	//---- end OK_BUTTON_DISABLE_WHEN_ADDING_NEW_PLOT
	bool	IsEditAllowed()
	{
		if (m_dpEditor)
		{
			return m_dpEditor.GetInfo(TREDTINFOOPTS_IS_EDIT_ALLOWED);
		}
		
		return false;
	}
	/// RVD 8/25/2003 QA70-5042 v7.0674 DATAPLOT_LIMITS_DISPLAY
	DWORD	GetView()
	{
		return m_dpEditor.View;
	}
	bool	UpdateDataPlotLimits(int nRow)
	{
		/// RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY
		if( m_dpEditor.View & DPEDTVIEW_HIDE_LIMITS )
			return false;
		/// end PLOT_RANGE_APPLY
		HOUR_GLASS
		switch( getRowType(nRow) )
		{
		case DPL_PLOT_OUTSIDE_GROUP:
		case DPL_PLOT_IN_GROUP:
			{
				TreeNode tn;
				if( GetTreeNode(tn, nRow) )
				{
					if( Project.UpdateDataPlotLimits(tn) )
						SetTreeNode(tn, nRow);
				}
			}
			break;
		}
		
		return true;
	}
	/// end DATAPLOT_LIMITS_DISPLAY
	virtual string GetRuntimeClass()
	{
		return "PlotListControl";
	}
	virtual int GetDefaultSize(){return 150;}
private:
	int getRowType(int nRow)
	{
		if(nRow < m_flx.FixedRows)
			return -1;
		
		DWORD	dw;
		UINT	dw1, dw2;
		dw = m_dpEditor.GetRowInfo(nRow, dw1, dw2);
		return dw;
	}
	int getPageType(const string& strPageName, const string& strLayerName, const vector<string>& vsColNames)
	{
		if(strPageName.IsEmpty())
		//------ CPY 10/1/03 v7.5710 FUNC_PLOT_CHOOSEN_AS_LOOSE_DATASET_WHEN_START_EDIT
		//	return EXIST_DATA;
		{
			DWORD dw = vsColNames.GetSize() > 0? Project.GetDatasetInfo(vsColNames[0]) : 0;
			//---- CPY 11/15/03 QA70-5434-P17 v7.5756 MATRIX_BECOME_LOOSE_DATASET
			//return (dw & PGDN_FUNCTION)? EXIST_FUNC_PLOT : EXIST_DATA;
			if(dw & PGDN_IN_MATRIX)
				return EXIST_MATRIX;
			
			return (dw & PGDN_FUNCTION)? EXIST_FUNC_PLOT : EXIST_DATA;
			//---- end MATRIX_BECOME_LOOSE_DATASET
		}
		//------ end FUNC_PLOT_CHOOSEN_AS_LOOSE_DATASET_WHEN_START_EDIT
		
		if(vsColNames.GetSize() > 0 && !vsColNames[0].IsEmpty())
			return EXIST_WKS;
		
		return EXIST_MATRIX;
	}
	int findLayerRow(int nLayer = 0)
	{
		int nLayerFound = 0;
		for(int nRow = m_flx.FixedRows; nRow < m_flx.Rows; nRow++)
		{
			if(DPL_LAYER == getRowType(nRow))
			{
				if(nLayer == nLayerFound)
					return nRow;
			
				nLayerFound++
			}
		}
		return -1;
	}
	//---- CPY 9/15/03 OK_BUTTON_DISABLE_WHEN_ADDING_NEW_PLOT
	int findDataPlotRow(int nDataPlot = 0, bool bNotInGroupOnly = false)
	{
		int nDataPlotFound = 0;
		int nType;
		for(int nRow = m_flx.FixedRows; nRow < m_flx.Rows; nRow++)
		{
			nType = getRowType(nRow);
			if(DPL_PLOT_OUTSIDE_GROUP == nType || (!bNotInGroupOnly && DPL_PLOT_IN_GROUP == nType))
			{
				if(nDataPlot == nDataPlotFound)
					return nRow;
			
				nDataPlotFound++
			}
		}
		return -1;
	}
	//----
	/// RVD 8/25/2003 QA70-5042 v7.0674 DATAPLOT_LIMITS_DISPLAY
	int	updateLayerRescale(vector<uint> &arrLayerRows, TreeNode& trDP)
	{
		HOUR_GLASS //PROFILE_HRGLASS
		
		/// RVD 9/3/2003 QA70-5078 v7.0682 PLOT_RANGE_APPLY
		if( m_dpEditor.View & DPEDTVIEW_HIDE_LIMITS )
			return false;
		/// end PLOT_RANGE_APPLY
		
		for (int ii = 0; ii < arrLayerRows.GetSize(); ii++)
		{
			LONG		nRow = arrLayerRows[ii];
			if( DPL_LAYER == getRowType(nRow) )
			{
				TreeNode trLayer;
		
				if( GetTreeNode(trLayer, nRow) )
				{
					if( Project.UpdateLayerRescale(trDP, trLayer) )
						SetTreeNode(trLayer, nRow);
				}
			}
		}
		return 0;
	}
	/// end DATAPLOT_LIMITS_DISPLAY
private:
	TreeEditor	m_dpEditor;
	int			m_nActiveLayer;
	int			m_nLastSelRow, m_nLastSelCol;
};


#endif //_PLOT_LIST_CONTROL_H


