/*------------------------------------------------------------------------------*
 * File Name: GetNBox.h															*
 * Creation: CPY 1/27/03														*
 * Purpose: Origin C support for a general parameters edit box as a replacement	*
 *	of the LabTalk GetNumber dialog												*
 * Copyright (c) OriginLab Corp.2003											*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 *	CPY 4/23/03 v7.0568 OPERATION_CLASS_NEED_TRY_AND_AUTO_UPDATE				*
 *	CPY 5/13/03 v7.0584 QA70-4467 BUTTON_IN_EDIT_TEXT							*
 *	CPY 5/15/03 v7.0585 QA70-4477 TREE_BRANCH_SUPPORT							*
 *	CPY 8/24/03 v7.5674 QA70-5061 QA70-5061 ADD_DISPLAY_OPTIONS					*
 *	CPY v7.5723 QA70-5376 GETNBOX_ADD_SIG_DIGITS_SUPPORT						*
 *	CPY v7.5763 QA70-5162 11/18/03 GETNBOX_JUSTIFICATION_AND_ENABLE_EDIT		*
 *------------------------------------------------------------------------------*/

 
#ifndef _GET_N_BOX
#define _GET_N_BOX


#include <Dialog.h>
#include <tree_utils.h>

//--- CPY 5/13/03 v7.0584 BUTTON_IN_EDIT_TEXT
#define TRGP_STR_BUTTON	1000
//---

#define TREE_ADD_LABEL(_NODE_LABEL)	_tmpSubNode.SetAttribute(STR_LABEL_ATTRIB, _NODE_LABEL) 

// declaration
#define GETN_NAMED_TREE(_TR_NAME, _NODE_NAME)	Tree GetNBoxTree_##_TR_NAME; TreeNode _TR_NAME = GetNBoxTree_##_TR_NAME.AddNode(#_NODE_NAME); TreeNode _tmpNode = _TR_NAME; TreeNode _tmpSubNode; string _strTemp;
#define GETN_TREE(_TR_NAME)	GETN_NAMED_TREE(_TR_NAME, GetNTree)	// for using as a tree, with tree look
#define GETN_BOX(_TR_NAME)	GETN_NAMED_TREE(_TR_NAME, GetNBox) // for using as simple dialog, dialog look
// add parameter

// a check box
#define GETN_CHECK(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL)  _tmpSubNode = _tmpNode.AddNumericNode((int)_DEFAULT_VAL, #_NODE_NAME, TRGP_CHECK);TREE_ADD_LABEL(_NODE_LABEL);
// a Combo box, enum list, 0 offset
#define GETN_COMBO(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL, _COMBO_STR) _tmpSubNode = _tmpNode.AddNumericNode((int)_DEFAULT_VAL, #_NODE_NAME, TRGP_ENUM_COMBO); \
TREE_ADD_LABEL(_NODE_LABEL);\
_tmpSubNode.SetAttribute(STR_COMBO_ATTRIB, _COMBO_STR);
// a string, edit box
#define GETN_STR(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL)	_tmpSubNode = _tmpNode.AddTextNode(_DEFAULT_VAL, #_NODE_NAME, TRGP_STR);TREE_ADD_LABEL(_NODE_LABEL);

// a numeric, just simple edit box
#define GETN_NUM(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL) _tmpSubNode = _tmpNode.AddNumericNode(_DEFAULT_VAL, #_NODE_NAME, TRGP_DOUBLE);TREE_ADD_LABEL(_NODE_LABEL);

// a list of str, with numeric offset
#define GETN_LIST(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL, _COMBO_STR)  _tmpSubNode = _tmpNode.AddNumericNode((int)_DEFAULT_VAL, #_NODE_NAME, TRGP_STR_LIST); \
TREE_ADD_LABEL(_NODE_LABEL);\
_tmpSubNode.SetAttribute(STR_COMBO_ATTRIB, _COMBO_STR);


// a color, pick from a list that is the system palette
#define GETN_COLOR(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL) _tmpSubNode = _tmpNode.AddNumericNode(_DEFAULT_VAL, #_NODE_NAME, TRGP_COLOR);TREE_ADD_LABEL(_NODE_LABEL);

/**#
	Example:
		void test()
		{
			string str = range_to_str(1,9);
			out_str(str);
		}		
*/
string range_to_str(int i1, int i2);

