#ifndef _PALEDIT_DATA_H
#define _PALEDIT_DATA_H

//for palette files
enum{
	SPRD_R2B = 0,
	SPRD_B2R,
	SPRD_RED, 
	SPRD_GREEN,
	SPRD_BLUE, 
};

///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
enum{
	GRADIENT_KEEP_CURRENT,
	GRADIENT_CONST,
	GRADIENT_STRAIGHT_LINE,
	GRADIENT_SIGMOID,
};
///End PALETTE_EDITOR_IMPORTMENT

#define GetRValue(rgb)      ((BYTE)(rgb))
#define GetGValue(rgb)      ((BYTE)(((WORD)(rgb)) >> 8))
#define GetBValue(rgb)      ((BYTE)((rgb)>>16))
#define MergeRGB(r, g, b)   (DWORD)((BYTE)r+(((WORD)g)<<8)+(((DWORD)b)<<16))   


//for paledit.oxf
#define SEGMENT_LINE_NAME "palSegmentLine"
#define ADJUST_LINE_NAME  "palAdjustLine"
#define SEG_RECT_NAME  "palRect"


///temp data worksheet cols index
#define COL_INDEX_PAL_X 0
#define COL_INDEX_PAL_R 1
#define COL_INDEX_PAL_G 2
#define COL_INDEX_PAL_B 3
#define COL_INDEX_PAL_SPY 4
#define COL_INDEX_PAL_SPC 5
#define COL_INDEX_PAL_PREV_R 6
#define COL_INDEX_PAL_PREV_G 7
#define COL_INDEX_PAL_PREV_B 8
#define COL_INDEX_PAL_CURR_Y 9


///info tree dataid
#define _ID_SEL_DEFINE 100000
#define _ID_RED_CHANNEL 10000
#define _ID_GREEN_CHANNEL 20000
#define _ID_BLUE_CHANNEL 30000
#define _ID_SEG_START         1000
#define _ID_LINE_TYPE       2000

//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////Utility functions///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

bool save_palette_to_file(string strFile, Worksheet& wks, int nRCol, int nGCol, int nBCol)
{
	
	Dataset dsR(wks, nRCol);
	Dataset dsG(wks, nGCol);
	Dataset dsB(wks, nBCol);
	vector<byte> vr(256), vg(256), vb(256);

	vr = dsR;
	vg = dsG;
	vb = dsB;
	if( 0 > okutil_palette_save(strFile, vr.GetSize(), vr, vg, vb))
		return false;
	return true;
}

bool read_palette_from_file(string strFile, vector& vr, vector& vg, vector& vb)
{
	vector<int> rgb;
   	if( okutil_palette_load(strFile, &rgb) < 0 )
   		return false;
   
   	int nSize = rgb.GetSize();
   	vr.SetSize(nSize);
   	vg.SetSize(nSize);
   	vb.SetSize(nSize);
    for( int i = 0; i < nSize; i++ )
	{
       vr[i] = GetRValue(rgb[i]);
       vg[i] = GetGValue(rgb[i]);
       vb[i] = GetBValue(rgb[i]);
	}
	
	return true;
}



static bool _create_curve(int nLineType,  vector<int>& vnX, vector<int>& vnY,int nBegin,int nEnd, int nCurrX, int nCurrY)
{
	//functional data ready
	

	vector vecSegY, vecSegX;
	vnX.GetSubVector(vecSegX, nBegin, nEnd);
	vnY.GetSubVector(vecSegY, nBegin, nEnd);
	int nSegPoints = vecSegY.GetSize();	

	switch(nLineType)
	{
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	//case 0: //constant
	case GRADIENT_KEEP_CURRENT:
		return false;

	case GRADIENT_CONST:
	///End PALETTE_EDITOR_IMPORTMENT
		double dd = nCurrY;
		vecSegY = dd;
		break;
	
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	//case 1:// line
	case GRADIENT_STRAIGHT_LINE:
	///End PALETTE_EDITOR_IMPORTMENT
		vector vx(2), vy(2);
		vx[0] = vnX[nBegin];
		vx[1] = vnX[nEnd];		
		if(abs(nBegin - nCurrX)<2 )
		{
			vy[0] = nCurrY;
			vy[1] = vnY[nEnd];
		}
		else
		{
			vy[0] =  vnY[nBegin];
			vy[1] = nCurrY;			
		}
		if( 0!= ocmath_interpolate(vecSegX, vecSegY, nSegPoints, vx, vy, vx.GetSize(), INTERP_TYPE_LINEAR))
			return false;
		break;
		
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	//case 2:// sigmoid
	case GRADIENT_SIGMOID:
	///End PALETTE_EDITOR_IMPORTMENT
		vector vx(3), vy(3);
		if(abs(nBegin - nCurrX)<2 )
		{
			vx[0] = nCurrX;
			vx[1] = vnX[(nBegin+nEnd)/2];
			vx[2] = vnX[nEnd];
			
			vy[0] = nCurrY;
			vy[1] = (vnY[nEnd]+nCurrY)/2;
			vy[2] = vnY[nEnd];
		}
		else if(abs(nEnd - nCurrX)<2 )
		{
			vx[0] = vnX[nBegin];
			vx[1] = vnX[(nBegin+nEnd)/2];
			vx[2] = nCurrX;
			
			vy[0] = vnY[nBegin];
			vy[1] = (vnY[nBegin]+nCurrY)/2;
			vy[2] = nCurrY;			
		}
		else
		{
			vx[0] = vnX[nBegin];
			vx[1] = nCurrX;
			vx[2] = vnX[nEnd];
			
			vy[0] = vnY[nBegin];
			vy[1] = nCurrY;
			vy[2] = vnY[nEnd];				
		}
	
		if(!_create_logistic_curve(vx, vy, nSegPoints, vecSegX, vecSegY))
			return false;
		break;
	default:
		return false;
	}

	vnY.SetSubVector(vecSegY, nBegin);
	
	return true;
}
static void _hide_show_no_use_subnode(TreeNode& trCh, int nNoUsedAfter, int nBranchID, bool bIsSegments = false)
{
	for(int ii = 1; ii<nNoUsedAfter; ii++)
	{
		TreeNode& trUsed = tree_find_node_by_dataID(trCh, nBranchID+ii );
		trUsed.Show = true;
		trUsed.Enable = true;
	}
	
	for(ii = nNoUsedAfter; ii<=8; ii++)
	{
		TreeNode& trNoUsed = tree_find_node_by_dataID(trCh, nBranchID+ii );
		trNoUsed.Show = false;
	}
	
	if(bIsSegments )
	{
		TreeNode& trStart = tree_find_node_by_dataID(trCh, nBranchID+1);
		TreeNode& trEnd = tree_find_node_by_dataID(trCh, nBranchID+nNoUsedAfter);
		
		trStart.Enable =trEnd.Enable = false;
		trStart.Show = trEnd.Show = (trCh.fw.nVal == 1? false: true);
		
		if(nNoUsedAfter != 9)
		{
			TreeNode& trTrueEnd = tree_find_node_by_dataID(trCh, nBranchID+9);
			trTrueEnd.Show = false;
		}

	}
	

}

