/*------------------------------------------------------------------------------*
 * File Name:MenuBase.h															*
 * Creation: CPY 6/14/2004														*
 * Purpose: OriginC Header for base menu class 									*
 * Copyright (c) Originlab Corp. 		2004, 2005, 2006, 						*
 * All Rights Reserved															*
 * 																				*
 * Modification Log:															*
 * DG 3/30/05 v8.0212 CLEAN_DUPLICATE_MORE										*
 *	ML 3/9/2006 STRANGE_MENU_BUILDING_BUG										*
 *	Folger 01/21/08 QA70-10960 ADD_XF_DIALOG_CONTEXT_MENU						*
 *	CPY 5/13/08 MOVE_TRACK_MENU_POPUP_TO_BASE_CLASS								*
 *	Folger 10/08/08 SHOULD_NOT_ALLOW_SHOW_SHARE_CLOUMN_WHEN_PARAM_SHARING_IS_NOT_ALLOWED
 *	Kyle 12/05/2008 ADD_ITEM_SHOW_ALL_COLUMNS_FOR_PARAMETERS_CHECK_MENU			*
 *------------------------------------------------------------------------------*/

#ifndef _MENUBASE_H_ 
#define _MENUBASE_H_

class	MenuBase	:	public	Menu
{
public:
	MenuBase()
	{
		m_nChoice = -1;
	}
	//----- CPY 5/13/08 MOVE_TRACK_MENU_POPUP_TO_BASE_CLASS
	/*
	virtual int DoTrackPopup(int nx, int ny, HWND hWndParent)
	{
		error_report("calling base class DoTrackPopup, implementation missing in derived class");
		return 0;
	}
	*/
	virtual int DoTrackPopup(int nx, int ny, HWND hWndParent)
	{
		TrackPopupMenu(0,  nx, ny, hWndParent);
		int nCmd;
		if(!GetCommand(nCmd))
			return -1;
		
		return nCmd;
	}
	//----- end MOVE_TRACK_MENU_POPUP_TO_BASE_CLASS
protected:
	void OnMenuItem(UINT nPos)
	{
		//out_int("OnMenuItem ",nPos);
		m_nChoice = nPos;
	}

	bool GetCommand(int& nChoice)
	{
		if(m_nChoice < 0)
			return false; // menu index must be 0,1,2,3 etc
		nChoice = m_nChoice;
		return true;
	}
private:
	int				m_nChoice;
};


class MenuTree : public Menu
{
	
public:
	
	MenuTree()
	{
	}
	MenuTree(TreeNode &tree)
	{
		m_trMenu = tree;
	}
	
	
	int		TrackPopupMenu(UINT nFlags,  int x, int y, HWND hwnd)
	{
		int nCmd = Menu::TrackPopupResMenu(nFlags,  x, y, hwnd);
		Handler(nCmd);
		return nCmd;
	}
	
	
	virtual void Handler(uint nCmd)
	{
		ASSERT(FALSE);
	}
protected:
	
	
	void createMenuFromTree()
	{
		BOOL bAddSeperator = FALSE;
		TreeNode tn = m_trMenu.FirstNode;
		for(; tn; tn = tn.NextNode)
		{
			if(TRGP_BRANCH == tn.ID)
			{
				if(bAddSeperator)
				{
					Add(NULL, 0, MF_SEPARATOR);
				}
				else
				{
					bAddSeperator = TRUE;
				}
				
				TreeNode tnMenuItem = tn.FirstNode;
				for(; tnMenuItem; tnMenuItem = tnMenuItem.NextNode)
				{
					if(TRGP_CHECK == tnMenuItem.ID)	
						addCheck(tnMenuItem);

				}
			}
		}
	}
	
	
	void addCheck(TreeNode &node)
	{
		int nID = 0;
		string strName;
		if(node.GetAttribute(STR_DATAID_ATTRIB, nID )  && (nID > 0)  && node.GetAttribute(STR_LABEL_ATTRIB, strName))
			AddChecked(strName, node.nVal, nID);
		else
			ASSERT(FALSE);
	}
	
	
	BOOL AddChecked(LPCSTR lpcszText, bool bChecked, int nID)
	{
		UINT nFlags = MF_STRING | (bChecked ? MF_CHECKED: 0);
		return Add(lpcszText, nID, nFlags);
	}

	
	
	
protected:	
	
	Tree	m_trMenu;
	
};



