/*------------------------------------------------------------------------------*
 * File Name: wkBook.h															*
 * Creation: CPY 8/5/2004													    *
 * Purpose: General GUI related operations on Workbook and Active sheet			*
 * Copyright (c) OriginLab Corp.2004											*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	CPY 8/5/04 WKBOOK_CONTEXT_MENU_STANDARD_HANDLING, created this file			*
 * EJP 2005-05-25 v8.0241 QA70-7218 NEW_MATRIX_WORKBOOK							*
 * EJP 2005-07-05 v8.0261 QA70-7769 MAT_FRAME_BUTTON_OC							*
 * Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING					*
 *	ML 10/30/2007 QA70-10560 P3 DELETE_HIER_SHEET_ONLY_NONUNDOABLY				*
 *	Folger 01/04/08 QA70-10891 MULTIPLE_SHEETS_SELECTION_OPERATION_SUPPORT		*
 *	Folger 01/22/08 QA70-10891-S1 ACTIVE_SHEET_AFTER_DELETING					*
 *	Folger 02/25/08 QA80-11161 IMPROVE_MOVE_SELECTED_SHEETS						*
 *	Folger 09/01/08 NOT_ALLOW_UNDO_OF_INSERT_SHEET_IN_CONTEXT_MENU				*
 *	Folger 09/01/08 IMPROVE_DELETE_SHEET_BEHAVIOR_FOR_HIERARCHY_SHEET			*
 *	ML 12/24/2008 QA70-12660 P6 DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY		*
 *	Folger 01/04/09 v8.0993c FAILS_TO_DELETE_MATRIX_LAYER_BY_CONTEXT_MENU		*
 *	RVD 4/15/2008 qa70-13457 FIX_MATRIX_SHEET_DELETE_UNDO						*
 *	RVD 2/16/2010 qa70-15115 NO_DATA_COPY_MUST_COPY_OPERATION					*
 *------------------------------------------------------------------------------*/

#ifndef _WKBOOK_H
#define _WKBOOK_H

//
////////
// some basic utility functions
/**
	Return:
		true if success
*/
/// YuI 10/20/04 QA70-7072 v7.5153 CORNER_OBJECT_FOR_NEW_WORKBOOK
//	int load_wks_default_context_menu(Menu* pmenu, Worksheet& wks, int nSel, int nx, int ny = 0, bool bByPos = false);
//------ CPY 5/11/2007 QA70-9760 XFBAR_CONTEXT_MENU_ON_TITLE
//BOOL load_wks_default_context_menu(Menu* pmenu, Worksheet& wks, int nId, int nPos);
//BOOL load_wks_default_context_menu(Menu* pmenu, Worksheet& wks, int nSelectionType, int nx, int ny);
BOOL load_default_context_menu(Menu* pmenu, OriginObject& wks, int nId, int nPos);
BOOL load_default_context_menu(Menu* pmenu, OriginObject& wks, int nSelectionType, int nx, int ny);
//-----
/// end CORNER_OBJECT_FOR_NEW_WORKBOOK

/// EJP 2005-05-25 v8.0241 QA70-7218 NEW_MATRIX_WORKBOOK
// In WorkBookActiveSheet class I changed all Worksheet to Datasheet and
// all WorksheetPage to Page.
/// end NEW_MATRIX_WORKBOOK

