/*------------------------------------------------------------------------------*
 * File Name:				 													*
 * Creation: CPY 1/10/03														*
 * Purpose: Origin C source file for Realtime Graphs example.					*
 * Copyright (c) Originlab Corp.	2003, 2004, 2005, 2006, 2007				*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/
#include <origin.h> 
#include <Dialog.h>      // Dialog class
#include "Graphs.h"      // Resource IDs, in same location as this C file

static Dialog MyDlg( "RealTimeGraph", "Graphs" );

// *** Dialog Event Map ***
BEGIN_EVENT_MAP
	ON_INIT( OnInitDialog ) 
	ON_SIZE( OnDlgResize )
	ON_BN_CLICKED(IDC_REALTIME_SCOPE, OnStartScope)
	ON_BN_CLICKED(IDC_REALTIME_STRIPT_CHART, OnStartChart)
	ON_DESTROY( OnDestroy )
END_EVENT_MAP

// *** Launch Dialog ***
bool RTgraph()
{
	MyDlg.DoModal();
	return true;
}

static string s_strWksName;
#define NUM_DATA_PTS 500

static BOOL OnDestroy()
{
	Worksheet wks(s_strWksName);
	if(wks)
		wks.Destroy();
	
	return TRUE;
}

	
// *** Initialize Dialog on creation ***
static BOOL OnInitDialog()
{
	// Attach to first GraphControl
	GraphControl og1 = MyDlg.GetItem( IDC_REALTIME_GRAPH );
	
	// Create Origin graph and add to first GraphControl
	og1.Create( NOCLICK_AXES | NOCLICK_TICKLABEL | NOCLICK_LAYERICON | NOCLICK_DATA_PLOT );
	
	// we will also create our worksheet with XY columns
	Worksheet wks;
	wks.Create(NULL,CREATE_HIDDEN);
	while(wks.DeleteCol(0))	 // Remove all columns in worksheet
		;
	// we don't trust the default template, so del all and recreate
	wks.AddCol();
	wks.AddCol();
	wks.Columns(0).SetType(OKDATAOBJ_DESIGNATION_X);
	wks.Columns(1).SetType(OKDATAOBJ_DESIGNATION_Y);
	wks.SetRange(0, NUM_DATA_PTS-1); // total 500 points
	Dataset aa(wks, 0);
	ASSERT(aa.GetSize() == NUM_DATA_PTS);
	double x1=-10;
	double x2 = 10;
	double inc = (x2-x1)/(NUM_DATA_PTS-1);
	aa.Data(x1,x2,inc);
	Dataset bb(wks, 1);
	bb = 0.5;
	s_strWksName = wks.GetPage().GetName();
	
	// we will also plot this into our graph
	Curve cc(wks, 0, 1);
	GraphPage gp = og1.GetPage(); // Get page
	GraphLayer gl = gp.Layers();  // Get active layer
	gl.AddPlot( cc );
	gl.Y.From = -1;
	gl.Y.To = 2;
	gl.X.From = x1;
	gl.X.To = x2;
	return true;
}

// *** Button handler, when user click button ***
static BOOL OnStartScope(Control cButton)
{
	GraphControl og1 = MyDlg.GetItem( IDC_REALTIME_GRAPH );
	GraphPage gp = og1.GetPage(); // Get page
	gp.LT_execute("set %(1,@D) -an 1"); // make sure data plot is in animate mode

	GraphLayer gl = gp.Layers();  // Get active layer
	DataPlot dp = gl.DataPlots(0);
	Dataset bb(dp.GetDatasetName());
	if(!bb)
	{
		ASSERT(FALSE);
		return TRUE;
	}
	dp.SetRange();// set to full range, incase range was not set to full before
	gp.LT_execute("plot -P");

	for(int jj = 0; jj < 10; jj++)
	{
		make_peak(jj/9.0, bb);
		
		bb.Update(FALSE, REDRAW_REALTIME_SCOPE);
		//LT_execute("sec -w 0.01;");// hard wait
	}
	return TRUE;
}


static BOOL OnStartChart(Control cButton)
{
	GraphControl og1 = MyDlg.GetItem( IDC_REALTIME_GRAPH );
	GraphPage gp = og1.GetPage(); // Get page
	gp.LT_execute("set %(1,@D) -an 0"); // make sure data plot is NOT in animate mode
	//gp.LT_execute("set %(1,@D) -tb 3"); // make sure data plot is NOT in animate mode
	gp.LT_execute("layer -b RT 1"); // we need to turn on layer realtime drawing support
	
	GraphLayer gl = gp.Layers();  // Get active layer
	DataPlot dp = gl.DataPlots(0);
	Dataset bb(dp.GetDatasetName());
	if(!bb)
	{
		ASSERT(FALSE);
		return TRUE;
	}
	// we need to use the full range of data, but we start out with range reset to 0
	bb.SetSize(NUM_DATA_PTS);// in case it was not setup correctly
	make_peak(0.5, bb); // 
	int nMax = bb.GetSize();
	int	nStepSize = nMax/50;
	bb.SetUpperIndex(-1);
	bb.Update(FALSE, REDRAW_REFRESH);

	//gp.LT_execute("plot -P"); // redraw the page
	
	LT_execute("sec -p 0.2");
	

	for(int jj = nStepSize; jj < nMax; jj+= nStepSize)
	{
		if(jj > nMax -1)
			jj = nMax -1;
		bb.SetUpperIndex(jj);		
		bb.Update(FALSE, REDRAW_REALTIME_WKS);
		// waste some time here to clearly show the curve moving
		LT_execute("sec -w 0.1");
	}
	return TRUE;
}

// make a gaussian shape with peak center around x0 (0-1)*DatasetSize
static void make_peak(double x0, Dataset& bb)
{
	int nSize = bb.GetSize();
	double xCtr = x0 * nSize;
	double xWidth = 0.05 * nSize;
	double yHeight = 1.2;
	double yNoiseLevel = 0.05;
	
	// we will make a gaussian curve with some noise
	for(int nx = 0; nx < nSize; nx++)
		bb[nx] = yNoiseLevel * rnd() + yHeight * exp(-(nx - xCtr)^2.0 / (PI*xWidth));
}
		

// *** Re-size controls on re-sized Dialog ***
// nType = SIZE_MAXIMIZED, SIZE_RESTORED etc, can be ignored
// cx and cy are width and height of dialog   
static BOOL OnDlgResize( int nType, int cx, int cy )
{	
	RECT r1;
	Window wndDlg = MyDlg.GetWindow();
	GraphControl og1 = MyDlg.GetItem( IDC_REALTIME_GRAPH );
	og1.GetWindowRect(&r1);
	wndDlg.ScreenToClient(&r1);
	int nGap = r1.left;
	r1.bottom = cy - nGap;
	r1.right = cx - nGap;
	
	og1.MoveWindow(&r1);
	
	return TRUE;
}