/////////////////////////////////////////////////////////////////////
// class ActionBase
/////////////////////////////////////////////////////////////////////
class ActionBase
{
public:
	virtual	bool	BuildMenuTree(TreeNode &tr)
					{ return false; }
					
					
	// Retuurns true if handled.	
	virtual	bool	HandleCommand(int nCmdId)
					{ return false; }
					
	// Retuurns true if handled.	
	virtual	bool	HandleCommand(int nCmdId, TreeNode &trCmd)
					{ return false; }
	
};


//#define		GETN_AMENU_GET_CMDID(_nId, _trNode)			_trNode.GetAttribute(STR_DATAID_ATTRIB, _nId)
#define		GETN_AMENU_GET_CMDID(_trNode)				_trNode.DataID
#define		GETN_AMENU_GET_TEXT(_strVal, _trNode)		_trNode.GetAttribute(STR_LABEL_ATTRIB, _strVal)


/////////////////////////////////////////////////////////////////////
// class MenuAction
/////////////////////////////////////////////////////////////////////
class	MenuAction : public MenuTree
{
public:
	MenuAction(ActionBase &actbase)
	{
		m_pactbase = &actbase;
	}
	
	
public:	
	int				DoMenu(UINT nFlags, int x, int y, HWND hwnd)
	{
		// Init the menu tree:
		if ( !InitMenuTree() )
			return -1;
		
		// Create the menu from the tree:
		if ( !CreateFromTree() )
			return -1;

		// Display the menu:
		int			nCmdId = Menu::TrackPopupResMenu(nFlags,  x, y, hwnd);
		if (nCmdId <= 0)
			return nCmdId;

		// First try to handle without the node:
		bool		bHandled = HandleCommand(nCmdId);
		if (bHandled)
			return nCmdId;
		
		TreeNode	trCmd;
		// Find the node:
		if ( !FindCmdNode(trCmd, nCmdId) )
		{
			error_report("FindCmdNode() failed!");	// should not happen
			return -1;
		}

		// Handle with the node:
		if ( !HandleCommand(nCmdId, trCmd) )
			error_report("Command not handled.");
		
		return nCmdId;

	}
	
protected:
	bool			InitMenuTree()
	{
		if ( !m_pactbase )
			return false;
		
		return m_pactbase->BuildMenuTree(m_trMenu);
	}
	
	bool			CreateFromTree()
	{
		TreeNode		tr = m_trMenu;
		if (!tr)
			return false;
		
		Create(TRUE);	// if this is not done and the first thing added is sub-popup, no menu appears
		
		return AddFromTreeNode(tr, *this);
	}
	
	bool			HandleCommand(int nCmdId)
	{
		return m_pactbase->HandleCommand(nCmdId);
	}

	bool			HandleCommand(int nCmdId, TreeNode &trCmd)
	{
		return m_pactbase->HandleCommand(nCmdId, trCmd);
	}

	
private:
	bool			FindCmdNode(TreeNode &trCmd, int nCmdId)
	{
		return FindCmdNode(trCmd, m_trMenu, nCmdId);
	}

	bool			FindCmdNode(TreeNode &trCmd, TreeNode &trNode, int nCmdId)
	{
		for (TreeNode tn = trNode.FirstNode; tn; tn = tn.NextNode)
		{
			if(TRGP_BRANCH == tn.ID)
			{
				if (FindCmdNode(trCmd, tn, nCmdId))
					return true;
			}
			else
			{
				int			nId = GETN_AMENU_GET_CMDID(tn);
				//GETN_AMENU_GET_CMDID(nId, tn);
				if (nId == nCmdId)
				{
					trCmd = tn;
					return true;
				}
			}
		}
		
		return false;
	}

	
	bool			AddFromTreeNode(TreeNode &trNode, Menu &menu)
	{
		for (TreeNode tn = trNode.FirstNode; tn; tn = tn.NextNode)
		{
			string		strText;
			GETN_AMENU_GET_TEXT(strText, tn);
			if (strText.IsEmpty())
				strText = tn.tagName;					// Eric Parent wants to use just the node name if no label
														// (say if it is some preexisting tree wihout labels).
			
			//if(TRGP_BRANCH == tn.ID)
			bool		bSubPopup = TRGP_BRANCH == tn.ID;
			if (!bSubPopup)								// again per Eric P's request.
				bSubPopup = 0 < tn.GetNodeCount();
			
			if(bSubPopup)
			{
				Menu		menuSub;
				/// ML 3/9/2006 STRANGE_MENU_BUILDING_BUG
				menuSub.Create(TRUE);
				/// end STRANGE_MENU_BUILDING_BUG				
				bool		bOK = AddFromTreeNode(tn, menuSub);
				
				if ( !bOK )
					return false;

				//GETN_AMENU_GET_TEXT(strText, tn);
				//if ( !menu.AddPopup(strText, menuSub) )
				//	error_report("menu.AddPopup() failed!");
				//
				
				// It appears that Menu::AddPopup() incorrectly returns BOOL. It actually may return 0 even if it succeeds,
				// so I am not testing the return value here.
				menu.AddPopup(strText, menuSub);
			}
			else
			{
				int			nId = GETN_AMENU_GET_CMDID(tn);
				//if ( 0 < nId && GETN_AMENU_GET_TEXT(strText, tn) && !strText.IsEmpty() )
				
				if ( 0 < nId )
				{
					menu.Add(strText, nId);
				}
			}
		}
		
		return true;
	}
	
private:
	ActionBase			*m_pactbase;
};