class WorkBookActiveSheet
{
public:
	void Init(Page &wksPage, Datasheet *pWks = NULL)
	{
		m_wksPage = wksPage;
		updateActiveSheet(pWks);
	}
	bool IsValid() {return m_wksPage.IsValid();}

//	bool IsChangeParamAvailable() {return m_bChangeParam;}
	bool MoveSheet(bool bUndo = true)
	{
		//------ Folger 02/25/08 QA80-11161 IMPROVE_MOVE_SELECTED_SHEETS
		/*
		//Bring up GUI to get these values
		vector<string> vsChoices;
		int nIndex = m_wksActive.GetIndex();
		int nCurrIndex = nIndex;
		foreach(Layer wksheets in m_wksPage.Layers)
		{
			if(nIndex > 0 || nIndex < -1)
			{
				string strName = wksheets.GetName();
				vsChoices.Add(strName);
			}
			nIndex--;
			
		}
		vector<byte> vSelections;
		
		if(0 == vsChoices.GetSize())
			return false;
		
		vsChoices.Add(_L("(move to end)"));
		
		/// TD 10-27-04 QA70-6410 SUPPORT_COPY_WORKSHHET_LAYER_FOR_CTXTMENU_MOVE_AND_DRAG_DROP
		//int nSel = ListInputBox(&vsChoices, _L("Before Sheet?\r\nPlease select"), -1);
		//if(nSel >= nCurrIndex)
		//	nSel+= 2;
		BOOL bMakeACopy = FALSE;
		int nSel = ListInputBox(&vsChoices, _L("Before Sheet?\r\nPlease select"), -1, &bMakeACopy ,_L("Create a copy"));
		if(nSel >= nCurrIndex)
		{
			nSel += 1;
			if(bMakeACopy)
				nSel += 1;
		}
	
		Datasheet wksLayerToMove = m_wksActive;
		if(bMakeACopy)
		{
			
			int nPos = m_wksPage.AddLayer(m_wksActive);
			if(nPos > 0)
				wksLayerToMove = m_wksPage.Layers(nPos);
		}
		if(wksLayerToMove && nSel > -1 )
		/// end SUPPORT_COPY_WORKSHHET_LAYER_FOR_CTXTMENU_MOVE_AND_DRAG_DROP
		{
			wksLayerToMove.SetIndex(nSel, bUndo);
			updateActiveSheet();
			return true;
		}
		return false;
		*/
		vector<string> vsChoices;
		foreach(Layer wksheets in m_wksPage.Layers)
		{
			vsChoices.Add(wksheets.GetName());
		}
		vsChoices.Add(_L("(move to end)"));
		
		BOOL bMakeACopy = false;
		int nSel = ListInputBox(&vsChoices, _L("Move Sheets\r\nBefore Sheet:"), 0, &bMakeACopy ,_L("Create a copy"));
		if ( nSel < 0 )
			return false;
		
		vector<int> vnLayers;
		int nSize;
		if ( (nSize = m_wksPage.GetSelectedLayers(vnLayers)) > 0 )
		{
			vnLayers.Sort();
			if ( bMakeACopy )
			{
				int nLayers = m_wksPage.Layers.Count();
				DuplicateSheet();
				vnLayers.Data(nLayers, nLayers + nSize - 1);
			}
			vector<uint> vnIndeces;
			int nFind = vnLayers.Find(vnIndeces, nSel);
			int nOffsetLeft = 0, nOffsetRight = 0;
			//from right to left, index descending, rules are from Microsoft Excel
			Layer lay;
			for ( int ii=nSize-1; ii>=0; --ii )
			{
				int nIndex = vnLayers[ii];
				if ( nIndex > nSel )
				{
					lay = m_wksPage.Layers(nIndex + (nOffsetRight++));
					lay.SetIndex(nFind > 0 ? nSel + 1 :  nSel);
				}
				else if ( nIndex <= nSel )
				{
					lay = m_wksPage.Layers(nIndex);
					if ( nIndex < nSel )
						lay.SetIndex(nSel - (++nOffsetLeft));
				}
			}
			if ( lay )
				set_active_layer(lay);
			updateActiveSheet();			
		}
		
		return true;
		//------ End IMPROVE_MOVE_SELECTED_SHEETS
	}
	void AddSheet(bool bBringToFront = true)	//may not be always true later
	{
		//------ Folger 01/04/08 QA70-10891 MULTIPLE_SHEETS_SELECTION_OPERATION_SUPPORT
		//int nLayer = addNewSheet();//m_wksPage.AddLayer("Data1");
		//
		//if(nLayer>=0 && bBringToFront)
			//page_set_active_layer(m_wksPage, nLayer);
		vector<int> vnLayers;
		int nSize;
		if ( (nSize = m_wksPage.GetSelectedLayers(vnLayers)) > 0 )
		{
			int nLayers = m_wksPage.Layers.Count();
			for ( int ii=0; ii<nSize;  ++ii )
			{
				addNewSheet();
			}
			if ( bBringToFront )
				page_set_active_layer(m_wksPage, nLayers);		//active the first added sheet
		}
		updateActiveSheet(); //CPY 1/4/08
		//------
	}
	//------ Folger 09/01/08 NOT_ALLOW_UNDO_OF_INSERT_SHEET_IN_CONTEXT_MENU
	/// Folger 09/01/08, since we did not support undo in AddSheet(AddLayer), then should disallow undo in InserSheet
	int InsertSheet(/*bool bUndo = true*/)
	//------ End NOT_ALLOW_UNDO_OF_INSERT_SHEET_IN_CONTEXT_MENU
	{
		//------ Folger 01/07/08 QA70-10891 MULTIPLE_SHEETS_SELECTION_OPERATION_SUPPORT
		////string		strInput = InputBox(_L("Sheet Name")); // keep dialog for now, we will remove dialog later
		////string		strInput = "Data1";//CPY 7/28/04, will auto rename if already present
		////if(m_wksPage.AddLayer(strInput))
		//if(addNewSheet())
		//{
			//int nCnt = m_wksPage.Layers.Count();	
			//Datasheet wksLayerNew = m_wksPage.Layers(nCnt-1);
			//int nIndex = m_wksActive.GetIndex();
			//if(wksLayerNew)
			//{
				//wksLayerNew.SetIndex(nIndex, bUndo);
				//updateActiveSheet();
				//return nIndex;
			//}
		//}
		vector<int> vnLayers;
		int nSize;
		if ( (nSize = m_wksPage.GetSelectedLayers(vnLayers)) > 0 )
		{
			
			vnLayers.Sort();
			for ( int ii=nSize-1; ii > 0 && vnLayers[ii] - vnLayers[ii-1] == 1; --ii );
			if ( ii != 0 )
			{
				warning_msg_box(CER_NON_CONSECUTIVE_SHEETS_SELECTED, true);
				return -1;
			}
			int nActiveLayer = m_wksActive.GetIndex();
			for ( ii=0; ii<nSize; ++ii )
			{
				Layer lay = m_wksPage.Layers(addNewSheet());
				//------ Folger 09/01/08 NOT_ALLOW_UNDO_OF_INSERT_SHEET_IN_CONTEXT_MENU
				//lay.SetIndex(nActiveLayer + ii);
				lay.SetIndex(nActiveLayer + ii, false);
				//------ End NOT_ALLOW_UNDO_OF_INSERT_SHEET_IN_CONTEXT_MENU
			}
			page_set_active_layer(m_wksPage, nActiveLayer);
			updateActiveSheet();
		}
		//------
		return -1;
	}
	void DeleteSheet()
	{
		//------ Folger 09/01/08 IMPROVE_DELETE_SHEET_BEHAVIOR_FOR_HIERARCHY_SHEET
		/*
		/// ML 10/30/2007 QA70-10560 P3 DELETE_HIER_SHEET_ONLY_NONUNDOABLY
		DWORD			dwOCD = OCD_DEL_LINKED_OBJS | OCD_DEL_PARENT_IF_LAST;
		BOOL			bHie = m_wksActive.GetSystemParam(0) & WP_SHEET_HIERARCHY;
		if( bHie )
		{
			if ( IDNO == ocu_err_msgbox(IDS_NOT_UNDOABLE_YESNO, MB_YESNO) )
				return;
		}
		else
			dwOCD |= OCD_UNDO;
		*/
		//------ End IMPROVE_DELETE_SHEET_BEHAVIOR_FOR_HIERARCHY_SHEET
		
		//------ Folger 01/04/08 QA70-10891 MULTIPLE_SHEETS_SELECTION_OPERATION_SUPPORT
		////---- CPY  8-3-04 QA70-6727 WKBOOK_NO_SHEET_SUPPORT
		//// we need undo support
		////m_wksLayer.Destroy();
		///// ML 10/30/2007 QA70-10560 P3 DELETE_HIER_SHEET_ONLY_NONUNDOABLY
		////m_wksActive.Delete(OCD_UNDO | OCD_DEL_LINKED_OBJS | OCD_DEL_PARENT_IF_LAST);
		//m_wksActive.Delete(dwOCD);
		///// end DELETE_HIER_SHEET_ONLY_NONUNDOABLY
		////----
		
		vector<int> vnLayers;
		/// ML 12/24/2008 QA70-12660 P6 DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY
		//int nSize;
		//if ( (nSize = m_wksPage.GetSelectedLayers(vnLayers)) > 0 )
		int			nSize = m_wksPage.GetSelectedLayers(vnLayers);
		if ( nSize <= 0 )
			return;
		
		// First check for operations to see if there is any:
		WKBKDELWKSMODE		wkbkmode = WKBKDELWKSMODE_CHECK_ASK;
		BOOL				bUndo = TRUE;
		WorksheetPage		wksPage;
		wksPage = m_wksPage;
		
		///------ Folger 01/04/09 v8.0993c FAILS_TO_DELETE_MATRIX_LAYER_BY_CONTEXT_MENU
		DWORD			dwOCD = OCD_DEL_LINKED_OBJS | OCD_DEL_PARENT_IF_LAST;
		if ( wksPage )
		///------ End FAILS_TO_DELETE_MATRIX_LAYER_BY_CONTEXT_MENU
		{
		int					nRetOpers = wksPage.CheckOperationsDelete(wkbkmode, &vnLayers, &bUndo);
		ASSERT(wkbkmode != WKBKDELWKSMODE_CHECK_ASK);
		if ( nRetOpers < 0 )
			return;		// user cancelled
		/// end DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY
		
			//------ Folger 09/01/08 IMPROVE_DELETE_SHEET_BEHAVIOR_FOR_HIERARCHY_SHEET
			//DWORD			dwOCD = OCD_DEL_LINKED_OBJS | OCD_DEL_PARENT_IF_LAST;		///------ Folger 01/04/09 v8.0993c FAILS_TO_DELETE_MATRIX_LAYER_BY_CONTEXT_MENU
			/// ML 12/24/2008 QA70-12660 P6 DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY
			/*
			BOOL			bHie = false;
			for ( int nn=0; !bHie && nn<nSize; ++nn )
			{
				Layer lay = m_wksPage.Layers(vnLayers[nn]);
				bHie = lay.GetSystemParam(0) & WP_SHEET_HIERARCHY;
			}
			
			if( bHie )
			{
				if ( IDNO == ocu_err_msgbox(IDS_NOT_UNDOABLE_YESNO, MB_YESNO) )
					return;
			}
			else
				dwOCD |= OCD_UNDO;
			*/
			if (0 < nRetOpers)		// already asked
			{
				ASSERT(wkbkmode != WKBKDELWKSMODE_DEFAULT);
				// There are outputs with opers, the first has already asked the user,
				// so need to call again to do operations removals and update vnLayers if necessary
				wksPage.CheckOperationsDelete(wkbkmode, &vnLayers, &bUndo);
				
				if ( bUndo )
					dwOCD |= OCD_UNDO;		// probably never happens, since outputs are getting destroyed
			}
			else if (0 == nRetOpers)		// user not asked, allow the old code to ask if necessary
			{
				// The first call to CheckOperationsDelete() did not ask any question, so need to run the old
				// code to ask for hier.:
				BOOL			bHie = false;
				for ( int nn=0; !bHie && nn<nSize; ++nn )
				{
					Layer lay = m_wksPage.Layers(vnLayers[nn]);
					bHie = lay.GetSystemParam(0) & WP_SHEET_HIERARCHY;
				}
				
				if( bHie )
				{
					if ( IDNO == ocu_err_msgbox(IDS_NOT_UNDOABLE_YESNO, MB_YESNO) )
						return;
				}
				else if ( bUndo )
					dwOCD |= OCD_UNDO;

				// If there are just operations to remove, do it:
				if (wkbkmode != WKBKDELWKSMODE_DEFAULT)
					wksPage.CheckOperationsDelete(wkbkmode, &vnLayers, &bUndo);
			}
			//------ End IMPROVE_DELETE_SHEET_BEHAVIOR_FOR_HIERARCHY_SHEET
			/// end DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY
		}
		/// RVD 4/15/2008 qa70-13457 FIX_MATRIX_SHEET_DELETE_UNDO
		else
		{
			if( bUndo )
				dwOCD |= OCD_UNDO;
		}
		/// end FIX_MATRIX_SHEET_DELETE_UNDO
			/// ML 12/24/2008 QA70-12660 P6 DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY
			nSize = vnLayers.GetSize();	// must do this because CheckOperationsDelete() might update vnLayers
			/// end DELETING_WHOLE_SHEETS_OPERATION_INTERPLAY
			UndoBlock ub;
			vnLayers.Sort();
			//------ Folger 01/22/08 QA70-10891-S1 ACTIVE_SHEET_AFTER_DELETING
			Datasheet dsActive;
			if ( vnLayers[nSize-1] + 1 < m_wksPage.Layers.Count() )
				dsActive = m_wksPage.Layers(vnLayers[nSize-1] + 1);
			else
			{
				vector<uint> vnIndeces;
				for ( int ii=vnLayers[nSize-1]-1; ii>=0 && vnLayers.Find(vnIndeces, ii)>0; --ii );
				if ( ii >= 0 )
					dsActive = m_wksPage.Layers(ii);
			}
			//------
			for ( int ii=nSize-1; ii>=0; --ii )
			{
				Layer lay = m_wksPage.Layers(vnLayers[ii]);
				lay.Delete(dwOCD);
			}
			//------ Folger 01/22/08 QA70-10891-S1 ACTIVE_SHEET_AFTER_DELETING
			if ( dsActive )
				page_set_active_layer(m_wksPage, dsActive.GetIndex());
			//------
		
		//------
		updateActiveSheet();
	}
	void RenameSheet()
	{
		m_wksActive.SetName(NULL);//NULL name will bring up rename dialog
	}
	void ChangeParam()
	{
		OperationBase &op = m_wksActive.GetSrcOperation();
		if(op)
			op.ChangeParam();
	}
	bool GetWksheet(Datasheet& wks)
	{
		if(m_wksActive)
			wks = m_wksActive;
		else
			return false;
		
		return true;
	}
	/*
	bool GetSplitterInfo(LPCSTR lpcszClassName = NULL)
	{
		if(m_wksPage)
			return m_wksPage.GetSplitterInfo(lpcszClassName);
		return false;
	}
	bool SetSplitters(LPCSTR lpcszString)
	{
		if(m_wksPage)
			return m_wksPage.SetSplitters(lpcszString);
		return false;
	}*/
	bool ProcessCommand(int nCmd)
	{
		if(m_wksPage)
			return m_wksPage.ProcessCommand(nCmd);
		return false;
	}
	