///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
//static GraphObject _add_control_line(GraphLayer& gl, int nIndex, string strName)
static GraphObject _add_control_line(GraphLayer& gl, int nIndex, string strName, bool bSelectable)
{
	GraphObject go;
	add_line(gl, go, nIndex*20, 256, 2, LN_VERTICAL, true, false, nIndex*20, 0, SYSCOLOR_LTGRAY);
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	//set_LT_script(go, "_event_from_control_line(0);" , GRCT_MOVE);
	if(bSelectable)
		set_LT_script(go, "_event_from_control_line(" + nIndex + ", 0)" , GRCT_MOVE);
	else
	{
		Tree tr;
		tr = go.GetFormat(FPB_OTHER, FOB_ALL, true, true);
		if(tr.Root && tr.Root.States)
			tr.Root.States.nVal = tr.Root.States.nVal | GOC_NO_SELECT;
		else
		{
			tr.Root.States.nVal = GOC_NO_SELECT;
			go.UpdateThemeIDs(tr.Root);
		}
		go.ApplyFormat(tr, true, true);
	}
	///End PALETTE_EDITOR_IMPORTMENT
	
	make_slider(go, "_events_from_edit_silder_moving", 0, "anchor", 0.5);
	go.SetName(strName+(string)nIndex);
	go.Show(false);
	return go;
}


static bool _update_control_line(GraphLayer& gl,int nIndex,  int nX, int nYofSlider, string strName)
{
	GraphObject go = gl.GraphObjects(strName+(string)nIndex);
	set_LT_script(go, NULL, GRCT_NONE);		///Kyle 09/04/2009 QA80-14124-P1 FIX_PREVIEW_RECURSIVELY_REFRESH
	go.Show(true);
	
	go.X = nX;
	
	double dPercent = nYofSlider/256.0;
	//bool bRet = make_slider(go, "_events_from_edit_silder_moving", nX, "anchor", dPercent);
	bool bRet = modify_slider(go,  dPercent);
	set_LT_script(go, NULL, GRCT_MOVE);		///Kyle 09/04/2009 QA80-14124-P1 FIX_PREVIEW_RECURSIVELY_REFRESH
	return bRet;
	
}

///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
static bool _update_slider_color(GraphLayer& gl, int nIndex, string strName, int nColor)
{
	GraphObject go = gl.GraphObjects(strName+(string)nIndex);
	if(!go)
		return false;
	Tree tr;
	tr.Root.Anchors.Anchor2.Symbol.EdgeColor.nVal = nColor;
	int nErr = go.UpdateThemeIDs(tr.Root);
	if(nErr == 0)
		return go.ApplyFormat(tr, true, true);
	return false;
}

static bool _reinit_gradient_type_on_segments(TreeNode& trGetN)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE +  _ID_LINE_TYPE + vnChID[trGetN.ch.nVal];
	TreeNode& trChSeg = tree_find_node_by_dataID(trGetN, nBranchID );
	
	if(!trChSeg.IsValid())
		return false;

	if(trChSeg.ft.nVal)
		trChSeg.type.nVal = GRADIENT_KEEP_CURRENT;
	else
	{
		int nBranchID = _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal] +_ID_LINE_TYPE,
			nSegNum = _get_curr_channel_seg_num(trGetN);
		for(int ii=1; ii<=nSegNum; ii++)
		{
			TreeNode trLineType = tree_find_node_by_dataID(trGetN, nBranchID + ii);
			if(trLineType)
				trLineType.nVal = GRADIENT_KEEP_CURRENT;
		}
	}
	return true
}

///End PALETTE_EDITOR_IMPORTMENT

static void _hide_control_line(GraphLayer& gl,int nIndex,  string strName)
{
	GraphObject go = gl.GraphObjects(strName+(string)nIndex);
	set_LT_script(go, NULL, GRCT_NONE);		///Kyle 09/04/2009 QA80-14124-P1 FIX_PREVIEW_RECURSIVELY_REFRESH
	go.Show(false);	
	go.X = 300;// move outside
	set_LT_script(go, NULL, GRCT_MOVE);		///Kyle 09/04/2009 QA80-14124-P1 FIX_PREVIEW_RECURSIVELY_REFRESH
}

static int _get_segment_range(TreeNode& trGetN, int& nBegin, int& nEnd, int nPos, int nLastSeg)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal] +_ID_SEG_START;
	TreeNode& trChSeg = tree_find_node_by_dataID(trGetN, nBranchID);
	
	int nIndex = 1;
	int nOldIndex = 1;
	int ii = 1;
	
	int nSegNum = _get_curr_channel_seg_num(trGetN);
	bool bFinish = false;
	do
	{
		
		TreeNode& trCurr = tree_find_node_by_dataID(trChSeg, nBranchID + ii);
		TreeNode& trNext = tree_find_node_by_dataID(trChSeg, nBranchID + ii + 1);
		if(!trCurr.IsValid() || !trNext.IsValid())
			break;
		int nCurr = trCurr.nVal;
		int nNext = trNext.nVal;
		
		if((nPos>=nCurr  && nPos < nNext) || ii == nSegNum)
		{
			nBegin = nCurr;
			nEnd = nNext;
			nIndex = ii;
			break;
		}
		
		ii++;
	}
	while(ii <= nSegNum);
	
	if( (nIndex - nLastSeg) == 1 && abs(nPos - nBegin)<2)
		nIndex = nLastSeg;
	
	if( (nLastSeg - nIndex) == 1 && abs(nPos - nEnd)<2 )
		nIndex = nLastSeg;

	
	TreeNode& trCurr = tree_find_node_by_dataID(trChSeg, nBranchID + nIndex);
	TreeNode& trNext = tree_find_node_by_dataID(trChSeg, nBranchID + nIndex + 1);
	if(!trCurr.IsValid() || !trNext.IsValid())
		return false;
	nBegin = trCurr.nVal;
	nEnd = trNext.nVal;	
	
	return nIndex ;

}

