/*------------------------------------------------------------------------------*
 * File Name:InsertUserVar.c	 												*
 * Creation: CPY																*
 * Purpose: OriginC Source C file for Insert User Variables dialog				*
 * Copyright (c) Originlab Corp.	2003										*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/
#include <Origin.h>
#include <Dialog.h>
#include "ResizeDialog.h"
#include <TreeEditor.h>
#include <vsFlexGrid.h>

#include <GetNBox.h>

#include "ODlg.h" // resource IDs, ODlg.dll also use this file for its res ids
#include "HelpID.h"
#include "GridControl.h"
	

class InfoVarsControl : public GridListControl
{
private:
	TreeEditor	m_treeEditor;
public:
	void Init(int nID, Dialog& dlg, TreeNode &tr)
	{
		GridListControl::InitControl(nID, dlg);
		m_treeEditor = dlg.GetItem(nID);
		m_flx = m_treeEditor.GetActiveXControl();
		
		SetFont();
		m_treeEditor.Root = tr;
		
		m_flx.Editable = flexEDNone;
		//m_flx.HighLight = flexHighlightNever;
		m_flx.FocusRect = flexFocusLight;
		
	}
	bool GetSelStr(string& str, bool bLink, bool bPropValPair)
	{
		vector<uint> arrRows;
		if(m_treeEditor.GetSelectedRows(&arrRows, TRUE) > 0)
		{
			string strTemp;
			for(int ii = 0; ii < arrRows.GetSize(); ii++)
			{
				if(getRowStr(strTemp, arrRows[ii], bLink, bPropValPair))
				{
					if(!str.IsEmpty())
						str += "\r\n";
					str += strTemp;
				}
			}
			return true;
		}
		return false;
	}
private:
	bool getRowStr(string& str, int nRow, bool bLink, bool bPropValPair)
	{
		DWORD	dwData = m_treeEditor.GetProperty(nRow);
		str.Empty();
		if(dwData)
		{
			EditorManager	trNodeManager;
			if(bLink)
				str = "\\v(" + trNodeManager.GetStrData(dwData) + ")";
			else
			{
				// check verbatim if file path is used, 
				str = trNodeManager.GetText(dwData, FALSE);
				int n1 = str.Find('\\');
				
				if(n1 >= 0 && !isFormatting(str, n1))
				{
					str = "\\v(" + str + ")";
				}
			}
			if(bPropValPair)
			{
				string strTagName = m_flx.TextMatrix(nRow, 0); // assume 2 cols, propertyname(0), value(1)
				str = strTagName + " = " + str;
			}
			return true;
		}
		return false;
	}
	//n1 if the '\\' location, we then check if in the form of \a(bc)
	bool isFormatting(const string& str, int n1)
	{
		int nLen = str.GetLength();
		if(n1+1 < nLen && str[n1+1] == '\\')
			return false; // not possible if \\ as part of network path
		if(n1+2 < nLen && str[n1+2] == '(')
			return true;
		
		// no other checking, can add later
		return false;
	}
};

// open Insert Info Variables dialog and return str to insert
// *lpType = 0 if insert as is, =1 if insert as link
bool InsertUserVar(HWND hWndParent, string& str, int* lpType = NULL)
{
	InsertUserVarDlg MyDlg;
	
	int nRet = MyDlg.DoModalEx(hWndParent);
	str = MyDlg.m_strRet;
	if(lpType)
		*lpType = MyDlg.m_bUseLink;
	return (IDCANCEL == nRet)? false:true;
}

class InsertUserVarDlg : public ResizeDialog
{
private:
	InfoVarsControl m_InfoVars;
	Button			m_btnUseLink;
	Button			m_btnPorpValPair;
	
public:
	InsertUserVarDlg() : ResizeDialog(IDD_PASTE_USER_VAR, "ODlg")
	{
	}
	int DoModalEx(HWND hWndParent = NULL)
	{
		InitMsgMap();// will be called from internal later
		return DoModal(hWndParent);
	}
	
	string 			m_strRet;
	bool			m_bUseLink;
protected:
	///----------------------------------------------
	///----------------- Message Map ----------------
	///
	EVENTS_BEGIN
		ON_INIT(OnInitDialog) 
		ON_OK(OnOK)
	EVENTS_END
	///----------------------------------------------
	
	///////////////////////////////////////////////////////
	/// Event Handlers
	///////////////////////////////////////////////////////
	BOOL OnInitDialog()
	{
		waitCursor _junk;
		ResizeDialog::OnInitDialog();
		
		Tree trJunk;// we cannot use tree directly, need to have at least one node
		TreeNode tr;
		// if in graph or wks
		GraphLayer glactive = Project.ActiveLayer();
		if(glactive)
		{
			TreeNode trWkslist = trJunk.AddNode("InfoVars");
			if(graph_get_info_tree(glactive, trWkslist))
				tr = trWkslist;
		}
		else
		{
			Page pg = Project.Pages();
			if(pg && tree_add_info(trJunk, pg, NULL, NULL, NPLOT_FOR_WKS))
				tr = trJunk;
		}
		m_InfoVars.Init(IDC_PASTEVAR_TREE, *this, tr);		
	
		m_btnUseLink = GetItem(IDC_PASTEVAR_KEEP_LINK);
		m_btnPorpValPair = GetItem(IDC_PASTEVAR_PROP_VALUE);
		
		ResizeDialog::LoadCheckBoxSettings("InsertUserVar", IDC_PASTEVAR_KEEP_LINK, IDC_PASTEVAR_PROP_VALUE);
		return TRUE;	
	}
	
	BOOL OnOK()
	{
		bool bPropValPair = m_btnPorpValPair.Check;
		m_bUseLink = m_btnUseLink.Check;
		m_InfoVars.GetSelStr(m_strRet, m_bUseLink, bPropValPair);
		
		ResizeDialog::SaveCheckBoxSettings();
		return TRUE;
	}
private:
	///////////////////////////////////////////////////////
	/// General utilities
	///////////////////////////////////////////////////////
	bool is_in_list(vector<string>& vsList, LPCSTR lpcszName)
	{
		for(int ii = 0; ii < vsList.GetSize(); ii++)
		{
			if(vsList[ii].CompareNoCase(lpcszName) == 0)
				return true;
		}
		return false;
	}
	
	// from the given graph, we will add all the page.info.User.Variables to our tree 
	bool graph_get_info_tree(GraphLayer gl, TreeNode& trNode)
	{
		if(!gl)
			return false;
		
		vector<string> vsWksNames;
		vector<uint>	vsDataPlots;
		uint iPlot = 1;// LabTalk index
		foreach(DataPlot dp in gl.DataPlots)
		{
			// we are trying to get wks name from a data plot
			// currently there is no clean way to do this
			string strName = dp.GetDatasetName();
			int nPos = strName.Find('_');
			string strWksName;
			if(nPos > 0)
				strWksName = strName.Left(nPos);
			else // check for matrices
				strWksName = strName;
			
			if(!strWksName.IsEmpty() && !is_in_list(vsWksNames, strWksName))
			{
				vsWksNames.Add(strWksName);
				vsDataPlots.Add(iPlot++);
			}
			
		}
		
		for(int ii = 0; ii < vsWksNames.GetSize(); ii++)
		{
			string str = vsWksNames[ii];
			Page pg(vsWksNames[ii]);
			string strLabel = pg.Label;
			if(!strLabel.IsEmpty())
				str += " - " + pg.Label;
			tree_add_info(trNode, pg, vsWksNames[ii], str, vsDataPlots[ii]);
		}
		
		return true;
	}
};


		
		
			
		
	
	