	/// SY 05/27/2005 v8.0244 QA70-7575 SHEET_DUPLICATE_CONTEXT_MENU
	/// TD 4-20-06 NO_DATA_COPY_MUST_COPY_STORAGE_DATA
	//int DuplicateSheet(bool bBringToFront = true)
	int DuplicateSheet(bool bBringToFront = true)
	{
		return DuplicateSheetEx(DCTRL_COPY_DEFAULT, bBringToFront);
	}
	int DuplicateSheetEx(DWORD dwOptions = DCTRL_COPY_DEFAULT, bool bBringToFront = true)
	/// end NO_DATA_COPY_MUST_COPY_STORAGE_DATA
	{
		//------ Folger 01/04/08 QA70-10891 MULTIPLE_SHEETS_SELECTION_OPERATION_SUPPORT
		///// TD 4-20-06 NO_DATA_COPY_MUST_COPY_STORAGE_DATA
		////int nLayer = m_wksPage.AddLayer(m_wksActive);	
		//int nLayer = m_wksPage.AddLayer(m_wksActive, dwOptions);	
		///// end NO_DATA_COPY_MUST_COPY_STORAGE_DATA
		//if( nLayer >= 0 && bBringToFront )
			//page_set_active_layer(m_wksPage, nLayer);
		vector<int> vnLayers;
		int nSize;
		if ( (nSize = m_wksPage.GetSelectedLayers(vnLayers)) > 0 )
		{
			int nLayers = m_wksPage.Layers.Count();
			for ( int ii=0;  ii<nSize; ++ii )
			{
				Layer lay = m_wksPage.Layers(vnLayers[ii]);
				m_wksPage.AddLayer(lay, dwOptions);
			}
			if ( bBringToFront )
				page_set_active_layer(m_wksPage, nLayers);
		}
		//------
		
		updateActiveSheet();
		
		return m_wksActive.GetIndex();
	}
	
