#include <origin.h>
#include <GetNBox.h>
#include <xfutils.h>
enum{
	option_layer,
	option_page,
};

/*------------------------------------------------------------------------------*
 * Modification Log:															*
 *------------------------------------------------------------------------------*/

//put additional include files here
#include <../OriginLab/graph_utils.h>

//put your own support static functions here

class GraphLayerInfoHelper
{
private:
	int			m_nOption;
	vector<int>	m_vnLayerIndices;
	GraphPage	m_gp;
public:
	GraphLayerInfoHelper(int nOption = option_layer)
	{
		m_nOption = nOption;
		m_vnLayerIndices.SetSize(0);
	}
public:
	BOOL	SetFontFixedFactor(double dFixedFactor = 1.0, bool bUndo = true)
	{
		BOOL bRet = GetLayers();
		if (bRet)
		{
			for(int ii = 0; ii < m_vnLayerIndices.GetSize(); ++ii)
			{
				GraphLayer gl = m_gp.Layers( m_vnLayerIndices[ii] );
				if (gl)
				{
					bRet = SetLayerObjFont(gl, dFixedFactor);
					ASSERT(bRet);
				}
			}
			return bRet;
		}
		return bRet;
	}
protected:
	BOOL	GetLayers()
	{
		m_gp = Project.Pages();
		if ( !m_gp )
		{
			XF_THROW(CER_INVALID_GRAPH);
			return FALSE;
		}
		if ( option_layer == m_nOption )
		{
			GraphLayer glActive = Project.ActiveLayer();
			if ( !glActive )
			{
				XF_THROW(CER_UNKNOWN_ERROR);
				return FALSE;
			}
			m_vnLayerIndices.Add( glActive.GetIndex() );
		}
		else if ( option_page == m_nOption )
		{
			foreach(GraphLayer gl in m_gp.Layers)
			{
				m_vnLayerIndices.Add( gl.GetIndex() );
			}
		}
		else
		{
			ASSERT(0);
			return FALSE;
		}
		return TRUE;
	}
	
	BOOL SetLayerObjFont(GraphLayer& gl, double dFixedFactor = 1.0, BOOL bUndo = TRUE)
	{
		ASSERT( gl.IsValid() );
		int		nScaleMode;
		double	dScalingFactor;
		BOOL bRet = gl.GetScaleElements(nScaleMode, dScalingFactor);
		ASSERT(bRet);
		
		int nTextObjSize = -1;
		int nAxisLabelSize = -1;
		Tree trTextObjFmt, trAxisLabelFmt;
		BOOL bGetTagNames = TRUE, bRelative = FALSE, bRepaint = TRUE;

		trTextObjFmt	= gl.GetFormat(FPB_STYLE_SIZE, FOB_LABELS, bGetTagNames, bRelative);
		trAxisLabelFmt	= gl.GetFormat(FPB_STYLE_SIZE, FOB_AXIS_LABELS, bGetTagNames, bRelative);

		TreeNode trTextObjGlobalFontSize	= trTextObjFmt.Root.Global.Size;
		TreeNode trAxisLabelGlobalFontSize	= trAxisLabelFmt.Root.Global.Size;
		
		if (trTextObjGlobalFontSize)
			nTextObjSize = trTextObjGlobalFontSize.nVal;
		if (trAxisLabelGlobalFontSize)
			nAxisLabelSize = trAxisLabelGlobalFontSize.nVal;

		bool bSameFontSize = nTextObjSize > 0 && nTextObjSize == nAxisLabelSize;
		if( bSameFontSize && updateTreeNodeFontSize(trTextObjGlobalFontSize, dScalingFactor) )
		{
		    int nErr = gl.UpdateThemeIDs(trTextObjGlobalFontSize.Root);
			if (0 == nErr)
			{
				bRet &= gl.ApplyFormat(trTextObjGlobalFontSize, bRepaint, bRelative, bUndo);
			}
		}
		else
		{
			bRet &= setTextObjectsFont(gl, dScalingFactor, nTextObjSize, bUndo);
			
			bRet &= setAxisLabelFont(gl, dScalingFactor, nAxisLabelSize, bUndo);
		}
		
		bRet &= gl.SetScaleElements(1, dFixedFactor);
		ASSERT(bRet);
		return bRet;
	}
private:
	BOOL setTextObjectsFont(GraphLayer& gl, double dScalingFactor, int nTextObjSize, BOOL bUndo = TRUE)
	{
		BOOL bRet = TRUE;
		BOOL bGetTagNames = TRUE, bRelative = TRUE, bRepaint = TRUE;
		BOOL bSameFontSize = nTextObjSize > 0;
		
		if ( bSameFontSize )
			nTextObjSize = calcFontSizeToFitActualSize(nTextObjSize, dScalingFactor);
		
		foreach(GraphObject go in gl.GraphObjects)
		{
			int nTypeID;
			go.GetObjectType(&nTypeID);
			if ( GROT_TEXT == nTypeID )
			{
				Tree trFmt;
				if ( bSameFontSize )
				{
					trFmt.Root.Font.Size.nVal = nTextObjSize;
				}
				else
				{
					trFmt = go.GetFormat(FPB_STYLE_SIZE, FOB_OTHER, bGetTagNames, bRelative);
					
					TreeNode trFontSize = trFmt.Root.Font.Size;
					if ( !updateTreeNodeFontSize(trFontSize, dScalingFactor) )
						continue;
				}	
				int nErr = go.UpdateThemeIDs(trFmt.Root);
				if (0 == nErr)
				{
					bRet &= go.ApplyFormat(trFmt, bRepaint, bRelative, bUndo);
				}
			}
		}
		return bRet;
	}
	