static int  _get_segment_linetype(TreeNode& trGetN, int nSegInd)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal] +_ID_LINE_TYPE;
	
	TreeNode& trFixedLineType = tree_find_node_by_dataID(trGetN, nBranchID);
	if(trFixedLineType.ft.nVal == 1)
	{
		return trFixedLineType.type.nVal;
	}
		
	TreeNode& trLineType = tree_find_node_by_dataID(trGetN, nBranchID+nSegInd);
	if(trLineType)
		return trLineType.nVal;
	else
		return 0;
}

static int _get_curr_channel_seg_num(TreeNode& trGetN)
{
	vector<int> vnChDiv(3);
	vnChDiv[0] = trGetN.div_r.nVal;
	vnChDiv[1] = trGetN.div_g.nVal;
	vnChDiv[2] = trGetN.div_b.nVal;	
	return vnChDiv[trGetN.ch.nVal];
}

static bool _create_logistic_curve(const vector& vx, const vector& vy, 
						int nPoints, vector& vCurveX, vector& vCurveY)
{
	
	vy[1] = max( vy[1], min(vy[0],vy[2]));
	vy[1] = min( vy[1], max(vy[0],vy[2]));
	
	double dFactor = abs(vy[0]-vy[2])*2.0;
		
	double ym = (vy[1]-vy[2])/(vy[0]-vy[2]);
	
	double dPower = (log10(dFactor*ym/(1-ym)))/log10(2);
	
	if(dPower == NANUM)
		return false;
	
	double dX0 = pow(1.0/dFactor, 1/dPower);	
	
	for(int ii = 0; ii<nPoints; ii++)
	{
		vCurveX[ii] = (double)ii/nPoints;
		vCurveY[ii] = 1/(1+pow((vCurveX[ii]/dX0), dPower));
	}

	double aa = vx[0];
	double bb = vy[2];	
	vCurveX = (vCurveX)*(vx[2]-vx[0])+aa;
	vCurveY = (vCurveY)*(vy[0]-vy[2])+bb;
	return true;
}

static void _arrange_segments_within_used_range(TreeNode& trCh, int nNoUsedAfter, int nBranchID)
{
	TreeNode& trStart = tree_find_node_by_dataID(trCh, nBranchID+1);
	trStart.nVal = 0;
	
	TreeNode& trEnd = tree_find_node_by_dataID(trCh, nBranchID+nNoUsedAfter);
	trEnd.nVal = 255;
	
	int nDiv = nNoUsedAfter - 1;
	if(trCh.fw.nVal == 0)
	{
		///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
		//for(int ii = 2; ii<nNoUsedAfter ; ii++)
		//{		
			//TreeNode& trLast = tree_find_node_by_dataID(trCh, nBranchID + ii - 1);
			//TreeNode& trCurrTo = tree_find_node_by_dataID(trCh, nBranchID + ii);
			//TreeNode& trNext = tree_find_node_by_dataID(trCh, nBranchID + ii + 1);
			//trCurrTo.nVal  = (trCurrTo.nVal <= trLast.nVal ? trLast.nVal+1 : trCurrTo.nVal);
			//trCurrTo.nVal  = (trCurrTo.nVal >= trNext.nVal ? trNext.nVal-1 : trCurrTo.nVal);
		//}			
		///End PALETTE_EDITOR_IMPORTMENT
	}
	else// in fixed mode
	{
		trCh.width.nVal = 256/nDiv;
		trCh.width.Enable = false;
		for(int ii = 2; ii<nNoUsedAfter ; ii++)
		{		
			TreeNode& trCurrTo = tree_find_node_by_dataID(trCh, nBranchID + ii);
			trCurrTo.nVal  = trCh.width.nVal*(ii-1)-1;
		}		
	}

}


static bool _set_curr_channel_to_fixed_width(TreeNode& trGetN)
{
	
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE +  _ID_SEG_START + vnChID[trGetN.ch.nVal];
	TreeNode& trChSeg = tree_find_node_by_dataID(trGetN, nBranchID );
	
	if(!trChSeg.IsValid())
	{
		return false;
	}

	int nfwOld = trChSeg.fw.nVal;
	trChSeg.fw.nVal = 1;
	
	int nSegNum = _get_curr_channel_seg_num(trGetN);

	_arrange_segments_within_used_range(trChSeg, nSegNum+1, nBranchID);
	
	trChSeg.fw.nVal = nfwOld;
	
	return true
}
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////Class///////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////

class OCPalEdit
{
public:
	OCPalEdit(){}
	~OCPalEdit(){}
	
	bool SetUpPreviewGraph(Worksheet&wks, GraphPage& gp, TreeNode& trGetN);
	bool InitPreviewByLoading(string strFile);
	
	void UpdateGetNTree(TreeNode& trGetN, TreeNode& trNode = NULL);
	void ConvertOColor2RGBCol();
	
	bool UpdateSegmentLines(TreeNode& trGetN);
	bool UpdateCurrSegmentInfo(TreeNode& trGetN, bool bFromSlider = false, bool bFormControlLine = false);
	bool UpdateRect(TreeNode& trGetN);
	bool UpdatePreviewBySliders(TreeNode& trGetN);
	
	bool ApplyCurr(int nChannel, bool bToCurr = true);
	void ApplyPreviewData();
	bool ApplyColorBar();
	
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	void ReInitGetNTree(TreeNode& trGetN, bool bNew);
	bool UpdateCurrColor(int nCurrChannel = 0);
	bool UpdatePreviewOnType(TreeNode& trGetN, int nSegIndex);
	bool GetSegmentsStart(TreeNode& trGetN, vector<int>& vnStarts);
	bool SetSegmentsStart(TreeNode& trGetN, int nIndex, int nPos);
	bool OnFixLineType(TreeNode& trGetN);
	bool OnMoveSegmentLine(TreeNode& trGetN, int nIndex);
	///End PALETTE_EDITOR_IMPORTMENT
	
private:
	bool setUpDataset();
	bool setupSegmentLines(TreeNode& trGetN);
	
private:
	Worksheet m_wks;
	GraphPage m_gp;
	GraphLayer m_gl1; //for control 
	GraphLayer m_gl2;//for color spectrum
	int m_nPlotCurr;							///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT

};