/// YuI 03/31/05 moved here from GetNBox.c
#ifdef _XV_ACTION_BASE_
class	TreeEditInputData;
class XVarActionBase : public ActionBase 
{
public:
	void		SetTreeCtrl(TreeEditInputData *pctrl)
		{ m_pctrl = pctrl; }
	void		SetTreeVarNode(TreeNode &trVar)
		{ m_tr = trVar; }
		
	TreeNode		GetTreeVarNode()
		{ return m_tr; }
		
protected:
	/// YuI 07/22/05 INTERACTIVE_CONTROL_SHOULD_BE_EDITABLE_IN_GRAPH
	virtual	bool	BuildMenuTree(TreeNode &tr);
	virtual	bool	HandleCommand(int nCmdId);
	/// end INTERACTIVE_CONTROL_SHOULD_BE_EDITABLE_IN_GRAPH
					
					
	virtual	bool	SupportsDataPopupNew(TreeNode &trVar)
		{ return false; }
	virtual	bool	SupportsDataPopupActive(TreeNode &trVar)
		{ return false; }
	/// YuI 07/22/05 INTERACTIVE_CONTROL_SHOULD_BE_EDITABLE_IN_GRAPH
	virtual	bool	SupportsDataPopupUnassigned(TreeNode &trVar)
		{ return true; } //support for all variables for now
	/// end INTERACTIVE_CONTROL_SHOULD_BE_EDITABLE_IN_GRAPH

	/// YuI 09/19/05 QA70-8119 SUPPORT_FOR_OUTPUT_TO_BE_SAME_AS_INPUT
	virtual	bool	SupportsDataPopupInput(TreeNode &trVar);
	/// end SUPPORT_FOR_OUTPUT_TO_BE_SAME_AS_INPUT

	bool			GetActiveDataplot(DataPlot &dpl);
	int				GetActiveLayer(GraphLayer &gl, Worksheet &wks, MatrixLayer &matlay);

	virtual	bool	SupportsPlotType(int nPlotId)
		{ return false; }
	
	virtual	bool	SupportsColumnType(int nColType)
		{ return false; }
		
		
		
protected:
	TreeEditInputData 	*m_pctrl;
	TreeNode			m_tr;
};
#endif //#ifdef _XV_ACTION_BASE_
/// end YuI