/**#
	Example:
		void test()
		{
			int i1,i2;
			string str("5-10");
			str_to_range(str,i1,i2);
			out_int("",i1);
			out_int("",i2);
		}
*/
bool str_to_range(LPCSTR lpcszRange, int& i1, int& i2);
/**
	Example:
		void test()
		{
			GETN_TREE(myTree)	
			
			GETN_STR(str,"String","abc")
			
			GETN_LIST(Type,"Color", 1, "Red|Blue|White")
			
			GETN_RANGE(Range,"Range",0,10,1,6)			
			
			if(GetNBox(myTree,"Test","OK",NULL,NULL))
			{
				out_str(myTree.str.strVal);
				out_int("",myTree.Type.nVal);
			}	
		}
*/
#define GETN_RANGE(_NODE_NAME, _NODE_LABEL, _I0, _IMAX, _I1, _I2) _strTemp = range_to_str(_I1, _I2);_tmpSubNode = _tmpNode.AddTextNode(_strTemp, #_NODE_NAME, TRGP_RANGE);\
TREE_ADD_LABEL(_NODE_LABEL);_strTemp = (_I0);_strTemp+="|" + (_IMAX);_tmpSubNode.SetAttribute(STR_COMBO_ATTRIB, _strTemp);


//---- CPY 4/23/03 OPERATION_CLASS_NEED_TRY_AND_AUTO_UPDATE
#define STR_OPERATION_TRY	"Try"
#define STR_ACTIVE_CURVE	"ActiveCurve"
#define STR_CLASS_NAME		"Class"
#define GETN_OPERATION(_TR_NAME)		GETN_NAMED_TREE(_TR_NAME, GUI) _tmpNode.SetAttribute(STR_OPERATION_TRY, "Try");
#define GETN_CURVE_OPERATION(_TR_NAME)	GETN_OPERATION(_TR_NAME) _tmpNode.SetAttribute(STR_ACTIVE_CURVE, "Input");
//----


//--- CPY 5/13/03 v7.0584 BUTTON_IN_EDIT_TEXT
// a string in edit box with button to bring up other dialog, like a FilePath dialog
#define GETN_BUTTON(_NODE_NAME, _NODE_LABEL, _DEFAULT_VAL) _tmpSubNode = _tmpNode.AddTextNode(_DEFAULT_VAL, #_NODE_NAME, TRGP_STR_BUTTON); \
TREE_ADD_LABEL(_NODE_LABEL);\
_tmpSubNode.SetAttribute(STR_COMBO_ATTRIB, "...");
//--- end CPY 5/13/03 v7.0584 BUTTON_IN_EDIT_TEXT

//------- CPY 5/15/03 v7.0585 QA70-4477 TREE_BRANCH_SUPPORT
//_tmSaveNode added in GETN_NAMED_TREE as well

#define GETN_BEGIN_BRANCH(_NODE_NAME, _NODE_LABEL) 	_tmpSubNode = _tmpNode.AddNode(#_NODE_NAME, TRGP_BRANCH);TREE_ADD_LABEL(_NODE_LABEL);\
TreeNode _tmSave_##_NODE_NAME = _tmpNode; _tmpNode = _tmpSubNode;
#define GETN_END_BRANCH(_NODE_NAME)					_tmpNode = _tmSave_##_NODE_NAME;

//------- end TREE_BRANCH_SUPPORT


//----- CPY 5/17/03 ALLOW_GETN_TREE_PASSED_INTO_FUNCTION
#define GETN_USE(_TR_NAME)	TreeNode _tmpNode = _TR_NAME; TreeNode _tmpSubNode;
//-----	

//---- CPY 8/24/03 v7.5674 QA70-5061 ADD_DISPLAY_OPTIONS
#define STR_ATTRIB_BRANCH			"Branch"
#define STR_ATTRIB_VERT_GRID_LINES	"GridLines"
#define STR_ATTRIB_LABEL_COLOR		"LabelColor"
#define STR_ATTRIB_BKGRND_COLOR		"BkGrndColor"
#define STR_ATTRIB_HANDLER			"Handler"
#define STR_ATTRIB_NUMFMT			"NumFormat"
#define STR_ATTRIB_DISPFMT			"DispFormat" //CPY v7.5763 QA70-5162 11/18/03 GETNBOX_JUSTIFICATION_AND_ENABLE_EDIT
// _VGLTYPE can be one of
#ifndef _VSFLEXGRID_H
	#define	flexGridFlatVert	8
	#define	flexGridInsetVert	9
	#define flexGridRaisedVert	10