bool OCPalEdit::InitPreviewByLoading(string strFile)
{
	m_wks.SetSize(256,COL_INDEX_PAL_CURR_Y+1, true);
	Dataset dsR(m_wks, COL_INDEX_PAL_PREV_R);
	Dataset dsG(m_wks, COL_INDEX_PAL_PREV_G);
	Dataset dsB(m_wks, COL_INDEX_PAL_PREV_B);
	Dataset dsX(m_wks, COL_INDEX_PAL_X);
	dsX.Data(0,255, 1);	

	return read_palette_from_file(strFile,dsR, dsG, dsB);

}



void OCPalEdit:: ApplyPreviewData()
{
	Dataset dsPreR(m_wks, COL_INDEX_PAL_PREV_R);
	Dataset dsPreG(m_wks, COL_INDEX_PAL_PREV_G);
	Dataset dsPreB(m_wks, COL_INDEX_PAL_PREV_B);	
	
	Dataset dsR(m_wks, COL_INDEX_PAL_R);
	Dataset dsG(m_wks, COL_INDEX_PAL_G);
	Dataset dsB(m_wks, COL_INDEX_PAL_B);
	
	dsR.SetSize(dsPreR.GetSize());
	dsG.SetSize(dsPreG.GetSize());
	dsB.SetSize(dsPreB.GetSize());
	
	dsR = dsPreR;
	dsG = dsPreG;
	dsB = dsPreB;
}

///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
void OCPalEdit::ReInitGetNTree(TreeNode& trGetN, bool bNew)
{
	//trGetN.ch.nVal = 0;		// default channel

	int nSegNum = 8;
	trGetN.div_r.nVal = nSegNum;
	trGetN.div_g.nVal = nSegNum;
	trGetN.div_b.nVal = nSegNum;

	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};

	int nBranchID;

	TreeNode tr = trGetN.seg_w;
	for(int ii = 0; ii<vnChID.GetSize(); ii ++)
	{
		nBranchID =  _ID_SEL_DEFINE +  _ID_SEG_START + vnChID[ii];
		TreeNode trChSeg = tree_find_node_by_dataID(tr, nBranchID );
		if(trChSeg)
		{
			trChSeg.fw.nVal = 1;
			trChSeg.width.nVal = 32;
		}
	}

	tr = trGetN.seg_t;
	int nDefLineType = bNew ? GRADIENT_STRAIGHT_LINE : GRADIENT_KEEP_CURRENT;
	for( ii = 0; ii < vnChID.GetSize(); ii ++)
	{
		int nBranchID =  _ID_SEL_DEFINE +  _ID_LINE_TYPE + vnChID[ii];
		TreeNode trChLineType = tree_find_node_by_dataID(tr, nBranchID );

		if(trChLineType)
		{
			trChLineType.ft.nVal = 0;
			trChLineType.type.nVal = GRADIENT_KEEP_CURRENT;
			
			for(int nSegIndex = 1; nSegIndex <= nSegNum; nSegIndex ++)
			{
				TreeNode trSegLineType = tree_find_node_by_dataID(tr, nBranchID + nSegIndex);
				if(trSegLineType)
					trSegLineType.nVal = nDefLineType;
			}
		}
	}
}

bool OCPalEdit::OnFixLineType(TreeNode& trGetN)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal] +_ID_LINE_TYPE;
	
	int nSegNum = _get_curr_channel_seg_num(trGetN);
	TreeNode trFixedLineType = tree_find_node_by_dataID(trGetN, nBranchID);
	if(trFixedLineType.ft.nVal)	// check
	{
		int nSegLineType = -1;
		for(int ii=1; ii <= nSegNum; ii++)
		{
			TreeNode trLineType = tree_find_node_by_dataID(trGetN, nBranchID + ii);
			if(trLineType)
			{
				if(nSegLineType < 0)
					nSegLineType = trLineType.nVal;
				else if(nSegLineType != trLineType.nVal)
					nSegLineType = GRADIENT_KEEP_CURRENT;
			}
		}
		trFixedLineType.type.nVal = nSegLineType;
	}
	else
	{
		int nFixedLineType = trFixedLineType.type.nVal;
		for(int ii=1; ii<=nSegNum; ii++)
		{
			TreeNode trLineType = tree_find_node_by_dataID(trGetN, nBranchID + ii);
			if(trLineType)
				trLineType.nVal = nFixedLineType;
		}
	}
	return true;
}
bool OCPalEdit::GetSegmentsStart(TreeNode& trGetN, vector<int>& vnStarts)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal];
	TreeNode trChSeg = tree_find_node_by_dataID(trGetN, nBranchID + _ID_SEG_START );

	if(!trChSeg.IsValid())
		return false;

	int nSegNum = _get_curr_channel_seg_num(trGetN);
	if(nSegNum < 1)
		return false;
	vnStarts.SetSize(nSegNum + 1);

	for(int ii = 1; ii<=nSegNum + 1; ii++)
	{
		TreeNode trSeg = tree_find_node_by_dataID(trChSeg, nBranchID + _ID_SEG_START + ii);
		if(!trSeg.IsValid())
			return false;

		vnStarts[ii-1] = trSeg.nVal;
	}
	return true;
}

bool OCPalEdit::SetSegmentsStart(TreeNode& trGetN, int nIndex, int nPos)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal];
	TreeNode trChSeg = tree_find_node_by_dataID(trGetN, nBranchID + _ID_SEG_START );

	if(!trChSeg.IsValid())
		return false;
	
	if(trChSeg.fw.nVal)
		return false;

	int nSegNum = _get_curr_channel_seg_num(trGetN);
	if(nSegNum < 1)
		return false;

	if(nIndex <= 1 || nIndex > nSegNum)				// the first one (1) and the last one (nSegNum + 1) can't be moved
		return false;
	
	TreeNode trCurrSeg = tree_find_node_by_dataID(trChSeg, nBranchID + _ID_SEG_START + nIndex);
	TreeNode trPrevSeg = tree_find_node_by_dataID(trChSeg, nBranchID + _ID_SEG_START + nIndex - 1);
	TreeNode trNextSeg = tree_find_node_by_dataID(trChSeg, nBranchID + _ID_SEG_START + nIndex + 1);
	if(!trCurrSeg.IsValid() || !trPrevSeg.IsValid() || !trNextSeg.IsValid())
		return false;
	
	if(nPos <= trPrevSeg.nVal || nPos >= trNextSeg.nVal )
		return false;
	
	trCurrSeg.nVal = nPos;

	UpdatePreviewOnType(trGetN, nIndex - 1);
	UpdatePreviewOnType(trGetN, nIndex);

	return false;

}

