// XTPShellTreeBase.h : header file
//
// This file is a part of the XTREME CONTROLS MFC class library.
// (c)1998-2011 Codejock Software, All Rights Reserved.
//
// THIS SOURCE FILE IS THE PROPERTY OF CODEJOCK SOFTWARE AND IS NOT TO BE
// RE-DISTRIBUTED BY ANY MEANS WHATSOEVER WITHOUT THE EXPRESSED WRITTEN
// CONSENT OF CODEJOCK SOFTWARE.
//
// THIS SOURCE CODE CAN ONLY BE USED UNDER THE TERMS AND CONDITIONS OUTLINED
// IN THE XTREME TOOLKIT PRO LICENSE AGREEMENT. CODEJOCK SOFTWARE GRANTS TO
// YOU (ONE SOFTWARE DEVELOPER) THE LIMITED RIGHT TO USE THIS SOFTWARE ON A
// SINGLE COMPUTER.
//
// CONTACT INFORMATION:
// support@codejock.com
// http://www.codejock.com
//
/////////////////////////////////////////////////////////////////////////////

//{{AFX_CODEJOCK_PRIVATE
#if !defined(__XTPSHELLTREEBASE_H__)
#define __XTPSHELLTREEBASE_H__
//}}AFX_CODEJOCK_PRIVATE

#if _MSC_VER >= 1000
#pragma once
#endif // _MSC_VER >= 1000

// -------------------------------------------------------------------
// Summary:
//     Enumeration used to determine folder or drive type.
// Remarks:
//     XTPFindType type defines the constants used by the CXTPShellTreeBase
//     class to determine the type of object enumerated either folder or drive.
// See Also:
//     CXTPFontListBox, CXTPFontListBox::SetListStyle
//
// <KEYWORDS xtpFindTypeDrive, xtpFindTypeFolder>
// -------------------------------------------------------------------
enum XTPFindType
{
	xtpFindTypeDrive,  // The object type is a drive.
	xtpFindTypeFolder, // The object type is a folder.
	xtpFindTypeRoot,   // The object type is a root folder
	xtpFindTypeShare   // The object is a UNC share
};

//===========================================================================
// Summary:
//     CXTPShellTreeBase is a multiple inheritance class derived from CXTPTreeView
//     and CXTPShellPidl. It is used to create a CXTPShellTreeBase class object.
//===========================================================================
class _XTP_EXT_CLASS CXTPShellTreeBase : public CXTPTreeBase, public CXTPShellPidl
{
public:

	//-----------------------------------------------------------------------
	// Summary:
	//     Constructs a CXTPShellTreeBase object
	//-----------------------------------------------------------------------
	CXTPShellTreeBase();