	int DuplicateSheetNoData(bool bBringToFront = true)
	{
		/// RVD 2/16/2010 qa70-15115 NO_DATA_COPY_MUST_COPY_OPERATION
		/*
		/// TD 4-20-06 NO_DATA_COPY_MUST_COPY_STORAGE_DATA
		return DuplicateSheetEx(0, bBringToFront);
		/// end NO_DATA_COPY_MUST_COPY_STORAGE_DATA
		string strSheet;
		m_wksActive.GetName(strSheet);

		string str = GetAppPath() + strSheet;
	   	str += ".otw";
	   	
		if( str.IsFile() )
		   DeleteFile(str);
		
		if( m_wksActive.SaveAs(str) )
		{
		   	if( str.IsFile() )
		   	{
				int nLayer = addNewSheet(str);
				
				if( nLayer >= 0 && bBringToFront )
					page_set_active_layer(m_wksPage, nLayer);
				
				updateActiveSheet();
				
				return m_wksActive.GetIndex();
		   	}
		   	else
		       	out_str("Save As return true but no file saved");
		}
		else
		   out_str("failed");
		
		return -1; // error
		*/
		return DuplicateSheetEx(DCTRL_COPY_OUT_OPERATIONS, bBringToFront);
		/// end NO_DATA_COPY_MUST_COPY_OPERATION
	}
	/// end SHEET_DUPLICATE_CONTEXT_MENU