bool OCPalEdit::OnMoveSegmentLine(TreeNode& trGetN, int nIndex)	// nIndex 1 offset
{
	GraphObject go = m_gl1.GraphObjects(SEGMENT_LINE_NAME + (string)nIndex);
	if(!go)
		return false;
	int nNewPos = (int)(go.X + 0.5);
	return SetSegmentsStart(trGetN, nIndex, nNewPos);
}

bool OCPalEdit::UpdatePreviewOnType(TreeNode& trGetN, int nSegIndex)
{
	if(!m_gl1.IsValid())
		return false;
	
	//curr dataset ready
	Dataset dsX(m_wks, COL_INDEX_PAL_X);
	Dataset dsCurrY(m_wks, COL_INDEX_PAL_CURR_Y);
	if(!dsCurrY.IsValid() || dsCurrY.GetSize() == 0)
		return false;
	vector<int> vnY = dsCurrY;
	vector<int> vnX = dsX;

	vector<int> vnStarts;
	if(!GetSegmentsStart(trGetN, vnStarts))
		return false;

	int nSegs = vnStarts.GetSize() - 1;
	if(nSegIndex <= 0)
	{
		for(int ii=0; ii<nSegs; ii++)
		{
			int nLineType = _get_segment_linetype(trGetN, ii + 1);
			int nBegin, nEnd;

			if(ii==0)
			{
				nBegin = vnStarts[0];
				nEnd = vnStarts[1];
			}
			else if(ii==nSegs-1)
			{
				nBegin = vnStarts[nSegs - 1] + 1;
				nEnd = vnStarts[nSegs];
			}
			else
			{
				nBegin = vnStarts[ii] + 1;
				nEnd = vnStarts[ii + 1];
			}
			_create_curve(nLineType, vnX, vnY, nBegin, nEnd, vnX[nBegin], vnY[nBegin]);
			dsCurrY = vnY;
		}
	}
	else if(nSegIndex <= nSegs)
	{
		int nLineType = _get_segment_linetype(trGetN, nSegIndex);
		int nBegin, nEnd;

		if(nSegIndex==1)
		{
			nBegin = vnStarts[0];
			nEnd = vnStarts[1];
		}
		else if(nSegIndex==nSegs)
		{
			nBegin = vnStarts[nSegs - 1] + 1;
			nEnd = vnStarts[nSegs];
		}
		else
		{
			nBegin = vnStarts[nSegIndex - 1] + 1;
			nEnd = vnStarts[nSegIndex];
		}
		_create_curve(nLineType, vnX, vnY, nBegin, nEnd, vnX[nBegin], vnY[nBegin]);
		dsCurrY = vnY;
	}
	else
		return false;
	
	return true;
}
///End PALETTE_EDITOR_IMPORTMENT

bool OCPalEdit::UpdatePreviewBySliders(TreeNode& trGetN)
{
	if(!m_gl1.IsValid())
		return false;
	
	//curr dataset ready
	Dataset dsX(m_wks, COL_INDEX_PAL_X);
	Dataset dsCurrY(m_wks, COL_INDEX_PAL_CURR_Y);
	if(!dsCurrY.IsValid() || dsCurrY.GetSize() == 0)
		return false;
	
	//info from slider ready
	HWND hwnd;
	Tree trStorge;
	load_GetN_from_page(m_gp, trStorge,  hwnd, STR_STORAGE_NAME);	
	if(!trStorge.currY || !trStorge.currX || trStorge.currX.nVal > dsCurrY.GetSize())
		return false;
	
	//get segment range(begin, end) and function(Line Type)
	int nBegin =  trStorge.currBegin.nVal;
	int nEnd =  trStorge.currEnd.nVal;
	int nSegInd = trStorge.currIndex.nVal;
	int nCurrY = trStorge.currY.nVal;
	int nCurrX = trStorge.currX.nVal;
	
	int nLineType = _get_segment_linetype(trGetN, nSegInd);

	
	vector<int> vnY = dsCurrY;
	vector<int> vnX = dsX;
	
	_create_curve(nLineType, vnX, vnY,nBegin, nEnd, nCurrX, nCurrY);
	dsCurrY = vnY;
	
	return true;
}


bool OCPalEdit::UpdateCurrSegmentInfo(TreeNode& trGetN, bool bFromSlider, bool bFormControlLine)
{
	if(!m_gl1.IsValid())
		return false;	
		
	HWND hwnd;
	Tree trStorge;
	load_GetN_from_page(m_gp, trStorge,  hwnd, STR_STORAGE_NAME);	
	if(trStorge.currIndex)
		trStorge.lastIndex.nVal = trStorge.currIndex.nVal;
		
	GraphObject goRect = m_gl1.GraphObjects(SEG_RECT_NAME);
	
	if(!goRect)
		return false;
	
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal] +_ID_SEG_START;
	TreeNode& trChSeg = tree_find_node_by_dataID(trGetN, nBranchID);	
	
	int nCenter, nPos;
	nCenter = goRect.X;
	
	if(bFromSlider && trStorge.currX)
	{
		nPos = trStorge.currX.nVal;
	}
	else
	{
		nPos = nCenter;
	}	

	int nSegNum = _get_curr_channel_seg_num(trGetN);
	
	int ii = 1;
	int nLeft, nRight, nIndex;
	int nCurr, nNext;
	do
	{
		
		TreeNode& trCurr = tree_find_node_by_dataID(trChSeg, nBranchID + ii);
		TreeNode& trNext = tree_find_node_by_dataID(trChSeg, nBranchID + ii + 1);
		if(!trCurr.IsValid() || !trNext.IsValid())
			break;
		nCurr = trCurr.nVal;
		nNext = trNext.nVal;
		
		if((nPos>=nCurr  && nPos <= nNext)|| ii == nSegNum)
		{
			nIndex = ii;
			break;
		}
		
		ii++;
	}
	while(ii <= nSegNum);

	///Kyle 02/10/2010 QA80-15103 FIX_ACCESS_TREENODE_NOT_EXIST_RUNTIME_ERROR
	//if(abs(nPos-nCurr)<2 && (ii - trStorge.lastIndex.nVal == 1))
	//{
		//nIndex = nIndex - 1;
	//}
	//if(abs(nPos-nNext)<2 && (trStorge.lastIndex.nVal - ii == 1))
	//{
		//nIndex = nIndex + 1;
	//}
	if( trStorge.lastIndex )
	{
		if(abs(nPos-nCurr)<2 && (nIndex - trStorge.lastIndex.nVal == 1))
		{
			nIndex = nIndex - 1;
		}
		if(abs(nPos-nNext)<2 && (trStorge.lastIndex.nVal - nIndex == 1))
		{
			nIndex = nIndex + 1;
		}
	}
	///End FIX_ACCESS_TREENODE_NOT_EXIST_RUNTIME_ERROR
	
	TreeNode& trCurr = tree_find_node_by_dataID(trChSeg, nBranchID + nIndex);
	TreeNode& trNext = tree_find_node_by_dataID(trChSeg, nBranchID + nIndex + 1);
	if(trCurr.IsValid() || trNext.IsValid())
	{
			
		trStorge.currBegin.nVal = (trCurr.nVal == 0? 0: trCurr.nVal+1);
		trStorge.currEnd.nVal = trNext.nVal;

	}
	
	
	//recorde to storge
	if(bFromSlider && trStorge.currX)
	{
		trStorge.currX.nVal = min(trStorge.currEnd.nVal, trStorge.currX.nVal);
		trStorge.currX.nVal = max(trStorge.currBegin.nVal, trStorge.currX.nVal);
	}
	
	trStorge.currIndex.nVal = nIndex;
	save_GetN_to_page(m_gp, trStorge,  hwnd, STR_STORAGE_NAME);
	
	return true;

}


