#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	axis_bottom,
	axis_top,
	axis_right,
	axis_left,
};
///////////////////////////////////////////////////////////////////////
//////// modification log
/// Hong 03/23/07 v8.0588 MORE_OPTION_ALLOW_NOT_RESCALE_ON_INIT
///////////////////////////////////////////////////////////////////////

#include <GetNbox.h>
//put additional include files here
#include <..\originlab\grobj_utils.h>

#ifdef _FOR_SMART_LOADING_ONLY
#include <..\originlab\AxisScrollbar.h>
#endif //_FOR_SMART_LOADING_ONLY

//put your own support static functions here
// return true only if layer has data and has been examined
static bool get_data_x_range(const GraphLayer& gl, double& x1, double& x2)
{
	double ax1 = gl.X.From;
	double ax2 = gl.X.To;
	DataPlot dp = gl.DataPlots(0);
	if(dp)
	{
		vector vx;
		int npts = dp.GetDataPoints(0, -1, vx, NULL);
		if(npts > 0)
		{
			double min, max;
			vx.GetMinMax(min, max);
			if(ax2 > ax1)
			{
				x1 = min(ax1, min);
				x2 = max(ax2, max);
				return true;
			}
		}
	}
	x1 = ax1;
	x2 = ax2;
	return false;
}

static bool get_data_y_range(const GraphLayer& gl, double& y1, double& y2)
{
	double ay1 = gl.Y.From;
	double ay2 = gl.Y.To;
	DataPlot dp = gl.DataPlots(0);
	if(dp)
	{
		vector vy;
		int npts = dp.GetDataPoints(0, -1, NULL, vy);
		if(npts > 0)
		{
			double min, max;
			vy.GetMinMax(min, max);
			if(ay2 > ay1)
			{
				y1 = min(ay1, min);
				y2 = max(ay2, max);
				return true;
			}
		}
	}
	y1 = ay1;
	y2 = ay2;
	return false;
}

static void auto_update_begin_and_end(TreeNode& trGetN)
{
	TreeNode trx1 = trGetN.begin;
	TreeNode trx2 = trGetN.end;
	bool bAutoX1=octree_get_auto_support(&trx1)==1?true:false;
	bool bAutoX2=octree_get_auto_support(&trx2)==1?true:false;
	/// Hong 03/07/07 QA80-9286-S11 CHANGE_DEFAULT_VALUE_TO_AUTO
	bool bUnassigneX1 = false, bUnassigneX2 = false;
	if( PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.begin.strVal) )
		bUnassigneX1 = true;
	if( PDS_AUTO == okutil_cvt_str_to_predefined_type(trGetN.end.strVal) )
		bUnassigneX2 = true;
	
	/// Hong 03/21/07 V8.0587 QA80-9286-P8 FIX_FAIL_AUTO_RANGE_CHANGE_AXIS
	//bAutoX1 &= bUnassigneX1;
	//bAutoX2 &= bUnassigneX2;
	bAutoX1 |= bUnassigneX1;
	bAutoX2 |= bUnassigneX2;
	/// end FIX_FAIL_AUTO_RANGE_CHANGE_AXIS
	/// end CHANGE_DEFAULT_VALUE_TO_AUTO
	if(bAutoX1 || bAutoX2)
	{
		GraphPage gp = Project.Pages();
		if(gp)
		{		
			GraphLayer gl = gp.Layers(trGetN.layer.nVal-1);
			if(gl)
			{
				double x1, x2;
				/// Hong 03/06/07 QA80-9286-S12 CHANGE_XF_GUI_OF_AXIS
				/*
				if(trGetN.x.nVal)
					get_data_x_range(gl, x1, x2);
				else
					get_data_y_range(gl, x1, x2);
				*/
				if(trGetN.axis.nVal < axis_right)
					get_data_x_range(gl, x1, x2);
				else
					get_data_y_range(gl, x1, x2);
				/// end CHANGE_XF_GUI_OF_AXIS
				if(bAutoX1)
					trGetN.begin.dVal = x1;
				if(bAutoX2)
					trGetN.end.dVal = x2;
			}
		}
	}
}