	BOOL setAxisLabelFont(GraphLayer& gl, double dScalingFactor, int nAxisLabelSize, BOOL bUndo = TRUE)
	{
		BOOL bRet = TRUE;
		BOOL bGetTagNames = TRUE, bRelative = TRUE, bRepaint = TRUE;
		TreeNode trFmt;
		trFmt = gl.GetFormat(FPB_STYLE_SIZE, FOB_AXIS_LABELS, bGetTagNames, bRelative);
		BOOL bSameFontSize = nAxisLabelSize > 0;
		
		if ( bSameFontSize )
		{
			nAxisLabelSize = calcFontSizeToFitActualSize(nAxisLabelSize, dScalingFactor);
		}
		
		TreeNode trAxes = trFmt.Root.Axes;
		if ( trAxes )
		{
			TreeNode trBottomLabelFont	= trAxes.X.Labels.BottomLabels.Font.Size;
			TreeNode trTopLabelFont		= trAxes.X.Labels.TopLabels.Font.Size;
			TreeNode trLeftLabelFont	= trAxes.Y.Labels.LeftLabels.Font.Size;
			TreeNode trRightLabelFont	= trAxes.Y.Labels.RightLabels.Font.Size;
			
			if ( bSameFontSize )
			{
				trBottomLabelFont.nVal	= nAxisLabelSize;
				trTopLabelFont.nVal		= nAxisLabelSize;
				trLeftLabelFont.nVal	= nAxisLabelSize;
				trRightLabelFont.nVal	= nAxisLabelSize;
			}
			else
			{
				updateTreeNodeFontSize(trBottomLabelFont, dScalingFactor);
				updateTreeNodeFontSize(trTopLabelFont, dScalingFactor);
				updateTreeNodeFontSize(trLeftLabelFont, dScalingFactor);
				updateTreeNodeFontSize(trRightLabelFont, dScalingFactor);
			}
				
			int nErr = gl.UpdateThemeIDs(trFmt.Root);
			if (0 == nErr)
			{
				bRet &= gl.ApplyFormat(trFmt, bRepaint, bRelative, bUndo);
			}
		}
		return bRet;
	}
	
	BOOL updateTreeNodeFontSize(TreeNode& trFontSize, double dScalingFactor)
	{
		if ( trFontSize )
		{	
			trFontSize.nVal = calcFontSizeToFitActualSize(trFontSize.nVal, dScalingFactor);
			return TRUE;
		}
		return FALSE;
	}
	
	int calcFontSizeToFitActualSize(int nFontSize, double dScalingFactor)
	{
		double dTmpFontSize = round(nFontSize * dScalingFactor, 0);
		nFontSize = dTmpFontSize;
		return nFontSize;
	}
};


void laysetfont(const int& option)
{
	GraphLayerInfoHelper helper(option);
	bool bRet = helper.SetFontFixedFactor();
}

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

}

int laysetfont_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 laysetfont_before_execute(TreeNode& trGetN, int nGetNDialog, int& nRet, int dwCntrl)
{
	GraphLayer glActive = Project.ActiveLayer();
	if ( !glActive )
	{
		nRet = XFEVT_ABORT;
	}
}
//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 laysetfont_event1_ex(TreeNode& trGetN, int nRow, int nEventID, DWORD& dwEnables, LPCSTR lpcszNodeName, WndContainer& DynaCntrlContainer, string& strAux, string& strErrMsg)
{
	return false;
}