bool OCPalEdit::ApplyColorBar()
{
	DataPlot dp;
	return plot_color_spectrum(dp, m_gl2, m_wks, COL_INDEX_PAL_X, COL_INDEX_PAL_SPY, COL_INDEX_PAL_SPC);
}

bool OCPalEdit::ApplyCurr(int nChannel, bool bToCurr)
{
	Dataset dsCurrY(m_wks, COL_INDEX_PAL_CURR_Y);
	Dataset dsPreR(m_wks, COL_INDEX_PAL_PREV_R);
	Dataset dsPreG(m_wks, COL_INDEX_PAL_PREV_G);
	Dataset dsPreB(m_wks, COL_INDEX_PAL_PREV_B);
	if(!dsCurrY.IsValid() || !dsPreR.IsValid() ||  !dsPreG.IsValid() ||!dsPreB.IsValid())
		return false;
		
	if(bToCurr)
	{
		dsCurrY.SetSize(dsPreR.GetSize());		
		if(nChannel == 0)
			dsCurrY = dsPreR;
		else if(nChannel == 1)
			dsCurrY = dsPreG;
		else
			dsCurrY = dsPreB;	
	}
	else
	{				
		if(nChannel == 0)
		{
			dsPreR.SetSize(dsCurrY.GetSize());
			dsPreR = dsCurrY;
		}
		else if(nChannel == 1)
		{
			dsPreG.SetSize(dsCurrY.GetSize());
			dsPreG = dsCurrY;
		}
		else
		{
			dsPreB.SetSize(dsCurrY.GetSize());
			dsPreB = dsCurrY;
		}		
	}
	return true;
}


bool OCPalEdit::UpdateRect(TreeNode& trGetN)
{
	if(!m_gl1.IsValid())
		return false;	
		
	GraphObject goRect = m_gl1.GraphObjects(SEG_RECT_NAME);
	//set_go_behind_data(goRect);
	if(!goRect)
		return false;
	set_LT_script(goRect, NULL, GRCT_NONE);		///Kyle 09/04/2009 QA80-14124-P1 FIX_PREVIEW_RECURSIVELY_REFRESH
	HWND hwnd;
	Tree trStorge;
	load_GetN_from_page(m_gp, trStorge,  hwnd, STR_STORAGE_NAME);	

	bool bRet = false;
	if(trStorge.currBegin && trStorge.currEnd)
	{
		int nBegin = trStorge.currBegin.nVal;
		int nRight = trStorge.currEnd.nVal;
		bRet = rect_move(goRect, nBegin, 256, UNITS_SCALE,nRight, 0);
		bRet = rect_move(goRect, nBegin, 256, UNITS_SCALE,nRight, 0);

	}
	set_LT_script(goRect, NULL, GRCT_MOVE);		///Kyle 09/04/2009 QA80-14124-P1 FIX_PREVIEW_RECURSIVELY_REFRESH

	return bRet;
}