#endif //_VSFLEXGRID_H
// flags for GETN_OPTION_BRANCH
enum {GETNBRANCH_OPEN = 1, GETNBRANCH_KEEP_SIZE_ON_COLLAPSE = 2, GETNBRANCH_KEEP_SIZE_ON_EXPAND = 4};
#define GETN_OPTION_GRIDLINE(_VGLTYPE)		_strTemp = _VGLTYPE; _tmpNode.SetAttribute(STR_ATTRIB_VERT_GRID_LINES, _strTemp);
#define GETN_OPTION_BRANCH(_DWOPTN)	_strTemp = _DWOPTN; _tmpNode.SetAttribute(STR_ATTRIB_BRANCH, _strTemp);
// can use RGB(r,g,b) or predefined COLOR_RED, COLOR_BLACK, COLOR_BLUE, COLOR_GREEN, COLOR_LTBLUE, COLOR_LTGREEN
#define GETN_OPTION_COLOR_LABEL(_RGB)		_strTemp = _RGB;_tmpSubNode.SetAttribute(STR_ATTRIB_LABEL_COLOR, _strTemp);
#define GETN_OPTION_COLOR_BACKGROUND(_RGB)		_strTemp = _RGB;_tmpSubNode.SetAttribute(STR_ATTRIB_BKGRND_COLOR, _strTemp);
#define GETN_OPTION_EVENT(_PFN)	{PEVENT_FUNC __dfn = _PFN;DWORD _dw_fn = (DWORD)__dfn;\
if(_dw_fn) {_strTemp = _dw_fn;_tmpSubNode.SetAttribute(STR_ATTRIB_HANDLER, _strTemp);}}	
	
#define GETN_OPTION_NUM_FORMAT(_STRFMT)	_tmpNode.SetAttribute(STR_ATTRIB_NUMFMT, _STRFMT); //CPY v7.5723 QA70-5376 GETNBOX_ADD_SIG_DIGITS_SUPPORT
//---- end QA70-5061 ADD_DISPLAY_OPTIONS

//----- CPY v7.5763 QA70-5162 11/18/03 GETNBOX_JUSTIFICATION_AND_ENABLE_EDIT
enum {DISPLAY_LEFT, DISPLAY_CENTER, DISPLAY_RIGHT};
#define GETN_OPTION_DISPLAY_FORMAT(_DISPFMT)	_strTemp = _DISPFMT;_tmpSubNode.SetAttribute(STR_ATTRIB_DISPFMT, _strTemp);
#define GETN_READ_ONLY							_tmpSubNode.Enable = false;
//----- end GETNBOX_JUSTIFICATION_AND_ENABLE_EDIT

typedef bool (* PAPPLY_FUNC)(TreeNode& tr);
typedef bool (* PEVENT_FUNC)(TreeNode& tr, int nRow, int nCntrlType, Dialog& getNDlg); //CPY 5/30/03 added getNDlg