	/// EJP 2005-07-05 v8.0261 QA70-7769 MAT_FRAME_BUTTON_OC
	//--- CPY 7/10/05 RENAME_MATRIX_OBJ
	bool RenameObject()
	{
		MatrixLayer ml = m_wksActive;
		if( ml.IsValid() )
		{
			MatrixObject mo = ml.MatrixObjects();
			if(mo)
			{
				string strLongName = mo.GetLongName();
				try {
					/// Nicole 07/05/2007 v8.0655 REMOVE_SPACE_FOR_LOCATION_STRING
					//string strTitle = _L("Enter a new name for Matrix: ");
					string strTitle = _L("Enter a new name for Matrix:") + " ";
					/// END REMOVE_SPACE_FOR_LOCATION_STRING
					strTitle += strLongName;
					strLongName = InputBox(strTitle, strLongName);
				}
				catch(int nErr)
				{
					return false;
				}
				mo.SetLongName(strLongName);
				return true;
			}
		}
		return false;
	}
	//---
	int AddObject()
	{
		MatrixLayer ml = m_wksActive;
		if( ml.IsValid() )
			return ml.Insert(1); // add 1 object after last object
		return -1;
	}
	
	int InsertObject()
	{
		MatrixLayer ml = m_wksActive;
		if( ml.IsValid() )
		{
			int nActiveObj = ml.GetActive();
			return ml.Insert(1, nActiveObj); // add 1 object before active object
		}
		return -1;
	}