bool OCPalEdit::UpdateSegmentLines(TreeNode& trGetN)
{

	for(int ii = 1; ii<=8; ii++)
	{
		_hide_control_line(m_gl1, ii, ADJUST_LINE_NAME);
	}	
	
	//data ready
	Dataset dsCurrY(m_wks, COL_INDEX_PAL_CURR_Y);
	if(!dsCurrY.IsValid() || dsCurrY.GetSize() == 0)
		return false;
	vector vnY = dsCurrY;	
	
	//segment and functional info ready
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nBranchID =  _ID_SEL_DEFINE + vnChID[trGetN.ch.nVal];
	TreeNode& trChSeg = tree_find_node_by_dataID(trGetN, nBranchID + _ID_SEG_START );
	TreeNode& trLineType = tree_find_node_by_dataID(trGetN, nBranchID +  _ID_LINE_TYPE );
	
	if(!trChSeg.IsValid() || !trLineType.IsValid())
	{
		return false;
	}

	int nSegNum = _get_curr_channel_seg_num(trGetN);
	int nFixdLineType = trLineType.type.nVal;
	
	//find the curr segment and moidfy the end control line to the segment end
	//GraphPage gp = m_gl1.GetPage();
	HWND hwnd;
	Tree trStorge;
	load_GetN_from_page(m_gp, trStorge,  hwnd, STR_STORAGE_NAME);	

	int nCurrEnd;
	if(trStorge.currIndex && trStorge.currIndex.nVal != 0)
	{
		nCurrEnd = trStorge.currIndex.nVal+1;
	}
	//
	for(ii = 1; ii<=nSegNum+1; ii++)
	{
		//add segment line
		TreeNode& trSeg = tree_find_node_by_dataID(trChSeg, nBranchID + _ID_SEG_START + ii);
		if(trSeg.IsValid() && trSeg.nVal<vnY.GetSize())
		{
			//if(nCurrEnd == 0 || nCurrEnd != ii)
				////_update_control_line(m_gl1, ii,  trSeg.nVal, vnY[trSeg.nVal], SEGMENT_LINE_NAME);
				//_update_control_line(m_gl1, ii,  trSeg.nVal, vnY[trSeg.nVal], SEGMENT_LINE_NAME);
			//else//current segment end should be the next begin-1
				//_update_control_line(m_gl1, ii,  trSeg.nVal-1, vnY[trSeg.nVal-1], SEGMENT_LINE_NAME);
				_update_control_line(m_gl1, ii,  trSeg.nVal, vnY[trSeg.nVal], SEGMENT_LINE_NAME);
		}
		
		//add functional line if needing 
		int nLineType = nFixdLineType;
		if(trLineType.ft.nVal != 1)
		{
			TreeNode& trFunc = tree_find_node_by_dataID(trLineType, nBranchID +  _ID_LINE_TYPE + ii);
			if(trFunc.IsValid())
				nLineType = trFunc.nVal;
		}
		///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
		//if((nLineType == 0 ||nLineType == 2) && ii != nSegNum+1)
		if((nLineType == GRADIENT_CONST ||nLineType == GRADIENT_SIGMOID) && ii != nSegNum+1)
		///End PALETTE_EDITOR_IMPORTMENT
		{
			TreeNode& trSegEnd = tree_find_node_by_dataID(trChSeg, nBranchID + _ID_SEG_START + ii +1);
			int nMean = (trSegEnd.nVal + trSeg.nVal)/2;
			//_add_adjust_lines(gl,ii,  nMean, vnY[nMean]);
			_update_control_line(m_gl1, ii,  nMean, vnY[nMean], ADJUST_LINE_NAME);
			//_add_one_line_slider(gl, nMean, vnY[nMean], true);
		}
	}
	
	
	//hide the remain control line
	for(ii = nSegNum+2; ii<=9; ii++)
	{
		_hide_control_line(m_gl1, ii, SEGMENT_LINE_NAME);
	}
	
	return true;
	
}


bool OCPalEdit::setupSegmentLines(TreeNode& trGetN)
{
	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};

	TreeNode& tr = trGetN.seg_w;
	int nBranchID =  _ID_SEL_DEFINE +  _ID_SEG_START + vnChID[trGetN.ch.nVal];
	TreeNode& trChSeg = tree_find_node_by_dataID(tr, nBranchID );
	if(!trChSeg)
		return false;
	
	for(int ii = 1; ii<=9; ii++)
		///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
		//_add_control_line(m_gl1, ii, SEGMENT_LINE_NAME);
		_add_control_line(m_gl1, ii, SEGMENT_LINE_NAME, true);
		///End PALETTE_EDITOR_IMPORTMENT
	
	for(ii = 1; ii<=8; ii++)
		///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
		//_add_control_line(m_gl1, ii, ADJUST_LINE_NAME);
		_add_control_line(m_gl1, ii, ADJUST_LINE_NAME, false);
		///End PALETTE_EDITOR_IMPORTMENT
	
	return true;
}

bool OCPalEdit::setUpDataset()
{
	if(!m_wks)
		return false;
	
	m_wks.SetSize(256,COL_INDEX_PAL_CURR_Y+1);
	
	Dataset dsX(m_wks, COL_INDEX_PAL_X);
	dsX.Data(0,255, 1);

	Dataset dsRed(m_wks, COL_INDEX_PAL_PREV_R);
	Dataset dsGreen(m_wks, COL_INDEX_PAL_PREV_G);
	Dataset dsBlue(m_wks, COL_INDEX_PAL_PREV_B);
	Dataset dsCurr(m_wks, COL_INDEX_PAL_CURR_Y);	

	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	Tree trFormat;
	trFormat.Root.Line.Width.dVal = 2;
	///End PALETTE_EDITOR_IMPORTMENT
	
	Curve curRed(dsRed.GetName());
	int nPlot = m_gl1.AddPlot(curRed, IDM_PLOT_LINE);
	DataPlot dpr = m_gl1.DataPlots(nPlot);
	dpr.SetColorRGB(0xFF, 0x00, 0x00, TRUE);
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	dpr.UpdateThemeIDs(trFormat.Root);
	dpr.ApplyFormat(trFormat, true, true);
	///End PALETTE_EDITOR_IMPORTMENT
	
	Curve curGreen(dsGreen.GetName());
	nPlot = m_gl1.AddPlot(curGreen, IDM_PLOT_LINE);
	DataPlot dpg = m_gl1.DataPlots(nPlot);
	dpg.SetColorRGB(0x00, 0xFF, 0x00, TRUE);
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	dpg.UpdateThemeIDs(trFormat.Root);
	dpg.ApplyFormat(trFormat, true, true);
	///End PALETTE_EDITOR_IMPORTMENT
	
	Curve curBlue(dsBlue.GetName());
	nPlot = m_gl1.AddPlot(curBlue, IDM_PLOT_LINE);
	DataPlot dpb = m_gl1.DataPlots(nPlot);
	dpb.SetColorRGB(0x00, 0x00, 0xFF, TRUE);
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	dpb.UpdateThemeIDs(trFormat.Root);
	dpb.ApplyFormat(trFormat, true, true);
	///End PALETTE_EDITOR_IMPORTMENT
	
	//preview plot
	Curve curCurr(dsCurr.GetName());
	nPlot = m_gl1.AddPlot(curCurr, IDM_PLOT_LINE);
	DataPlot dpCurr = m_gl1.DataPlots(nPlot);
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
	//dpCurr.SetColorRGB(0x07, 0x07, 0x07, TRUE);
	m_nPlotCurr = nPlot;
	trFormat.Root.Line.Width.dVal = 5;
	dpCurr.UpdateThemeIDs(trFormat.Root);
	dpCurr.ApplyFormat(trFormat, true, true);
	///End PALETTE_EDITOR_IMPORTMENT
	
	return true;
}