/// Iris 01/29/2007 v8.0548 CHECK_INVALID_LAYER_INDEX
static void _check_layer_index(int nLayer, bool& bOKEnable, string& strErrMsg)
{
	GraphPage gp = Project.Pages();
	if(!gp)
		return;
	
	if(nLayer <= 0 || nLayer > gp.Layers.Count() )
	{
		bOKEnable = false;
		strErrMsg = XFERR_INVALID_GRAPH_LAYER;		
	}	
}
///end CHECK_INVALID_LAYER_INDEX
/// Hong 01/29/07 ADD_VERTICAL_SUPPORT
static void _check_position_combo_string(TreeNode& trGetN)
{
	string strHorizontal("Top|Bottom"), strVertical("Right|Left");
	if( 1 == trGetN.x.nVal )
		trGetN.position.SetAttribute(STR_COMBO_ATTRIB, strHorizontal);
	else
		trGetN.position.SetAttribute(STR_COMBO_ATTRIB, strVertical);
}
/// end ADD_VERTICAL_SUPPORT

/// Hong 03/07/07 QA80-9286-S14 ADD_AUTO_LAYER_TO_ACTIVE_LAYER
static bool auto_update_layer_to_active(TreeNode& trGetN)
{
	/// Hong 03/07/07 QA80-9286-S11 CHANGE_DEFAULT_VALUE_TO_AUTO
	if( PDS_AUTO != okutil_cvt_str_to_predefined_type(trGetN.layer.strVal) )
		return false; // no need update
	/// end CHANGE_DEFAULT_VALUE_TO_AUTO
	GraphLayer gl = Project.ActiveLayer();
	if(!gl)
		return false;
	
	trGetN.layer.nVal = gl.GetIndex() + 1;

	return true;
}
/// end ADD_AUTO_LAYER_TO_ACTIVE_LAYER
		

void axis_scrollbar(const int& axis, const double& begin, const double& end, const int& layer, const int& rescale)
{
	
	GraphPage gp = Project.Pages();
	if(!gp)
		return;
	
	GraphLayer gl = gp.Layers(layer-1);
	if(!gl)
	{
		//out_str("not active graph layer");
		XF_THROW(XFERR_INVALID_GRAPH_LAYER); // Hong 01/15/07 ADD_ERROR_MESSAGE
		return;
	}
	/// Hong 03/07/07 QA80-9286-S13 MORE_PROPER_LENGTH_ANDPOSITION
	//double width = 0.05;
	//double length = 0.94;
	//double left = 0.03;
	//double margin = 0.01;
	double width = 0.03;
	double length = 0.8;
	double left = 0.12;
	double margin = 0.01;
	double offset = 0.09;
	/// end MORE_PROPER_LENGTH_ANDPOSITION
	//position = 0,1
	double top = margin;
	/// Hong 03/06/07 QA80-9286-S12 CHANGE_XF_GUI_OF_AXIS
	/*
	/// Hong 01/29/07 FIX_ERROR_POSTION_FOR_VERTICAL
	//if(position > 0)
		//top = 1 - margin - width;
	if(position > 0 && x > 0)
		top = 1 - margin - width;
	if(position < 1 && x < 1)
		left = 1 - margin - width;
	/// end FIX_ERROR_POSTION_FOR_VERTICAL
	*/
	bool x = true;
	switch( axis )
	{
	case axis_bottom:
		top = 1 - margin - width;
		break;
	case axis_top:
		break;
	case axis_right:
		x = false;
		left = 1 - margin - width;
		top += offset;// Hong 03/07/07 QA80-9286-S13 MORE_PROPER_LENGTH_ANDPOSITION
		break;
	case axis_left:
		x = false;
		/// Hong 03/07/07 QA80-9286-S13 MORE_PROPER_LENGTH_ANDPOSITION
		left = margin + width;
		top += offset;
		/// end MORE_PROPER_LENGTH_ANDPOSITION
		break;
	default:
		break;
	}
	/// end CHANGE_XF_GUI_OF_AXIS
	/// Hong 03/23/07 v8.0588 MORE_OPTION_ALLOW_NOT_RESCALE_ON_INIT
	//add_axis_scrollbar(gl, begin, end, left, top, length, width, x);
	bool bRescale = ( 1 == rescale ) ? true:false;
	add_axis_scrollbar(gl, begin, end, left, top, length, width, x, bRescale);
	/// end MORE_OPTION_ALLOW_NOT_RESCALE_ON_INIT
}