	int DeleteObject()
	{
		MatrixLayer ml = m_wksActive;
		if( ml.IsValid() )
		{
			int nActiveObj = ml.GetActive();
			return ml.Delete(nActiveObj); // delete active object
		}
		return -1;
	}
	
	BOOL SetActiveObject(int nIndex)
	{
		MatrixLayer ml = m_wksActive;
		if( ml.IsValid() )
			return ml.SetActive(nIndex);
		return FALSE;
	}
	
	Datasheet GetActiveDatasheet()
	{
		return m_wksActive;
	}
	/// end MAT_FRAME_BUTTON_OC

private:

	//--- CPY 5/26/05 NEW_MATRIX_SHEET_DIFF_NAME_FROM_WKS
	/// SY 05/27/2005 v8.0244 QA70-7575 SHEET_DUPLICATE_CONTEXT_MENU
	///	int addNewSheet()
	int addNewSheet(LPCSTR lpcszTemplate = NULL)
	/// end SHEET_DUPLICATE_CONTEXT_MENU
	{
		int nType = m_wksPage.GetType();
		//---- CPY 8/31/06 QA70-8949 NOT_TO_ALLOW_EMPTY_SHEET_NAME
		/*
		string strNewSheetName = "Data1";// 1 terminated will be auto enum
		if(EXIST_MATRIX == nType)
			strNewSheetName = "MSheet1";
		
		/// SY 05/27/2005 v8.0244 QA70-7575 SHEET_DUPLICATE_CONTEXT_MENU
		///	return m_wksPage.AddLayer(strNewSheetName);
		return m_wksPage.AddLayer(strNewSheetName, 0, lpcszTemplate);
		/// end SHEET_DUPLICATE_CONTEXT_MENU
		*/
		return m_wksPage.AddLayer(NULL, 0, lpcszTemplate);
		//----
	}
	//---
	void updateActiveSheet(Datasheet *pWks = NULL)
	{
		Datasheet wks = m_wksPage.Layers(); //
		if(pWks)
			m_wksActive = *pWks;

		if(!m_wksActive || !pWks)
			m_wksActive = wks;
//		m_bChangeParam = false;
		if(m_wksActive)
		{
//			OperationBase &op = m_wksActive.GetSrcOperation();
//			if(op)
//				m_bChangeParam = true;
		}
	}
//	bool			m_bChangeParam;
	Page 			m_wksPage;
	Datasheet		m_wksActive; // active sheet
};

// need to move this to GetNBox.h later
#define GETN_ADD_DATA(_NUM_DATA)	_tmpSubNode.SetAttribute(STR_DATAID_ATTRIB, ftoa(_NUM_DATA)); 

// wks col related info consts
enum {
	WCRI_BOOK_LONGNAME,
	WCRI_BOOK_SHORTNAME,
	WCRI_BOOK_COMMENTS,
	WCRI_BOOK_MODIFIED_DATE,
	WCRI_BOOK_CREATE_DATE,

	WCRI_SHEET_NAME,

	WCRI_COL_LONGNAME,
	WCRI_COL_SHORTNAME,
	WCRI_COL_UNITS,
	WCRI_COL_PARAMETER,
	WCRI_COL_COMMENTS,
	WCRI_COL_ROW_RANGE,
	
	WCRI_IMPORT_FILENAME,
	WCRI_IMPORT_FILEDATE,
	WCRI_IMPORT_FILEPATH,

	WCRI_IMPORT_FILESIZE,



	WCRI_LAST_ENTRY
};

// a class for usful column operations by the user
class WksColumn
{
public:
	WksColumn() {m_nCol = -1;}
	~WksColumn() {}
	