/** >User Interface Controls
		Opens a simple dialog to get multiple values from user
	Parameters:
		trNode = a TreeNode constructed by the GETN_BOX or GETN_TREE macro
		lpcszTitle = Dialog title
		lpcszDescription = a line of text above the editable list of parameters
		pfnApply = if specified, an Apply button will show and call this handler
		pfnEvent = if specified, it will be called at the beginning with Row number = -1 for each control type, and if user change any editable parameters, the event handler will also be called
		hWndParent = parent window. If NULL, Origin main window will be used, also the location of the dialog will be reset to where it was brought up the time before. 
		If hWndParent is specified, the dialog will be open at its default location, so the event handler can move the dialog to a desired location.
	
	Return:
		TRUE if user click OK, FALSE if user click Cancel
	Example:
		// this will bring up the simple form with dialog look
		void test_get_n_box()
		{
			double x0, x1;
			GETN_BOX(trTemp)
			GETN_NUM(xFrom, "X From", 1.3)
			GETN_NUM(xStep, "X Step", -0.5)
			if(GetNBox(trTemp, "Row# as X", "Please specify initial X value and increment"))
			{
				x0 = trTemp.xFrom.dVal;
				x1 = trTemp.xStep.dVal;
				printf("X from %f with increment %f\n", x0, x1);
			}
		}
		// the following example shows a tree that allow more info to be edited
		static bool fit_expdecay_event(TreeNode& myTree, int nRow, int nType, Dialog& dlgGetNBox)	
		{
			if(nRow < 0) // On dialog init, nothing to do
				return false;
			
			// only handle the button for file path for now
			if(TRGP_STR_BUTTON == nType)
			{
				string str = BrowseGetPath(GetAppPath() + "OriginC\\", "Browse");
				myTree.Path.strVal = str;
				return true;
			}
			return false;
		}
		void test_get_n_tree()
		{
			GETN_TREE(myTree)
			GETN_COMBO(numExp, "Number of Terms", 1, "1|2|3")
			
			GETN_BEGIN_BRANCH(DecayTime, "Decay Times")
				GETN_NUM(decayT1, "1st Decay Time (t1)", 0.0)
				GETN_NUM(decayT2, "2nd Decay Time (t2)", 0.0)
				GETN_NUM(decayT3, "3rd Decay Time (t3)", 0.0)
			GETN_END_BRANCH(DecayTime)
			
			GETN_CHECK(PartialRange, "Fit Partial Data", false)
			GETN_BUTTON(Path, "File path", "c:\\")
			
			GETN_COLOR(FitCurveColor, "Fit Curve color", 1)
			
			if(GetNBox(myTree, "Fit Exp Decay", "Fit Exponential Decay 1,2,3", NULL, fit_expdecay_event))
			{
				if(myTree.numExp.nVal > 1)
					out_str("Multiple exponential");
				if(myTree.DecayTime.decayT1.dVal <= 0)
					out_str("Invalid decay time specified");
			}
		}
*/ 
bool GetNBox(TreeNode& trNode, LPCSTR lpcszTitle=NULL, LPCSTR lpcszDescription=NULL, PAPPLY_FUNC pfnApply = NULL, PEVENT_FUNC pfnEvent = NULL, HWND hWndParent = NULL);

/**#
	Example:
		void test()
		{
			Tree     tr;
			tr.trNode.strVal = "Tree";
			tr.trNode.First.strVal = "first";
			tr.trNode.First.abc.nVal = 1;
			tr.trNode.First.def.nVal = 2;	
			out_params(tr);				
		}
*/
bool out_params(TreeNode& trNode);

//#define load_default_getnbox_gui(__TR, __CLASSNAME)	load_default_settings(__TR, __CLASSNAME,SETTINGS_GUI)
 
#pragma dll(OTreeEditor.dll)

#define AFTER_EDIT_USE_CUSTOM_EDITOR (-1)
#define AFTER_EDIT_USE_STR			(-2)

/**#
*/
class EditorManager
{
public:
	EditorManager();
	~EditorManager();
	
	
	DWORD	New(int nType, int nRow, DWORD nID=0, LPCSTR lpcszAuxString=NULL, DWORD dwParam1=0, DWORD dwParam2=0);
	bool	Delete(DWORD dwData);
	BOOL	DrawCell(DWORD dwData, DWORD hDC, const RECT * lpcRect, BOOL bSelected);
	double	GetCellHeightFactor(DWORD dwData);
	DWORD	CreateEditor(DWORD dwData, const RECT * lpcRect, HWND hwndOwner, UINT nControlID=100, LPCTSTR lpcszFontName=NULL, int nFontSize=0);
	bool	DestroyEditor(DWORD dwData);
	bool	StartEdit(DWORD dwData, int nRow);
	bool	AfterEdit(DWORD dwData, int nComboIndex = AFTER_EDIT_USE_CUSTOM_EDITOR, LPCSTR lpcszNewText = NULL);
	string	GetText(DWORD dwData, BOOL bTranslate = TRUE);
	bool	SetText(DWORD dwData, LPCSTR lpcsz, int nCvtText = OXVT_UINT);
	int		GetEditInfo(DWORD dwData, string& strCombo, string& strEditMask);
	string	GetStrData(DWORD dwData);
	bool	SetStrData(DWORD dwData, LPCSTR lpcsz);
	bool	ValidateEdit(DWORD dwData, LPCSTR lpcsz);
};
#endif //_GET_N_BOX