///DG 4/1/05 CLEAN_DUPLICATE_MORE : move from TreeEditInputData.h
//------ Folger 01/21/08 QA70-10960 ADD_XF_DIALOG_CONTEXT_MENU
//enum { XF_MENU_ADD, XF_MENU_INSERT,XF_MENU_SEPARATOR, XF_MENU_DEL, XF_MENU_SEPARATOR1, XF_MENU_ENLARGE, XF_MENU_SHRINK };
enum { XF_MENU_ADD, XF_MENU_INSERT,XF_MENU_SEPARATOR, XF_MENU_DEL, XF_MENU_SEPARATOR1, XF_MENU_ENLARGE, XF_MENU_SHRINK, XF_MENU_SEPARATOR2, XF_MENU_COLUMN };
//------
class XFControlMenu : public MenuBase
{
public:
	//------ Folger 01/21/08 QA70-10960 ADD_XF_DIALOG_CONTEXT_MENU
	//XFControlMenu(bool bAllowDel=true, bool bIsXFunctionDialog = false) : MenuBase()
	XFControlMenu(bool bAllowDel=true, bool bIsXFunctionDialog = false,
	const vector<string> &vsColHeading = NULL, const vector<byte> &vbCols = NULL, const vector<int> &vnRemove = NULL, int nDisable = 1) : MenuBase()
	//------
	{
		Add(_L("Add variable"), OnMenuItem);

		if(bAllowDel)
		{
			Add(_L("Insert variable"), OnMenuItem);
			Add(NULL, OnMenuItem);
			Add(_L("Delete"), OnMenuItem);
		}
		if(bIsXFunctionDialog)
		{
			Add(NULL, OnMenuItem);
			Add(_L("Enlarge Pane"), OnMenuItem);
			Add(_L("Shrink Pane"), OnMenuItem);
			//------ Folger 01/21/08 QA70-10960 ADD_XF_DIALOG_CONTEXT_MENU
			if ( !bAllowDel && vsColHeading != NULL && vbCols != NULL )
			{				
				Add(NULL, OnMenuItem);
				int nSize = vsColHeading.GetSize();
				for (int ii=0; ii<nSize; ++ii )
				{
					vector<uint> vnIndeces;
					if ( vnRemove == NULL || vnRemove.Find(vnIndeces, ii) < 1 )
					{
						int nCntrl = !vbCols[ii] ? MF_CHECKED : MF_UNCHECKED;
						if ( nDisable == ii )
							nCntrl |= MF_GRAYED;
						Add(vsColHeading[ii], OnMenuItem, nCntrl);
					}
				}
			}
			//------
		}
		
	}

	int DoTrackPopup(int nx, int ny, HWND hWndParent, bool bAllowDel = true)
	{
		TrackPopupMenu(0,  nx, ny, hWndParent);
		int nCmd;
		if(!GetCommand(nCmd))
			return -1;
		
		if(!bAllowDel && nCmd > XF_MENU_ADD)
		{
			nCmd = nCmd + 3;	///because have three offset ....
		}
		return nCmd;
	}

};

/// Vinde 5/13/2008 GRID_TABLE_CONTROL
class CheckMenu: public MenuBase
{
public:
	//------ Folger 10/08/08 SHOULD_NOT_ALLOW_SHOW_SHARE_CLOUMN_WHEN_PARAM_SHARING_IS_NOT_ALLOWED
	//CheckMenu(const vector<byte> &vnStates, const vector<string> &vsColHeaders)
	CheckMenu(const vector<byte> &vnStates, const vector<string> &vsColHeaders, const vector<bool>& vbItemsDisable = NULL)
	//------
	{
		ASSERT(vnStates.GetSize() == vsColHeaders.GetSize() );
		//------ Folger 10/08/08 SHOULD_NOT_ALLOW_SHOW_SHARE_CLOUMN_WHEN_PARAM_SHARING_IS_NOT_ALLOWED
		if ( vbItemsDisable )
			ASSERT(vbItemsDisable.GetSize() == vsColHeaders.GetSize());
		//------
		int nCmd=0;
		for(int ii = 0;ii < vnStates.GetSize();ii ++)
		{
			///Kyle 12/05/2008 ADD_ITEM_SHOW_ALL_COLUMNS_FOR_PARAMETERS_CHECK_MENU
			if(vsColHeaders[ii].IsEmpty())
			{
				Add(NULL, OnMenuItem, MF_SEPARATOR);
				nCmd ++;
				continue;
			}
			///End ADD_ITEM_SHOW_ALL_COLUMNS_FOR_PARAMETERS_CHECK_MENU
			int nFlags = vnStates[ii]?  MF_CHECKED : MF_UNCHECKED;
			//------ Folger 10/08/08 SHOULD_NOT_ALLOW_SHOW_SHARE_CLOUMN_WHEN_PARAM_SHARING_IS_NOT_ALLOWED
			if ( vbItemsDisable && vbItemsDisable[ii] )
				nFlags |= MF_GRAYED;
			//------
		    Add(vsColHeaders[ii], OnMenuItem, nFlags, nCmd++);
		}
	}
};
///End GRID_TABLE_CONTROL
///end CLEAN_DUPLICATE_MORE
#endif //_MENUBASE_H_