	bool Init(Column& col)
	{
		m_col = col;
		if(m_col)
			m_nCol = m_col.GetIndex();
		else
			m_nCol = -1;
		
		if(m_nCol >= 0)
		{
			m_col.GetParent(m_wks);
		}
		if(!m_wks)
			return false;
		
		return true;
	}
	bool IsValid() 
	{
		return m_nCol >=0 && m_wks.IsValid() && m_col.IsValid() ? true:false;
	}
	bool InsertColsDlg()
	{
		GETN_TREE(tr)
		
		GETN_BEGIN_BRANCH(Col, "Column and Data")
			GETN_OPTION_BRANCH(GETNBRANCH_OPEN | GETNBRANCH_KEEP_SIZE_ON_COLLAPSE)
			GETN_CHECK(ColLongName, "Column Long Names", 0)		GETN_ADD_DATA(WCRI_COL_LONGNAME)
			GETN_CHECK(ColShortName, "Column Short Names", 0)	GETN_ADD_DATA(WCRI_COL_SHORTNAME)
			GETN_CHECK(ColUnits, "Column Units", 0)				GETN_ADD_DATA(WCRI_COL_UNITS)
			GETN_CHECK(ColParameter, "Column Parameters", 0)	GETN_ADD_DATA(WCRI_COL_PARAMETER)
			GETN_CHECK(ColComments, "Column Comments", 0)		GETN_ADD_DATA(WCRI_COL_COMMENTS)
			GETN_CHECK(ColComments, "Data Row Range", 0)		GETN_ADD_DATA(WCRI_COL_ROW_RANGE)
		GETN_END_BRANCH(Col)
		
		GETN_BEGIN_BRANCH(Import, "Data Import Info")
			GETN_OPTION_BRANCH(GETNBRANCH_OPEN | GETNBRANCH_KEEP_SIZE_ON_COLLAPSE)
			GETN_CHECK(FileName, "File Name", 0)				GETN_ADD_DATA(WCRI_IMPORT_FILENAME)			
			GETN_CHECK(FileName, "File Path", 0)				GETN_ADD_DATA(WCRI_IMPORT_FILEPATH)			
			GETN_CHECK(FileDate, "File Modified Date", 0)		GETN_ADD_DATA(WCRI_IMPORT_FILEDATE)
		GETN_END_BRANCH(Import)
		
		GETN_BEGIN_BRANCH(BookSheet, "Book and Sheet")
			GETN_OPTION_BRANCH(GETNBRANCH_OPEN | GETNBRANCH_KEEP_SIZE_ON_COLLAPSE)
			GETN_CHECK(BookLongName, "Book Long Names", 0)		GETN_ADD_DATA(WCRI_BOOK_LONGNAME)
			GETN_CHECK(SheetName, "Sheet Names", 0)				GETN_ADD_DATA(WCRI_SHEET_NAME)
			GETN_CHECK(BookShortName, "Book Short Names", 0)	GETN_ADD_DATA(WCRI_BOOK_SHORTNAME)
			GETN_CHECK(BookComment, "Book Comments", 0)			GETN_ADD_DATA(WCRI_BOOK_COMMENTS)
			GETN_CHECK(BookDate, "Book Modified Date", 0)		GETN_ADD_DATA(WCRI_BOOK_MODIFIED_DATE)
		GETN_END_BRANCH(BookSheet)
		
		if(GetNBox(tr, "Insert Columns", "Find related info to fill new columns from the data in current column", NULL, NULL))
		{
			insertCols(tr);
			return true;
		}
		return false;
	}
	Worksheet GetWorksheet()
	{
		return m_wks;
	}
private:		
	int insertCols(TreeNode tr)
	{
		string strColName;
		vector<uint> vuInsertIDs;
		vector<string> vsLabels;
		////////////////////////////////////////////////////
		// following needs to be moved into tree_utils
		string strDataID, strLabel;
		foreach(TreeNode trNode in tr.Children)
		{
			if(trNode.GetNodeCount() > 0 || trNode.ID == ONODETYPE_BRANCH) // branch node
			{
				foreach(TreeNode trn in trNode.Children)
				{
					if(trn.nVal > 0 && trn.GetAttribute(STR_DATAID_ATTRIB, strDataID))
					{
						vuInsertIDs.Add(atoi(strDataID));
						trn.GetAttribute(STR_LABEL_ATTRIB, strLabel);
						vsLabels.Add(strLabel);
					}
				}
			}
		}
		////////////////////////////////////////////////////
		// insert from the end
		int nCount = 0;
		for(int ii = vuInsertIDs.GetSize() - 1; ii >= 0; ii--)
		{
			if(insertCol(vuInsertIDs[ii], m_nCol + 1, vsLabels[ii]) >= 0)
				nCount ++;
		}
		if(nCount)
			m_wks.GetPage().Refresh();
		
		return nCount;
	}
	int insertCol(int nWCRIType, int nPos, const string& strLabel, LPCSTR lpcszAuxStr = NULL)
	{
		string strColName;
		m_wks.InsertCol(nPos, NULL, strColName);
		Column cIns = m_wks.Columns(strColName);
		if(cIns)
		{
			cIns.SetLongName(strLabel);
			if(isDateType(nWCRIType))
				cIns.SetFormat(OKCOLTYPE_DATE);
			Dataset dsNewCol(cIns);
			return fillCol(dsNewCol, nWCRIType, lpcszAuxStr);
		}
		return -1;
	}
	bool isDateType(int nWCRIType)
	{
		if(WCRI_BOOK_MODIFIED_DATE == nWCRIType ||
		WCRI_BOOK_CREATE_DATE == nWCRIType ||	
		WCRI_IMPORT_FILEDATE == nWCRIType)
			return true;
		
		return false;
	}
	