bool OCPalEdit::SetUpPreviewGraph(Worksheet&wks, GraphPage& gp, TreeNode& trGetN)
{
	
	m_wks = wks;
	m_gp = gp;

	string strTemplate ="editPalTemplate";
	///Jasmine 08/13/2010 ORG-172-S2 CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL
	//page_load(gp, strTemplate, NOCLICK_DATA_PLOT | NOCLICK_TICKLABEL | NOCLICK_LAYER | NOCLICK_LAYERICON | NOCLICK_AXES);
	page_load(gp, strTemplate, OC_PREVIEW_NOCLICK_NOZOOMPAN);
	///End CENTRALIZE_NOCLICK_BIT_FOR_PREVIEW_IN_OC_TOOL

	if(!m_gp.IsValid() || !m_wks.IsValid())
		return false;
	
	m_gl1 = gp.Layers(0);
	m_gl2 = gp.Layers(1);
	
	//remove all graph dataplot
	if(!m_gl1 || !m_gl2)
		return false;
	///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT, not show Apply button on preview
	/////sandy 2007-10-19 add
	//GraphObject goBtn = m_gl2.GraphObjects("ApplyBtn");
	//if(goBtn)
		//goBtn.Text =_L("Apply");
	/////end
	///End PALETTE_EDITOR_IMPORTMENT
	
	int nPlots = m_gl1.DataPlots.Count();
	for(int ii = 0; ii < nPlots; ii++)
		m_gl1.RemovePlot(0);
	
	nPlots = m_gl2.DataPlots.Count();
	for(ii = 0; ii < nPlots; ii++)
		m_gl2.RemovePlot(0);	
	
	if(setUpDataset() && setupSegmentLines(trGetN))
		return true;
	else
		return false;
	
}
void OCPalEdit::ConvertOColor2RGBCol()
{

	Dataset dsRGB(m_wks, COL_INDEX_PAL_SPC);
	Dataset dsSpectrumY(m_wks, COL_INDEX_PAL_SPY);
	Dataset dsR(m_wks, COL_INDEX_PAL_PREV_R);
	Dataset dsG(m_wks, COL_INDEX_PAL_PREV_G);
	Dataset dsB(m_wks, COL_INDEX_PAL_PREV_B);
	
	int nSize = dsR.GetSize();
	dsRGB.SetSize(nSize);
	for(int ii = 0; ii< nSize; ii++)
	{
		dsRGB[ii] = MergeRGB(dsR[ii], dsG[ii], dsB[ii]);
 
	}
	dsSpectrumY.SetSize(nSize);
	dsSpectrumY = 1;
	
	//dsSpectrumY.Data(1,nSize , 1);
	

}

void OCPalEdit::UpdateGetNTree(TreeNode& trGetN, TreeNode& trNode)
{
	//copy treenode to getN
	if(trNode.IsValid())
	{
		int nDataID = trNode.DataID;
		if(nDataID > _ID_SEL_DEFINE)
		{
			TreeNode& trChange = tree_find_node_by_dataID(trGetN, nDataID);
			trChange.nVal = trNode.nVal;
		}
	}
	
	
	trGetN.seg_w.Show = false;
	trGetN.seg_t.Show = false;
	trGetN.load.Enable = false;
	
	trGetN.div_r.Enable = (trGetN.ch.nVal == 0 ? true : false);
	trGetN.div_g.Enable = (trGetN.ch.nVal == 1 ? true : false);
	trGetN.div_b.Enable = (trGetN.ch.nVal == 2 ? true : false);

	vector<int> vnChID = {_ID_RED_CHANNEL, _ID_GREEN_CHANNEL, _ID_BLUE_CHANNEL};
	int nSegNum = _get_curr_channel_seg_num(trGetN);
	TreeNode& tr = trGetN.seg_w;
	tr.Show = true;
	int nBranchID;
	for(int ii = 0; ii<vnChID.GetSize(); ii ++)
	{
		nBranchID =  _ID_SEL_DEFINE +  _ID_SEG_START + vnChID[ii];
		TreeNode& trChSeg = tree_find_node_by_dataID(tr, nBranchID );
		if(trChSeg)
		{
			if(ii == trGetN.ch.nVal)
			{
				trChSeg.Show = true;
				trChSeg.width.Show = (trChSeg.fw.nVal == 1? true: false);
				
				if(trChSeg.fw.nVal == 1)
				{
					_hide_show_no_use_subnode(trChSeg, 1, nBranchID, true);				
				}
				else
				{
					_hide_show_no_use_subnode(trChSeg, nSegNum+1, nBranchID , true);
				}
				
				_arrange_segments_within_used_range(trChSeg, nSegNum+1, nBranchID);
					
				
			}
			else
			{
				trChSeg.Show = false;
			}
		}
	}		

	tr = trGetN.seg_t;
	tr.Show = true;
	for( ii = 0; ii<vnChID.GetSize(); ii ++)
	{
		int nBranchID =  _ID_SEL_DEFINE +  _ID_LINE_TYPE + vnChID[ii];
		TreeNode& trChLineType = tree_find_node_by_dataID(tr, nBranchID );
	
		if(trChLineType)
		{
			if(ii == trGetN.ch.nVal)
			{
				trChLineType.Show = true;
				trChLineType.type.Show = (trChLineType.ft.nVal == 1? true: false);
				if(trChLineType.ft.nVal == 1)
				{
					_hide_show_no_use_subnode(trChLineType, 1, nBranchID );	
				}
				else
				{
					_hide_show_no_use_subnode(trChLineType, nSegNum+1, nBranchID );	
				}

			}
			else
			{
				trChLineType.Show = false;
			}
		}
	}

	
}

///Kyle 02/11/2009 QA80-13002 PALETTE_EDITOR_IMPORTMENT
bool OCPalEdit::UpdateCurrColor(int nCurrChannel)
{
	DataPlot dpCurr = m_gl1.DataPlots(m_nPlotCurr);
	if(!dpCurr)
		return false;

	int nColor;
	if(nCurrChannel == 0)
		nColor = SYSCOLOR_RED;
	else if(nCurrChannel == 1)
		nColor = SYSCOLOR_GREEN;
	else
		nColor = SYSCOLOR_BLUE;

	dpCurr.SetColor(nColor);

	for(int ii = 1; ii<=9; ii++)
		_update_slider_color(m_gl1, ii, SEGMENT_LINE_NAME, nColor);
	
	for(ii = 1; ii<=8; ii++)
		_update_slider_color(m_gl1, ii, ADJUST_LINE_NAME, nColor);
	
	return true;
}
///End PALETTE_EDITOR_IMPORTMENT

#endif