	//-----------------------------------------------------------------------
	// Summary:
	//     Destroys a CXTPShellTreeBase object, handles cleanup and deallocation
	//-----------------------------------------------------------------------
	virtual ~CXTPShellTreeBase();

protected:

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function fills a branch of the TreeView control. Given
	//     the shell folder, it enumerates the subitems of this folder and adds
	//     the appropriate items to the tree.
	// Parameters:
	//     lpsf    - Pointer to the parent shell folder.
	//     lpifq   - Fully qualified item ID list to the item having items enumerated.
	//               This is the PIDL to the item identified by the 'lpsf' parameter.
	//     hParent - Parent tree node.
	// Returns:
	//     TRUE if successful, otherwise returns FALSE.
	//-----------------------------------------------------------------------
	virtual BOOL InitTreeViewItems(LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function gets the index for the normal and selected
	//     icons for the current item.
	// Parameters:
	//     lpifq    - Fully qualified item ID list for the current item.
	//     lptvitem - Pointer to the tree view item being added to the tree.
	//-----------------------------------------------------------------------
	virtual void GetNormalAndSelectedIcons(LPITEMIDLIST lpifq, LPTV_ITEM lptvitem);

public:

	//-----------------------------------------------------------------------
	// Summary:
	//     Call this member function to enable or disable the display of the
	//     shell context menu on right item click.
	// Parameters:
	//     bEnable - TRUE to display a context menu.
	//-----------------------------------------------------------------------
	void EnableContextMenu(BOOL bEnable);

	//-----------------------------------------------------------------------
	// Summary:
	//     Call this member to set root CSIDL folder.
	// Parameters:
	//     nRootFolder - Root folder of tree view.
	//-----------------------------------------------------------------------
	void SetRootFolder(int nRootFolder = CSIDL_DESKTOP);

	//-----------------------------------------------------------------------
	// Summary:
	//     Call this member to show all files instead of only folders
	// Parameters:
	//     bShowFiles - TRUE to show folder's files
	//-----------------------------------------------------------------------
	void ShowFiles(BOOL bShowFiles = TRUE);

	//-----------------------------------------------------------------------
	// Summary:
	//     Call this member function to determine the type of items included
	//     in the shell enumeration. The default is SHCONTF_FOLDERS | SHCONTF_NONFOLDERS.
	// Parameters:
	//     uFlags - Determines the type of items included in an enumeration. It
	//              can be one or more of the values listed in the Remarks section.
	// Remarks:
	//     Styles to be added or removed can be combined by using the bitwise
	//     OR (|) operator. It can be one or more of the following:<p/>
	//     * <b>SHCONTF_FOLDERS</b> Include items that are folders in
	//       the enumeration.
	//     * <b>SHCONTF_NONFOLDERS</b> Include items that are not folders
	//       in the enumeration.
	//     * <b>SHCONTF_INCLUDEHIDDEN</b> Include hidden items in the
	//       enumeration.
	//     * <b>SHCONTF_INIT_ON_FIRST_NEXT</b> IShellFolder::EnumObjects
	//       can return without validating the enumeration object. Validation
	//       can be postponed until the first call to IEnumIDList::Next.
	//       This flag is intended to be used when a user interface may be
	//       displayed prior to the first IEnumIDList::Next call. For a
	//       user interface to be presented, 'hwndOwner' must be set to a valid
	//       window handle.
	//     * <b>SHCONTF_NETPRINTERSRCH</b> The caller is looking for
	//       printer objects.
	//-----------------------------------------------------------------------
	void SetEnumFlags(UINT uFlags);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function obtains a handle to the system image list and
	//     attaches it to the tree control.
	// Returns:
	//     TRUE if successful, otherwise returns FALSE.
	//-----------------------------------------------------------------------
	virtual BOOL InitSystemImageLists();

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function adds items to the tree view.
	//-----------------------------------------------------------------------
	virtual void PopulateTreeView();

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function responds to a TVN_ITEMEXPANDING message in
	//     order to fill up subdirectories.
	// Parameters:
	//     pNMTreeView - Address of an NM_TREEVIEW struct.
	//-----------------------------------------------------------------------
	virtual void OnFolderExpanding(NM_TREEVIEW* pNMTreeView);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function displays the shell context menu for the selected
	//     item or folder.
	// Returns:
	//     A handle to the currently selected HTREEITEM.
	//-----------------------------------------------------------------------
	virtual HTREEITEM GetContextMenu();

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function responds to a TVN_SELCHANGED message to retrieve
	//     the specified folder path.
	// Parameters:
	//     pNMTreeView   - Address of an NM_TREEVIEW struct.
	//     strFolderPath - Address of a CString object to receive the file system path.
	// Returns:
	//     TRUE if the folder path was found, otherwise returns FALSE.
	//-----------------------------------------------------------------------
	virtual BOOL OnFolderSelected(NM_TREEVIEW* pNMTreeView, CString& strFolderPath);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function retrieves the path of the currently selected
	//     tree item.
	// Parameters:
	//     strFolderPath - Address of a CString object to receive the file system path.
	// Returns:
	//     TRUE if successful, otherwise returns FALSE.
	//-----------------------------------------------------------------------
	virtual BOOL GetSelectedFolderPath(CString& strFolderPath);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function recursively searches the tree control beginning
	//     at 'hItem' to find the item specified by 'lplvid'. This is typically used when
	//     the user double clicks an item in the list view.
	// Parameters:
	//     hItem  - Handle to the tree item to search from.
	//     lplvid - Pointer to the list view item data.
	//     bRecursively - TURE to recursively search.
	// Returns:
	//     TRUE if successful, otherwise returns FALSE.
	//-----------------------------------------------------------------------
	virtual BOOL FindTreeItem(HTREEITEM hItem, XTP_LVITEMDATA* lplvid, BOOL bRecursively = TRUE);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function is used to associate a CComboBox object with
	//     the control. Whenever the path changes, the combo is updated.
	// Parameters:
	//     pWnd - Points to the combo box that is associated with the tree.
	//-----------------------------------------------------------------------
	virtual void AssociateCombo(CWnd* pWnd);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function is called to initialize a branch of the shell
	//     tree.
	// Parameters:
	//     hItem  - Handle to a tree node.
	//     lptvid - Pointer to the list view item data.
	//-----------------------------------------------------------------------
	virtual void InitTreeNode(HTREEITEM hItem, XTP_TVITEMDATA* lptvid);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function searches the tree for a specified folder.
	// Parameters:
	//     hItem         - Tree item to begin the search from.
	//     pABSPidl      - pidl we're looking to match
	// Returns:
	//     HTREEITEM of node in tree that resulted in a match.
	//-----------------------------------------------------------------------
	virtual HTREEITEM SearchTree(HTREEITEM hItem, LPCITEMIDLIST pABSPidl);


	//-----------------------------------------------------------------------
	// Summary:
	//     This member function will "tunnel" the tree to find the specified
	//     path. This will work only when the PopulateTreeView() method is used
	//     to populate the tree.
	// Parameters:
	//     strFindPath - Path to find.
	//-----------------------------------------------------------------------
	virtual BOOL TunnelTree(CString strFindPath);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function retrieves the path of a folder item, which
	//     does not have to be selected. Pass a CString object that will hold
	//     the folder path.
	// Parameters:
	//     hItem         - Tree item to get the path for.
	//     strFolderPath - Reference to a CString object to contain the folder path.
	// Returns:
	//     TRUE if the path is not in the file system (e.g.
	//     MyComputer); if none is selected, it returns FALSE.
	//-----------------------------------------------------------------------
	virtual BOOL GetFolderItemPath(HTREEITEM hItem, CString &strFolderPath);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function populates a tree based upon a path. You must
	//     call InitializeTree() before populating the tree for the first time.
	// Parameters:
	//     lpszPath - Path to populate.
	// See Also: InitializeTree()
	//-----------------------------------------------------------------------
	virtual void PopulateTree(LPCTSTR lpszPath);

	//-----------------------------------------------------------------------
	// Summary:
	//     Call this member function to initialize the shell tree control prior
	//     to calling PopulateTree.
	// Parameters:
	//     dwStyle - TVS_ style flags for tree control.
	// Returns:
	//     TRUE if successful, otherwise returns FALSE.
	// See Also: PopulateTree()
	//-----------------------------------------------------------------------
	virtual BOOL InitializeTree(DWORD dwStyle = TVS_HASBUTTONS | TVS_HASLINES | TVS_LINESATROOT);


	//-----------------------------------------------------------------------
	// Summary:
	//     Used by the shell list control to handle a drag event.
	// Parameters:
	//     pNMTreeView - Points to a NM_TREEVIEW structure.
	//-----------------------------------------------------------------------
	virtual void BeginDrag(NM_TREEVIEW* pNMTreeView);

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function is called to insert the Desktop as the root
	//     item in the shell tree control.
	// Parameters:
	//     nFolder - Root folder CSIDL to insert.
	// Returns:
	//     A handle to the desktop tree item if successful, otherwise NULL.
	//-----------------------------------------------------------------------
	virtual HTREEITEM InsertDesktopItem(int nFolder = CSIDL_DESKTOP);

	//-----------------------------------------------------------------------
	// Summary:
	//     Called after a user makes a new tree selection.
	// Remarks:
	//     This member function is called whenever a user makes a selection
	//     within the tree control to synchronize any shell list or shell
	//     combo boxes associated with the tree. You can override this member
	//     to provide additional functionality.
	// Parameters:
	//     hItem         - Handle to the newly selected tree item.
	//     strFolderPath - NULL terminated string representing the fully
	//                     qualified path to the selected tree item.
	//-----------------------------------------------------------------------
	virtual void SelectionChanged(HTREEITEM hItem, CString strFolderPath);

protected:

	//-----------------------------------------------------------------------
	// Summary:
	//     This member function sets the shell attribute flags for the specified
	//     tree item.
	// Parameters:
	//     hItem        - Handle to HTREEITEM node.
	//     dwAttributes - Flags retrieved from SHELLFOLDER::GetAttributesOf.
	//-----------------------------------------------------------------------
	void SetAttributes(HTREEITEM hItem, DWORD dwAttributes);


	// -------------------------------------------------------------------------------------------
	// Summary:
	//     Parses a path for the next path component.
	// Parameters:
	//     pszPath -  Pointer to a NULL\-terminated string with the path. Paths are
	//                delimited by backslashes or by the NULL at the end of the
	//                path.
	// Remarks:
	//     This member function parses a path for the next path component,
	//     not dependent on shell32.dll, and is a replacement for the windows
	//     API PathFindNextComponent.
	// Returns:
	//     A pointer to a NULL-terminated string with the next path component
	//     if successful, or NULL otherwise.
	// Example:
	//     The following example demonstrates using the XTFuncPathFindNextComponent function.
	// <code>
	// // Path to find the next part.
	// char buffer_1[ ] = "c:\\\\path1\\\\path2\\\\test";
	// char *lpStr1;
	// lpStr1 = buffer_1;
	//
	// cout \<\< "Search a path for the next path component "
	//      \<\< "after the root " \<\< lpStr1 \<\< endl;
	// cout \<\< "Return the next path component: \\""
	//      \<\<  XTFuncPathFindNextComponent(lpStr1) \<\< "\\"" \<\< endl;
	//
	// cout \<\< "\\nSearch a path for the next path component "
	//      \<\< "after the root \\"c:\\\\path1\\\\path2\\"" \<\< endl;
	// cout \<\< "Return the next path component: \\""
	//      \<\<  XTFuncPathFindNextComponent("c:\\\\path1\\\\path2") \<\< "\\"" \<\< endl;
	//
	// cout \<\< "\\nSearch a path for the next path component "
	//      \<\< "after the root \\"c:\\\\path1\\"" \<\< endl;
	// cout \<\< "Return the next path component: \\""
	//      \<\<  XTFuncPathFindNextComponent("c:\\\\path1") \<\< "\\"" \<\< endl;
	//
	// \OUTPUT:
	// ===========
	// Search a path for the next path component after the root c:\\path1\\path2\\test
	// Return the next path component: "path1\\path2\\test"
	//
	// Search a path for the next path component after the root "c:\\path1\\path2"
	// Return the next path component: "path1\\path2"
	//
	// Search a path for the next path component after the root "c:\\path1"
	// Return the next path component: "path1"
	// </code>
	// -------------------------------------------------------------------------------------------
	CString PathFindNextComponent(const CString& pszPath);

	// -------------------------------------------------------------------------------------------
	// Summary:
	//     Sorts items in the control using the provided callback function.
	// Parameters:
	//     hParent - Parent item to sort
	// -------------------------------------------------------------------------------------------
	virtual void SortChildren(HTREEITEM hParent);

protected:
//{{AFX_CODEJOCK_PRIVATE

	//{{AFX_MSG(CXTPShellTreeBase)
	afx_msg void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnDeleteTreeItem(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg void OnRclick(NMHDR* pNMHDR, LRESULT* pResult);
	afx_msg BOOL OnEraseBkgnd(CDC* pDC);
	afx_msg void OnPaint();
	//}}AFX_MSG
//}}AFX_CODEJOCK_PRIVATE

protected:

	UINT             m_uFlags;       // Flags indicating which items to include in the enumeration.
	bool             m_bTunneling;   // true if tree is currently traversing.
	BOOL             m_bContextMenu; // TRUE to display the shell context menu on right item click.
	CWnd*            m_pComboBox;    // CComboBox that is associated with this control. See AssociateCombo(...)
	CXTPShellSettings m_shSettings;   // Contains SHELLFLAGSTATE info.
	int              m_nRootFolder;  // Root Folder CSIDL
	BOOL             m_bShowFiles;   // FALSE to show only directories
};

//////////////////////////////////////////////////////////////////////

AFX_INLINE void CXTPShellTreeBase::SetEnumFlags(UINT uFlags) {
	m_uFlags = uFlags;
}
AFX_INLINE void CXTPShellTreeBase::EnableContextMenu(BOOL bEnable) {
	m_bContextMenu = bEnable;
}
AFX_INLINE void CXTPShellTreeBase::SetRootFolder(int nRootFolder /*= CSIDL_DESKTOP*/) {
	m_nRootFolder = nRootFolder;
}
AFX_INLINE void CXTPShellTreeBase::ShowFiles(BOOL bShowFiles /*= TRUE*/) {
	m_bShowFiles = bShowFiles;
}

// --------------------------------------------------------------------------------------
// Summary:
//     The DELCLATE_SHELLTREE_BASE class is a template class used by the
//     CXTPShellTreeView and CXTPShellTreeCtrl class to declare a multiple
//     inheritance base class so that both classes could share a common
//     code base.
// Parameters:
//     ClassName -  Name of the object to be declared as the base class.
//     Tree -       Existing class that this object will derive from.
//     Base -       Existing shared class that this object will derive from.
// Remarks:
//     <i>Tree</i> must be an existing class that is derived from either <i>CTreeCtrl</i>
//     or <i>CTreeView</i>.
// Example:
//     The following example demonstrates how to use DECLATE_SHELLTREE_BASE.
// <code>
// DECLATE_SHELLTREE_BASE(CXTPShellTreeViewBase, CTreeView, CXTPShellTreeBase)
//
// class _XTP_EXT_CLASS CXTPShellTreeView : public CXTPShellTreeViewBase
// {
// public:
//     CXTPShellTreeView();
// };
// </code>
// --------------------------------------------------------------------------------------
#define DECLATE_SHELLTREE_BASE(ClassName, Tree, Base)
//{{AFX_CODEJOCK_PRIVATE
#undef DECLATE_SHELLTREE_BASE
#define DECLATE_SHELLTREE_BASE(ClassName, Tree, Base)\
DECLATE_TREE_BASE(Base##Tree, Tree, Base)\
class _XTP_EXT_CLASS ClassName : public Base##Tree\
{\
protected:\
	void OnPaint() {\
		Base::OnPaint();\
	}   \
	void OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult) {\
		NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;\
		BeginDrag(pNMTreeView);\
		*pResult = 0;\
	}\
	void OnSelchanged(NMHDR* pNMHDR, LRESULT* pResult) {\
		Base::OnSelchanged(pNMHDR, pResult);\
	}   \
	void OnDeleteTreeItem(NMHDR* pNMHDR, LRESULT* pResult) {\
		Base::OnDeleteTreeItem(pNMHDR, pResult);\
	}   \
	void OnRclick(NMHDR* pNMHDR, LRESULT* pResult) {\
		Base::OnRclick(pNMHDR, pResult);\
	}   \
	void OnItemexpanding(NMHDR* pNMHDR, LRESULT* pResult) {\
		Base::OnItemexpanding(pNMHDR, pResult);\
	}\
};

#define ON_SHELLTREE_REFLECT\
	ON_NOTIFY_REFLECT(NM_RCLICK, OnRclick)\
	ON_NOTIFY_REFLECT(TVN_ITEMEXPANDING, OnItemexpanding)\
	ON_NOTIFY_REFLECT(TVN_SELCHANGED, OnSelchanged)\
	ON_NOTIFY_REFLECT(TVN_BEGINDRAG, OnBeginDrag)\
	ON_NOTIFY_REFLECT(TVN_BEGINRDRAG, OnBeginDrag)\
	ON_NOTIFY_REFLECT(TVN_DELETEITEM, OnDeleteTreeItem)\
	ON_TREECTRL_REFLECT
//}}AFX_CODEJOCK_PRIVATE

#endif // __XTPSHELLTREEBASE_H__
