#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
#include <origin.h>


void addinsetlayer(EventInfo& ei, const double& frac)
{
	// This X-Function adds an inset layer to the current
	// graph layer and plots the data in the current layer
	// defined by limits of the rectangle graph object.
	// User can then move around the rectangle object
	// to update the inset layer. User can also move the 
	// inset layer and/or resize it as desired. On deleting
	// the rectangle object, the inset layer is not deleted.
	//
	GraphObject grTool;
	ei.GetParent(grTool);
	GraphLayer glyData;
	grTool.GetParent(glyData);
	
	// Get event info
	int nEvent = ei.GetEvent();
	
	// On creation of the rectangle object...
	if (OE_INIT_ANCHORS == nEvent)
	{
		// Add a new layer by duplicating data layer
		GraphPage gpg = glyData.GetPage();
		int nInsetLayerIndex = gpg.AddLayer(glyData);
		
		// Save inset layer index to even tree
		TreeNode trUser = ei.GetUserData(true);
		trUser.InsetLayerIndex.nVal = nInsetLayerIndex;
		
		// When duplicate layer is created the XF rect
		// object also gets duplicated, so need to delete
		string strTool = grTool.GetName();
		GraphLayer glyInset = gpg.Layers(nInsetLayerIndex);	
	///Kevin 09/05/05 FIX_OTHER_OBJECT_APPEAR_IN_LAYER_BUG	
		//grobjInsetCopy.Destroy();
		//GraphObject grobjInsetCopy;
		//grobjInsetCopy = glyInset.GraphObjects(strTool);
		
		Collection<GraphObject> goColl;
		goColl = glyInset.GraphObjects;
		GraphObject goToDel;
		foreach(goToDel in goColl)
			goToDel.Destroy();
	///End FIX_OTHER_OBJECT_APPEAR_IN_LAYER_BUG	
				
		// Set units of data layer to be in inches temporarily
		int nDataLayerUnits = glyData.Dimension.Units.nVal;
		bool bSwitchedUnits = false;
		if( nDataLayerUnits != 1 )
		{
			glyData.Dimension.Units.nVal = 1;
			bSwitchedUnits = true;
		}
		
		// Get the dimensions of the data layer
		double dTop, dLeft, dWidth, dHeight;
		dTop = glyData.Dimension.Top.dVal;
		dLeft = glyData.Dimension.Left.dVal;
		dWidth = glyData.Dimension.Width.dVal;
		dHeight = glyData.Dimension.Height.dVal;
		if( bSwitchedUnits )
			glyData.Dimension.Units.nVal = nDataLayerUnits;
		
		// Set the inset layer dimensions so that it is frac * size 
		// of data layer and is at top right corner of data layer
		// Set inset layer units to be in inches
		glyInset.Dimension.Units.nVal = 1;
		glyInset.Dimension.Top.dVal = dTop;
		glyInset.Dimension.Left.dVal = dLeft + (1 - frac) * dWidth;
		glyInset.Dimension.Width.dVal = frac * dWidth;
		glyInset.Dimension.Height.dVal = frac * dHeight;
	
		// Set units of inset layer to be same as data layer
		glyInset.Dimension.Units.nVal = nDataLayerUnits;
		
		// Turn off inset layer axis labels
		GraphObject grLabel;
		grLabel = glyInset.GraphObjects("XB");
		if( grLabel )
			grLabel.Show = 0;
		grLabel = glyInset.GraphObjects("YL");
		if( grLabel )
			grLabel.Show = 0;
		grLabel = glyInset.GraphObjects("XT");
		if( grLabel )
			grLabel.Show = 0;
		grLabel = glyInset.GraphObjects("YR");
		if( grLabel )
			grLabel.Show = 0;
		
		// Turn off legend display in inset layer
		grLabel = glyInset.GraphObjects("Legend");
		if( grLabel )
			grLabel.Show = 0;
		
		// Boost the size of the inset layer axes labels
		int nSize;
		AxisObject aoX, aoY;
		aoX = glyInset.XAxis.AxisObjects(AXISOBJPOS_LABEL_FIRST);
		nSize = (int) (0.5 * aoX.BottomLabels.Font.Size.nVal / frac);
		aoX.BottomLabels.Font.Size.nVal = nSize;
		aoY = glyInset.YAxis.AxisObjects(AXISOBJPOS_LABEL_FIRST);
		nSize = (int) (0.5 * aoY.LeftLabels.Font.Size.nVal / frac);
		aoY.LeftLabels.Font.Size.nVal = nSize;
		aoX = glyInset.XAxis.AxisObjects(AXISOBJPOS_LABEL_SECOND);
		nSize = (int) (0.5 * aoX.TopLabels.Font.Size.nVal / frac);
		aoX.TopLabels.Font.Size.nVal = nSize;
		aoY = glyInset.YAxis.AxisObjects(AXISOBJPOS_LABEL_SECOND);
		nSize = (int) (0.5 * aoY.RightLabels.Font.Size.nVal / frac);
		aoY.RightLabels.Font.Size.nVal = nSize;
	
		// Prompt user to move rectangle as desired	
		SetDataDisplayText("Move rectangle to update inset graph");	
		shape_tool_init(grTool);
	
	}
	
	// On Init, Move, and Resize...
	if( OE_INIT_ANCHORS == nEvent || OE_MOVE == nEvent || OE_RESIZE == nEvent )
	{
		// Get the lower left and upper right corner coordinates of the rectangle
		double dX1, dY1, dX2, dY2;
		dX1 = grTool.Shape.Dimension.Left.dVal;;
		dX2 = dX1 + grTool.Shape.Dimension.Width.dVal;
		dY2 = grTool.Shape.Dimension.Top.dVal;
		dY1 = dY2 + grTool.Shape.Dimension.Height.dVal;
	
		// Use these values to set the x, y scale of the inset layer
		TreeNode trUser = ei.GetUserData(true);
		int nInsetLayerIndex = trUser.InsetLayerIndex.nVal;
		GraphPage gpg = glyData.GetPage();
		GraphLayer glyInset = gpg.Layers(nInsetLayerIndex);
		glyInset.XAxis.Scale.From.dVal = dX1;
		glyInset.XAxis.Scale.To.dVal = dX2;
		glyInset.YAxis.Scale.From.dVal = dY1;
		glyInset.YAxis.Scale.To.dVal = dY2;
	}
	
	// When user deletes rectangle, clear message text
	if( OE_DELETE == nEvent )
		SetDataDisplayText("");
	
}

//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 addinsetlayer_event1(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	if( xf_is_extended_event(nEventID) )
		return addinsetlayer_event1_ex(trGetN, nRow, nEventID, dwEnables, lpcszNodeName, DynaCntrlContainer, strAux, strErrMsg);
	DECLARE_BUTTON_ENABLES
	return false;

}

int addinsetlayer_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 addinsetlayer_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{

}
//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 addinsetlayer_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