	int fillCol(Dataset& dsDest, int nWCRIType, LPCSTR lpcszAuxStr = NULL)
	{
		Dataset dsSrc(m_wks, m_nCol);
		if(!dsSrc.IsValid())
			return -1;
		int nSize = dsSrc.GetUpperIndex() + 1;
		dsDest.SetSize(nSize);
		string strSrc;
		string strDest;
		double dValDest;
		bool bNumeric;
		int nCount = 0; // count not empty results
		for(int ii = 0; ii < nSize; ii++)
		{
			dsSrc.GetText(ii, strSrc);
			bNumeric = false;
			if(!strSrc.IsEmpty())
				bNumeric = getRelatedInfo(strSrc, nWCRIType, strDest, dValDest, lpcszAuxStr);
			else
				strDest = "";
			
			if(bNumeric)
				dsDest[ii] = dValDest;
			else
				dsDest.SetText(ii, strDest);
			
			if(!strDest.IsEmpty() || bNumeric)
				nCount++;
		}
		
		return nCount;
	}
	// return book name
	string parseRangeStr(LPCSTR lpcszRange, string& strSheet, string& strCol, string& strR1, string& strR2)
	{
		string strBook;
		char szBook[MAXLINE];
		char szSheet[MAXLINE];
		char szCol1[MAXLINE];
		char szCol2[MAXLINE];
		char szRow1[MAXLINE];
		char szRow2[MAXLINE];
		if(parse_data_range_str(lpcszRange, szBook, szSheet, szRow1, szCol1, szRow2, szCol2))
		{
			strBook = szBook;
			strSheet = szSheet;
			strCol = szCol1;
			strR1 = szRow1;
			strR2 = szRow2;
		}
		return strBook;
	}

		
	bool getRelatedInfo(LPCSTR lpcszSrc, int nWCRIType, string& strRet, double& dRet, LPCSTR lpcszAuxStr)
	{
		bool bNumeric = false;
		string strSheet;
		string strCol, strR1, strR2;
		string strBook = parseRangeStr(lpcszSrc, strSheet, strCol, strR1, strR2);
		WorksheetPage pg(strBook);
		Worksheet wks;
		if(pg)
			wks = pg.Layers(strSheet);
		
		switch(nWCRIType)
		{
		case WCRI_BOOK_LONGNAME:
			strRet =  pg.GetLongName();
			break;
		case WCRI_BOOK_SHORTNAME:
			strRet = strBook;
			break;
		case WCRI_BOOK_COMMENTS:
			strRet = pg.GetComments();
			break;
		case WCRI_SHEET_NAME:
			if(wks)
				strRet = wks.GetName();
			break;
		case WCRI_BOOK_MODIFIED_DATE:
			{
				PageSystemInfo	PgInfo;
				pg.GetPageSystemInfo(&PgInfo);
				bNumeric = true;
				dRet = PgInfo.dModified;
			}
			break;
		case WCRI_COL_LONGNAME:
		case WCRI_COL_SHORTNAME:
		case WCRI_COL_UNITS:
		case WCRI_COL_PARAMETER:
		case WCRI_COL_COMMENTS:
		case WCRI_COL_ROW_RANGE:
			{
				Column col = wks.Columns(strCol);
				if(col)
				{
					switch(nWCRIType)
					{
					case WCRI_COL_ROW_RANGE:
						strRet = strR1 + " - " + strR2;
						break;
					case WCRI_COL_LONGNAME:
						strRet = col.GetLongName();
						break;
					case WCRI_COL_SHORTNAME:
						strRet = col.GetName();
						break;
					case WCRI_COL_UNITS:
						strRet = col.GetUnits();
						break;
					case WCRI_COL_PARAMETER:
						col.GetParameter(strRet);
						break;
					case WCRI_COL_COMMENTS:
						strRet = col.GetComments();
						break;
					}
				}
			}
			break;
		case WCRI_IMPORT_FILENAME:
		case WCRI_IMPORT_FILEPATH:			
		case WCRI_IMPORT_FILEDATE:
			{
				string strFileFullPath;
				if(wkbook_find_import_file(strBook, strSheet, strCol, strFileFullPath, dRet))
				{
					switch(nWCRIType)
					{
					case WCRI_IMPORT_FILEDATE:
						bNumeric = true;
						break;
					case WCRI_IMPORT_FILEPATH:
						strRet = GetFilePath(strFileFullPath);
						break;
					case WCRI_IMPORT_FILENAME:
						strRet = GetFileName(strFileFullPath);
						break;
					}
				}
			}
			break;
		}
		return bNumeric;
	}
private:
	int			m_nCol;
	Column		m_col;
	Worksheet	m_wks; 
};


#endif //_WKBOOK_H
