/*------------------------------------------------------------------------------*
 * File Name: 							 										*
 * Creation: 																	*
 * Purpose: OriginC Sample 										 				*
 * Copyright (c) Originlab Corp.	2003, 2004, 2005, 2006, 2007				*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/
#include <Dialog.h>
#include "nitestRes.h"	// Resource header file

enum CWChartStyles
{
    cwChartStrip = 0,
    cwChartScope = 1
};


class CNiStipChart : public Dialog
{
	
public:
	CNiStipChart() : Dialog(IDD_NI_CHART_RT, "NiTest")
	{
		m_nTimerID = 8888;
		m_nTimerTime = 200; // milliseconds
		m_nPtsPerTimer = 10;
		m_xInc = 0.3;
		m_nCurrentIndex = 0;
		m_bTimerBusy = false;
		m_dbFreq = 1;
		m_dbOffset = 0;
		
		// Use a hidden wsk to put sample data;
		m_wksHidden.Create(NULL, CREATE_HIDDEN);
		while(m_wksHidden.DeleteCol(0))	 // Remove all columns in worksheet
			;
		m_wksHidden.AddCol();
		m_wksHidden.Columns(0).SetType(OKDATAOBJ_DESIGNATION_X);
		
		// we just need two Y cols for this demo
		for(int ii = 1; ii < 3; ii++)
		{
			int jj = m_wksHidden.AddCol();
			m_wksHidden.Columns(jj).SetType(OKDATAOBJ_DESIGNATION_Y);
		}
		
		// temp matrix and vect transfer data
		m_mat_y.SetSize(2, m_nPtsPerTimer);
		m_vec_x.SetSize(m_nPtsPerTimer);
	}

	virtual int  DoModal(HWND hParent = NULL)
	{
		InitMsgMap();
		int nRet = Dialog::DoModal(hParent);
		return nRet;
	}

protected:
	
EVENTS_BEGIN
	ON_INIT(OnInitDialog)
	ON_ACTIVEX_EVENT(1, IDC_CWKNOB_NOISE, OnNoiseChange, VTS_CTRL VTS_I4 VTS_PVARIANT)
	ON_ACTIVEX_EVENT(1, IDC_CWSLIDE_UPDATE_FREQ, OnFrequencyChange, VTS_CTRL VTS_I4 VTS_PVARIANT)
	ON_ACTIVEX_EVENT(1, IDC_CWSLIDE_OFFSET, OnOffsetValueChange, VTS_CTRL VTS_I4 VTS_PVARIANT)
	ON_DESTROY(OnDestroy)
	ON_TIMER(OnTimer)
EVENTS_END
	
	BOOL OnInitDialog()
	{
		// initialize all data member of interface controls
		m_objCWMeter = GetItem(IDC_CWKNOB_PERCENT).GetActiveXControl();	
		m_objCW2DGraph = GetItem(IDC_CWGRAPH1).GetActiveXControl();
		m_objCWKnob0 = GetItem(IDC_CWKNOB_NOISE).GetActiveXControl();
		
		if(m_objCW2DGraph)
		{
			Object CWPlot = m_objCW2DGraph.Plots.Item(1);
			CWPlot.LineColor = RGB(64,127,255);
			CWPlot.LineWidth = 1;
			
			CWPlot = m_objCW2DGraph.Plots.Item(2);
			CWPlot.LineColor = RGB(255,0,0);
			CWPlot.LineWidth = 1;
			
			m_objCW2DGraph.ChartStyle = cwChartStrip;
			m_objCW2DGraph.Axes.Item("XAxis").SetMinMax(0.,30.);
		}
		
		m_dbNoise = m_objCWKnob0.Value;
		
		m_nTimerID = SetTimer(m_nTimerID, m_nTimerTime);
		return TRUE;
	}
	
	// this function is provided to stop the realtime chart from labtalk
	bool NiChartStop()
	{
		if(m_nTimerID)
		{
			KillTimer(m_nTimerID);
			m_nTimerID = 0;
			return true;
		}
		return false;
	}
	
	BOOL OnDestroy(void)
	{
		NiChartStop();
		
		// we will not destroy the wks, but to show it at the end
		m_wksHidden.GetPage().LT_execute("win -a %H");
		return true;
	}
	
	BOOL OnTimer(UINT nTimerID)
	{
		if(m_bTimerBusy)
		{
			out_str("Timer reentrance, skipped");
			return true;
		}
		m_bTimerBusy = true;
		ASSERT(nTimerID==m_nTimerID);
		
		double x0;		
		
		for(int ii = 0; ii < m_nPtsPerTimer; ii++)
		{
			x0 = m_xInc * m_nCurrentIndex;
			
			m_vec_x[ii] = x0;
			
			m_mat_y[0][ii] = YFuncCurve1(x0);
			
			m_mat_y[1][ii] = YFuncCurve2(x0);
			m_nCurrentIndex++;
		}
		
		_VARIANT	var = m_mat_y;
		m_objCW2DGraph.ChartY(var, m_xInc);
	
		
		// now save to our m_wksHidden, please note that m_vec_x was never sent over to CWGraph as ChartY
		// is the only way to make strip chart, so we must begin from 0 and increment same between 
		// each point, so x array is no used to ChartY
		if(m_wksHidden)
		{
			Dataset col_x(m_wksHidden, 0);
			col_x.Append(m_vec_x);
			
			vector vv;
			for(int ii = 0; ii < 2; ii++)
			{
				m_mat_y.GetRow(vv, ii); 
				Dataset aa(m_wksHidden, ii+1);
				aa.Append(vv);
			}
			int nPercentComplete = (long)m_nCurrentIndex/10.0;
			
			m_objCWMeter.Value = nPercentComplete;
			if(m_nTimerID && nPercentComplete >= 100)
				NiChartStop();
		}
		m_bTimerBusy = false;	
		
		return TRUE;
	}
	
	
	// when the noise is changed, the m_dbNoise will updata accordingly. 
	// The m_dbNoise will use in y_func_curve1 and y_func_curve2
	void OnNoiseChange(Control ctrl, long nPointer, _VARIANT& var)
	{
		m_dbNoise = var;
	}
	
	
	// when the noise is changed, the m_dbFreq will updata accordingly. 
	// The m_dbFreq will use in y_func_curve1 and y_func_curve2
	void OnFrequencyChange(Control ctrl, long nPointer, _VARIANT& var)
	{
		m_dbFreq = var;
	}
	
	// when the noise is changed, the m_dbOffest will updata accordingly. 
	// The m_dbOffset will use in y_func_curve2
	void OnOffsetValueChange(Control ctrl, long nPointer, _VARIANT& var)
	{
		m_dbOffset = var;
	}
	
	
	double YFuncCurve1(double x)
	{
		return m_dbNoise * Noise( m_dbFreq*x) ;
	}
	
	
	double YFuncCurve2(double x)
	{
		return m_dbOffset + m_dbNoise * Noise( m_dbFreq*x ) + 3.0 * sin( m_dbFreq * x );
	}
	
	
	double Noise(double x)
	{
		return rnd();
	}

private: 
	Worksheet 	m_wksHidden;
	matrix 		m_mat_y;
	vector 		m_vec_x;
	
	string 	m_strHiddenWksName;
	int 	m_nTimerNewTime;
	int 	m_nPtsPerTimer;
	double 	m_xInc;
	int 	m_nCurrentIndex;
	double 	m_dbNoise;
	bool 	m_bTimerBusy;
	double 	m_dbFreq;
	double 	m_dbOffset;
	
private: 
	// control objects, these are NI ActiveX controls
	Object 	m_objCWMeter;
	Object 	m_objCW2DGraph;
	Object 	m_objCWKnob0;
	
	int 	m_nTimerID;
	int 	m_nTimerTime; // milliseconds	
};



