text: // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
  
  #ifndef __FILE_TREE_H__
  #define __FILE_TREE_H__
  #pragma once
  
  #if BB_PLATFORM_WINDOWS
  
  	#include <BlackBox/Core/Platform/Windows.hpp>
  	#include "_TinyMain.h" // includes <windows.h>
  	#include "_TinyWindow.h"
  	#include "_TinyFileEnum.h"
  	#include "_TinyImageList.h"
  
  	#include <vector>
  
  	#include "..\LuaDebuggerResource.h"
  	#include <BlackBox/System/File/ICryPak.hpp>
  
  class CFileTree : public _TinyTreeView
  {
  public:
  	CFileTree() { m_iID = 0; };
  	virtual ~CFileTree() {};
  
  	using _TinyWindow::Create;
  	using _TinyTreeView::Create;
  	using _TinyTreeView::AddItemToTree;
  
  	BOOL Create(const _TinyRect& rcWnd, _TinyWindow* pParent = NULL, UINT iID = NULL)
  	{
  		m_iID = iID;
  		_TinyVerify(_TinyTreeView::Create(iID, WS_CHILD | TVS_HASLINES | TVS_HASBUTTONS | TVS_LINESATROOT |
  		                                  WS_VISIBLE, WS_EX_CLIENTEDGE, &rcWnd, pParent));
  		m_cTreeIcons.CreateFromBitmap(MAKEINTRESOURCE(IDB_TREE_VIEW), 16);
  		SetImageList(m_cTreeIcons.GetHandle());
  
  		return TRUE;
  	};
  
  	static int CALLBACK SortItems(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
  	{
  		CFileTree* parent = static_cast<CFileTree*>((CFileTree*)lParamSort);
  		int diff = (parent->m_isDir[lParam2] ? 1 : 0) - (parent->m_isDir[lParam1] ? 1 : 0);
  		if (diff)
  			return diff;
  		else
  			return stricmp(parent->m_vFileNameTbl[lParam1], parent->m_vFileNameTbl[lParam2]);
  	}
  
  	virtual HTREEITEM AddItemToTree(LPTSTR lpszItem, LPARAM ud = NULL, HTREEITEM hParent = NULL, UINT iImage = 0)
  	{
  		HTREEITEM res = _TinyTreeView::AddItemToTree(lpszItem, ud, hParent, iImage);
  		TVSORTCB sort;
  		sort.hParent = hParent;
  		sort.lParam = (LPARAM)this;
  		sort.lpfnCompare = &SortItems;
  		TreeView_SortChildrenCB(m_hWnd, &sort, FALSE);
  		return res;
  	}
  	virtual void RemoveItemFromTree(HTREEITEM itm)
  	{
  		TreeView_DeleteItem(m_hWnd, itm);
  	}
  
  	void ScanFiles(char* pszRootPath)
  	{
  		HTREEITEM hRoot = _TinyTreeView::AddItemToTree(pszRootPath, NULL, NULL, 2);
  		EnumerateScripts(hRoot, pszRootPath);
  		Expand(hRoot);
  	};
  
  	const char* GetCurItemFileName()
  	{
  		HTREEITEM hCurSel = NULL;
  		LPARAM nIdx;
  		hCurSel = _TinyTreeView::GetSelectedItem();
  		if (!hCurSel)
  			return NULL;
  		nIdx = _TinyTreeView::GetItemUserData(hCurSel);
  
  		size_t sz = m_vFileNameTbl.size();  // size_t is unsigned, so don't subtract 1
  		if ((0 == sz) || ((size_t)nIdx > (sz - 1)))
  			return NULL;
  		return m_vFileNameTbl[nIdx].c_str();
  	};
  
  protected:
  	_TinyImageList      m_cTreeIcons;
  	INT                 m_iID;
  	std::vector<string> m_vFileNameTbl;
  	std::vector<bool>   m_isDir;
  
  	int EnumerateScripts(HTREEITEM hRoot, char* pszEnumPath)
  	{
  		int num_added = 0;
  		_finddata_t c_file;
  		char szPath[_MAX_PATH];
  		char szFullFilePath[_MAX_PATH];
  		HTREEITEM hItem = NULL;
  
  		intptr_t hFile;
  
  		if ((hFile = gEnv->pCryPak->FindFirst((string(pszEnumPath) + "/*.*").c_str(), &c_file)) == -1L)
  			return 0;
  
  		while (gEnv->pCryPak->FindNext(hFile, &c_file) == 0)
  		{
  			if (_stricmp(c_file.name, "..") == 0)
  				continue;
  			if (_stricmp(c_file.name, ".") == 0)
  				continue;
  
  			sprintf(szFullFilePath, "%s%s", pszEnumPath, c_file.name);
  			m_vFileNameTbl.push_back(szFullFilePath);
  			m_isDir.push_back((c_file.attrib & _A_SUBDIR) != 0);
  
  			if (c_file.attrib & _A_SUBDIR)
  			{
  				HTREEITEM hItem = AddItemToTree(c_file.name, (LPARAM) m_vFileNameTbl.size() - 1, hRoot, 0);
  				sprintf(szPath, "%s%s/", pszEnumPath, c_file.name);
  				if (EnumerateScripts(hItem, szPath))
  				{
  					++num_added;
  				}
  				else
  				{
  					RemoveItemFromTree(hItem);
  				}
  			}
  			else
  			{
  				char fname[_MAX_PATH];
  				strcpy(fname, c_file.name);
  				_strlwr(fname);
  				if (!strchr(fname, '.'))
  					continue;
  				if (strcmp(strchr(fname, '.'), ".lua") == 0)
  				{
  					hItem = AddItemToTree(c_file.name, (LPARAM) m_vFileNameTbl.size() - 1, hRoot, 1);
  					++num_added;
  				}
  			}
  		}
  		return num_added;
  	};
  };
  
  #endif // CRY_PLATFORM_WINDOWS
  
  #endif
  