//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int axis_scrollbar_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return axis_scrollbar_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	bool	bOnTheme = 0 == lstrlen(lpcszNodeName);
	
	if(0 == lstrcmp(lpcszNodeName, "begin") || 0 == lstrcmp(lpcszNodeName, "end") || bOnTheme)
	{
		auto_update_begin_and_end(trGetN);
	}
	/// Iris 01/29/2007 v8.0548 CHECK_INVALID_LAYER_INDEX
	if(0 == lstrcmp(lpcszNodeName, "layer") || bOnTheme)
	{
		_check_layer_index(trGetN.layer.nVal, bOKEnable, strErrMsg);
		if(bOKEnable)
			auto_update_begin_and_end(trGetN);
	}
	///end CHECK_INVALID_LAYER_INDEX
	/// Hong 03/06/07 QA80-9286-S12 CHANGE_XF_GUI_OF_AXIS
	/*
	/// Hong 01/29/07 ADD_VERTICAL_SUPPORT
	if(0 == lstrcmp(lpcszNodeName, "x") || bOnTheme)
	{
		_check_position_combo_string(trGetN);
		auto_update_begin_and_end(trGetN);
	}
	/// end ADD_VERTICAL_SUPPORT
	*/
	if(0 == lstrcmp(lpcszNodeName, "axis") || bOnTheme)
	{
		auto_update_begin_and_end(trGetN);
	}
	/// end CHANGE_XF_GUI_OF_AXIS
	return true;   

}

int axis_scrollbar_make_tree(TreeNode& tr, LPCSTR lpcszVarName)
{
	return false;
}
//nGetNDialog = 0,1,2, corresponding to the XF GetN dropdown, 0 = dialog is not used
//you can change nRet to be one of XFEVT_PROCEED (defualt), XFEVT_ABORT, XFEVT_PROCEED_NO_DLG or XFEVT_PROCEED_WITH_DLG(when nGetNDialog = 0)
//nGetNDialog = -1 when Ok on GetN dialog to allow handler to preocess <auto> etc variables
//dwCntrl is combination of bits
//LTXF_FROM_GUI_MENU, LTXF_FROM_GUI_PROMPT, LTXF_FROM_AUTO_UPDATE, LTXF_FROM_FUNCTION, LTXF_THEME_USED, LTXF_CHANGE_PARAM
void axis_scrollbar_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	/// Hong 03/07/07 QA80-9286-S11 CHANGE_DEFAULT_VALUE_TO_AUTO
	//if(nGetNDialog > 0 || ((LTXF_FROM_GUI_MENU & dwCntrl) && nGetNDialog>=0))
	/// end CHANGE_DEFAULT_VALUE_TO_AUTO
	{
		auto_update_begin_and_end(trGetN);
		/// Hong 03/07/07 QA80-9286-S14 ADD_AUTO_LAYER_TO_ACTIVE_LAYER
		auto_update_layer_to_active(trGetN);
		/// end ADD_AUTO_LAYER_TO_ACTIVE_LAYER
		/// Hong 03/06/07 QA80-9286-S12 CHANGE_XF_GUI_OF_AXIS
		//_check_position_combo_string(trGetN); // Hong 01/29/07 ADD_VERTICAL_SUPPORT 
		/// end CHANGE_XF_GUI_OF_AXIS
	}
	
}
//nEventID < 0 on event, like GETNE_ON_INIT, GETNE_ON_OK etc, >0 on change from control
//return 0 to do nothing, return PEVENT_GETN_RET_TO_CLOSE to close dialog
//dwEnables = bOKEnable, bBTN1Enable, bBTN2Enable, bBTN3Enable, , can set to false to disable OK/Apply buttons
//lpcszNodeName = the trGetN TreeNode tag name that generates the event, or is  if GETNE_ON_OK etc
//strAux = optional string for XF Wizard Bar, like DLG_NEED_CHANGE_GRID etc, it will be invalid if from internal node value change event
//strErrMsg = allowing messages to be shown
int axis_scrollbar_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
