Files
FC1/Editor/PanelTreeBrowser.cpp
romkazvo 34d6c5d489 123
2023-08-07 19:29:24 +08:00

952 lines
23 KiB
C++

// PanelTreeBrowser.cpp : implementation file
//
#include "stdafx.h"
#include "PanelTreeBrowser.h"
#include "PanelPreview.h"
#include "ViewManager.h"
#include "Viewport.h"
#include "Objects\EntityScript.h"
#include "EntityPrototype.h"
#include "EntityPrototypeLibrary.h"
#include "EntityPrototypeManager.h"
#include "Prefabs\PrefabManager.h"
#include "Settings.h"
#include <io.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
// Sort the item in reverse alphabetical order.
static int CALLBACK TreeCompareProc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
{
// lParamSort contains a pointer to the tree control.
// The lParam of an item is just its handle, as specified with SetItemData
CTreeCtrl* pTreeCtrl = (CTreeCtrl*)lParamSort;
int nChilds1 = (pTreeCtrl->ItemHasChildren((HTREEITEM)lParam1) == TRUE) ? 1 : 0;
int nChilds2 = (pTreeCtrl->ItemHasChildren((HTREEITEM)lParam2) == TRUE) ? 1 : 0;
if (nChilds1 != nChilds2)
return nChilds2 - nChilds1;
CString strItem1 = pTreeCtrl->GetItemText((HTREEITEM) lParam1);
CString strItem2 = pTreeCtrl->GetItemText((HTREEITEM) lParam2);
return stricmp(strItem1, strItem2);
}
//////////////////////////////////////////////////////////////////////////
// Simple sub string searching case insensitive.
//////////////////////////////////////////////////////////////////////////
inline const char* strstri( const char *s1, const char *s2)
{
int i,j,k;
for(i=0;s1[i];i++)
for(j=i,k=0;tolower(s1[j])==tolower(s2[k]);j++,k++)
if(!s2[k+1])
return (s1+i);
return NULL;
}
/////////////////////////////////////////////////////////////////////////////
// CPanelTreeBrowser dialog
StdMap<CString,int> CPanelTreeBrowser::m_selectionHistory;
CPanelTreeBrowser::FileHistory CPanelTreeBrowser::m_fileHistory;
CPanelTreeBrowser::CPanelTreeBrowser(CWnd* pParent /*=NULL*/)
: CXTResizeDialog(CPanelTreeBrowser::IDD, pParent)
{
//{{AFX_DATA_INIT(CPanelTreeBrowser)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_panelPreview = NULL;
m_panelPreviewId = 0;
}
CPanelTreeBrowser::~CPanelTreeBrowser()
{
if (m_panelPreviewId)
GetIEditor()->RemoveRollUpPage( ROLLUP_OBJECTS,m_panelPreviewId );
m_panelPreviewId = 0;
m_panelPreview = 0;
}
void CPanelTreeBrowser::DoDataExchange(CDataExchange* pDX)
{
CXTResizeDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_BROWSER_TREE, m_tree);
DDX_Control(pDX, IDC_RELOAD,m_reloadBtn );
DDX_Control(pDX, IDC_FILTER,m_filter );
}
BEGIN_MESSAGE_MAP(CPanelTreeBrowser, CXTResizeDialog)
ON_NOTIFY(NM_DBLCLK, IDC_BROWSER_TREE, OnDblclkBrowserTree)
ON_NOTIFY(TVN_SELCHANGED, IDC_BROWSER_TREE, OnSelchangedBrowserTree)
ON_NOTIFY(TVN_BEGINDRAG, IDC_BROWSER_TREE, OnBeginDrag)
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONUP()
ON_NOTIFY(NM_CLICK, IDC_BROWSER_TREE, OnClickBrowserTree)
ON_BN_CLICKED(IDC_RELOAD, OnReload)
ON_WM_DESTROY()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CPanelTreeBrowser message handlers
BOOL CPanelTreeBrowser::OnInitDialog()
{
CXTResizeDialog::OnInitDialog();
m_dragImage = 0;
m_bFiles = false;
CMFCUtils::LoadTrueColorImageList( m_cImageList,IDB_TREE_VIEW,16,RGB(255,0,255) );
// Create the list
//m_cImageList.Create(IDB_TREE_VIEW, 16, 1, RGB (255, 0, 255));
// Attach it to the control
m_tree.SetImageList(&m_cImageList, TVSIL_NORMAL);
//m_tree.SetImageList(&m_cImageList, TVSIL_STATE);
m_tree.SetIndent( 0 );
//m_tree.SetBkColor( RGB(0xE0,0xE0,0xE0) );
SetResize( IDC_BROWSER_TREE,SZ_RESIZE(1) );
SetResize( IDC_FILTER,SZ_RESIZE(1) );
// Add the Master CD folder to the list
//HTREEITEM hRoot = m_tree.InsertItem( "Root", 2, 2, TVI_ROOT);
/*
RecurseDirectory( "c:\\mastercd\\Objects", TVI_ROOT, "*.cgf" );
//m_tree.Expand( m_tree.GetRootItem(), TVE_COLLAPSE);
//CRect rc;
//GetClientRect( rc );
//int h = m_tree.GetVisibleCount()*m_tree.GetItemHeight();
//SetWindowPos( NULL,0,0,rc.right,h+80,SWP_NOMOVE );
m_tree.Expand( m_tree.GetFirstVisibleItem(), TVE_COLLAPSE);
*/
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::OnDestroy()
{
CXTResizeDialog::OnDestroy();
}
void CPanelTreeBrowser::Create( SelectCallback &cb,const CString &searchSpec,CWnd *parent,int flags )
{
CXTResizeDialog::Create( IDD,parent );
//////////////////////////////////////////////////////////////////////////
SetResize( IDC_RELOAD,SZ_HORREPOS(1) );
//////////////////////////////////////////////////////////////////////////
m_flags = flags;
m_bSelectOnClick = flags & SELECT_ONCLICK;
m_bDragDropEnabled = !(flags & NO_DRAGDROP);
m_searchspec = searchSpec;
Refresh(false);
m_selectCallback = cb;
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::Refresh( bool bReloadFiles )
{
CWaitCursor wait;
CString searchSpec = m_searchspec;
char dir[_MAX_PATH];
char drive[_MAX_DRIVE];
char fname[_MAX_FNAME];
char fext[_MAX_EXT];
_splitpath( searchSpec,drive,dir,fname,fext );
CString searchPath = Path::GetPath( searchSpec );
CString fileSpec = searchSpec.Mid( searchPath.GetLength() );
m_path = dir;
m_fileSpec = fileSpec;
//@HACK
// hardcoded names.
if (searchSpec == "*EntityClass")
{
// Entity classes.
FillEntityScripts();
}
else if (searchSpec == "*EntityPrototype")
{
// Entity prototypes.
FillEntityPrototypes();
}
else if (searchSpec == "*Prefabs")
{
// Entity prototypes.
FillPrefabs();
}
else
{
FileHistory::iterator it = m_fileHistory.find(fileSpec);
if (it == m_fileHistory.end() || bReloadFiles)
{
// Load files from disk.
FilesInfo finfo;
LoadFiles( finfo );
FillFiles( finfo );
}
else {
FillFiles( it->second );
}
m_bFiles = true;
/*
// Just files.
RecurseDirectory( GetIEditor()->GetMasterCDFolder(),dir,TVI_ROOT,fileSpec );
*/
CString numFiles;
numFiles.Format( "%d Files",m_itemsMap.GetCount() );
SetDlgItemText( IDC_NUM_FILES,numFiles );
}
SelectLastKnownItem();
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::AddPreviewPanel()
{
if (m_panelPreview)
return;
if (!(m_flags & NO_PREVIEW) && gSettings.bPreviewGeometryWindow)
{
// Searching geometries.
if (strstr(m_fileSpec,"*.ccgf") != 0 || strstr(m_fileSpec,"*.cgf") != 0 || strstr(m_fileSpec,"*.cga") != 0)
{
// Create Preview.
m_panelPreview = new CPanelPreview( AfxGetMainWnd() );
m_panelPreviewId = GetIEditor()->AddRollUpPage( ROLLUP_OBJECTS,"Object Preview",m_panelPreview );
}
}
}
void CPanelTreeBrowser::SelectLastKnownItem()
{
//Select item from history.
int index;
if (m_selectionHistory.Find(m_path+m_fileSpec,index))
{
int cnt = 0;
HTREEITEM hItem = GetTreeItemByIndex( m_tree.GetRootItem(),index,cnt );
if (hItem) {
m_tree.Select( hItem,TVGN_CARET );
m_tree.EnsureVisible( hItem );
}
}
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::SelectFile( const CString &filename )
{
SelectCallback cb = m_selectCallback;
m_selectCallback = 0;
HTREEITEM hItem = stl::find_in_map( m_fileToItem,filename,(HTREEITEM)0 );
if (hItem)
{
m_tree.Select( hItem,TVGN_CARET );
m_tree.EnsureVisible( hItem );
//m_tree.SetItemBold( hItem,TRUE );
//m_tree.SetItemColor( hItem,RGB(255,0,0) );
}
m_selectCallback = cb;
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::FillEntityScripts()
{
m_tree.SetRedraw(FALSE);
m_fileToItem.clear();
m_itemsMap.Clear();
m_tree.DeleteAllItems();
CString filter;
m_filter.GetWindowText( filter );
bool bFilter = !filter.IsEmpty();
StdMap<CString,HTREEITEM> items;
// Entity scripts.
std::vector<CEntityScript*> scripts;
CEntityScriptRegistry::Instance()->GetScripts( scripts );
for (int i = 0; i < scripts.size(); i++)
{
// If class is not usable simply skip it.
if (!scripts[i]->IsUsable())
continue;
CString name = scripts[i]->GetName();
if (bFilter)
{
if (strstri(name,filter) == 0)
continue;
}
HTREEITEM hRoot = TVI_ROOT;
char *token;
CString clsFile = scripts[i]->GetRelativeFile();
clsFile.Replace( "Scripts\\Default\\Entities\\","" );
char classFile[1024];
strcpy( classFile,clsFile );
token = strtok( classFile,"\\/" );
CString itemName;
while (token)
{
CString strToken = token;
token = strtok( NULL,"\\/" );
if (!token)
break;
itemName += strToken+"\\";
if (!items.Find( itemName,hRoot ))
{
hRoot = m_tree.InsertItem(strToken, 0, 0, hRoot );
m_tree.SetItemData( hRoot,(DWORD_PTR)hRoot );// Fort sorting.
items.Insert( itemName,hRoot );
}
}
HTREEITEM hNewItem = m_tree.InsertItem(name, 3, 3, hRoot );
m_tree.SetItemData( hNewItem,(DWORD_PTR)hNewItem );// Fort sorting.
m_tree.SetItemState(hNewItem, TVIS_BOLD, TVIS_BOLD);
m_itemsMap[hNewItem] = name;
}
CString numFiles;
numFiles.Format( "%d Entities",m_itemsMap.GetCount() );
SetDlgItemText( IDC_NUM_FILES,numFiles );
SortTree();
m_tree.SetRedraw(TRUE);
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::FillEntityPrototypes()
{
m_tree.SetRedraw(FALSE);
m_fileToItem.clear();
m_itemsMap.Clear();
m_tree.DeleteAllItems();
CString filter;
m_filter.GetWindowText( filter );
bool bFilter = !filter.IsEmpty();
CEntityPrototypeManager *protMan = GetIEditor()->GetEntityProtManager();
for (int j = 0; j < protMan->GetLibraryCount(); j++)
{
IDataBaseLibrary *lib = protMan->GetLibrary(j);
if (bFilter)
{
if (strstri(lib->GetName(),filter) == 0)
continue;
}
std::map<CString,HTREEITEM> groupMap;
HTREEITEM hLibItem = m_tree.InsertItem( lib->GetName(), 0, 0 );
m_tree.SetItemData( hLibItem,(DWORD_PTR)hLibItem );// Fort sorting.
for (int i = 0; i < lib->GetItemCount(); i++)
{
CEntityPrototype* prototype = (CEntityPrototype*)lib->GetItem(i);
CString groupName = prototype->GetGroupName();
HTREEITEM hGroupItem = hLibItem;
if (!groupName.IsEmpty())
{
HTREEITEM hItem = stl::find_in_map( groupMap,groupName,(HTREEITEM)0 );
if (hItem)
{
hGroupItem = hItem;
}
else
{
hGroupItem = m_tree.InsertItem( groupName, 0, 0, hLibItem );
m_tree.SetItemData( hGroupItem,(DWORD_PTR)hGroupItem );// Fort sorting.
groupMap[groupName] = hGroupItem;
}
}
CString itemName = prototype->GetShortName();
HTREEITEM hNewItem = m_tree.InsertItem(itemName, 3, 3, hGroupItem );
m_tree.SetItemData( hNewItem,(DWORD_PTR)hNewItem );// Fort sorting.
m_tree.SetItemState(hNewItem, TVIS_BOLD, TVIS_BOLD);
CString fullItemName = GuidUtil::ToString(prototype->GetGUID());
m_itemsMap[hNewItem] = fullItemName;
}
}
CString numFiles;
numFiles.Format( "%d Entities",m_itemsMap.GetCount() );
SetDlgItemText( IDC_NUM_FILES,numFiles );
SortTree();
m_tree.SetRedraw(TRUE);
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::FillPrefabs()
{
m_tree.SetRedraw(FALSE);
m_fileToItem.clear();
m_itemsMap.Clear();
m_tree.DeleteAllItems();
CString filter;
m_filter.GetWindowText( filter );
bool bFilter = !filter.IsEmpty();
CPrefabManager *pManager = GetIEditor()->GetPrefabManager();
for (int j = 0; j < pManager->GetLibraryCount(); j++)
{
IDataBaseLibrary *lib = pManager->GetLibrary(j);
if (bFilter)
{
if (strstri(lib->GetName(),filter) == 0)
continue;
}
std::map<CString,HTREEITEM> groupMap;
HTREEITEM hLibItem = m_tree.InsertItem( lib->GetName(), 0, 0 );
m_tree.SetItemData( hLibItem,(DWORD_PTR)hLibItem );// Fort sorting.
for (int i = 0; i < lib->GetItemCount(); i++)
{
CEntityPrototype* prototype = (CEntityPrototype*)lib->GetItem(i);
CString groupName = prototype->GetGroupName();
HTREEITEM hGroupItem = hLibItem;
if (!groupName.IsEmpty())
{
HTREEITEM hItem = stl::find_in_map( groupMap,groupName,(HTREEITEM)0 );
if (hItem)
{
hGroupItem = hItem;
}
else
{
hGroupItem = m_tree.InsertItem( groupName, 0, 0, hLibItem );
m_tree.SetItemData( hGroupItem,(DWORD_PTR)hGroupItem );// Fort sorting.
groupMap[groupName] = hGroupItem;
}
}
CString itemName = prototype->GetShortName();
HTREEITEM hNewItem = m_tree.InsertItem(itemName, 1, 1, hGroupItem );
m_tree.SetItemData( hNewItem,(DWORD_PTR)hNewItem );// Fort sorting.
m_tree.SetItemState(hNewItem, TVIS_BOLD, TVIS_BOLD);
CString fullItemName = GuidUtil::ToString(prototype->GetGUID());
m_itemsMap[hNewItem] = fullItemName;
}
}
CString numFiles;
numFiles.Format( "%d Prefabs",m_itemsMap.GetCount() );
SetDlgItemText( IDC_NUM_FILES,numFiles );
SortTree();
m_tree.SetRedraw(TRUE);
}
//////////////////////////////////////////////////////////////////////////
int CPanelTreeBrowser::RecurseDirectory( const CString &basePath,const CString &searchPath, HTREEITEM hRoot, LPCSTR pszFileSpec )
{
////////////////////////////////////////////////////////////////////////
// Enumerate all files in the passed directory which match to the the
// passed pattern. Also continue with adding all subdirectories
////////////////////////////////////////////////////////////////////////
CString szFolder = searchPath;
//char szFolder[_MAX_PATH];
//strcpy( szFolder,searchPath );
CFileEnum cTempFiles;
__finddata64_t sFile;
char szFilePath[_MAX_PATH];
HTREEITEM hNewRoot, hNewItem;
ASSERT(pszFileSpec);
CString fileSpec = pszFileSpec;
std::vector<CString> fileSpecs;
// Split file spec with ';'
while (!fileSpec.IsEmpty())
{
int splitpos = fileSpec.Find(';');
if (splitpos < 0)
{
fileSpecs.push_back(fileSpec);
break;
}
fileSpecs.push_back(fileSpec.Mid(0,splitpos));
fileSpec = fileSpec.Mid(splitpos+1);
}
// Make the path ready for appening a folder or filename
szFolder = Path::AddBackslash(szFolder);
int numFiles = 0;
// Start the enumeration of the files
if (cTempFiles.StartEnumeration(szFolder, "*.*", &sFile))
{
do
{
// Construct the full filepath of the current file
strcpy(szFilePath, szFolder);
strcat(szFilePath, sFile.name);
// Have we found a directory ?
if (sFile.attrib & _A_SUBDIR)
{
// Skip the parent directory entries
if (_stricmp(sFile.name, ".") == 0 ||
_stricmp(sFile.name, "..") == 0)
{
continue;
}
// Add it to the list and start recursion
hNewRoot = m_tree.InsertItem(sFile.name, 0, 0, hRoot);
m_tree.SetItemData( hNewRoot,(DWORD_PTR)hNewRoot );// Fort sorting.
int num = RecurseDirectory( basePath,szFilePath, hNewRoot, pszFileSpec);
m_tree.Expand( hNewRoot,TVE_COLLAPSE);
m_tree.SortChildren(hNewRoot);
if (num == 0)
{
// Delete empty directory item.
m_tree.DeleteItem( hNewRoot );
}
numFiles += num;
continue;
}
int nImage = 1;
// Check if the file name maches the pattern
bool bFileMatch = false;
for (int i = 0; i < fileSpecs.size(); i++)
{
if (PathMatchSpec(sFile.name,fileSpecs[i]))
{
bFileMatch = true;
break;
}
nImage = 2;
}
if (!bFileMatch)
continue;
// Remove the extension from the name
PathRenameExtension(sFile.name, "");
// Add the file to the list
hNewItem = m_tree.InsertItem(sFile.name, nImage, nImage, hRoot);
m_tree.SetItemData( hNewItem,(DWORD_PTR)hNewItem );// Fort sorting.
m_tree.SetItemState(hNewItem, TVIS_BOLD, TVIS_BOLD);
m_itemsMap[hNewItem] = szFilePath;
numFiles++;
} while (cTempFiles.GetNextFile(&sFile));
}
return numFiles;
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::LoadFiles( FilesInfo &info )
{
CString fileSpec = m_fileSpec;
CString currFileSpec;
static CFileUtil::FileArray files;
info.files.clear();
// Reserve many files.
files.resize(0);
files.reserve( 10000 );
// Split file spec with ';'
while (!fileSpec.IsEmpty())
{
int splitpos = fileSpec.Find(';');
if (splitpos < 0)
{
currFileSpec = fileSpec;
CFileUtil::ScanDirectory( m_path,currFileSpec,files,true );
break;
}
CString currFileSpec = fileSpec.Mid(0,splitpos);
CFileUtil::ScanDirectory( m_path,currFileSpec,files,true );
fileSpec = fileSpec.Mid(splitpos+1);
}
info.files.reserve( files.size() );
for (int i = 0; i < files.size(); i++)
{
info.files.push_back( files[i].filename );
}
//std::sort( info.files.begin(),info.files.end() );
m_fileHistory[m_fileSpec] = info;
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::FillFiles( FilesInfo &finfo )
{
m_tree.SetRedraw( FALSE );
m_fileToItem.clear();
m_itemsMap.Clear();
m_tree.DeleteAllItems();
int offsetPath = Path::AddBackslash(m_path).GetLength();
CString filter;
m_filter.GetWindowText( filter );
bool bFilter = !filter.IsEmpty();
CString filename,ext,path;
std::map<CString,HTREEITEM> pathmap;
for (int i = 0; i < finfo.files.size(); i++)
{
Path::Split( finfo.files[i],path,filename,ext );
if (bFilter)
{
if (strstri(filename,filter) == 0)
continue;
}
HTREEITEM hGroup = TVI_ROOT;
if (!path.IsEmpty())
{
hGroup = stl::find_in_map( pathmap,path,(HTREEITEM)0 );
if (!hGroup)
{
hGroup = TVI_ROOT;
int startPos = 0;
int prevPos = 0;
CString subpath;
while (startPos < path.GetLength())
{
prevPos = startPos;
int pos = path.Find( '\\',startPos );
if (pos >= 0)
{
startPos = pos+1;
}
else
startPos = path.GetLength();
subpath = path.Mid(0,pos);
HTREEITEM hItem = stl::find_in_map( pathmap,subpath,(HTREEITEM)0 );
if (!hItem)
{
CString subGroupName = path.Mid(prevPos,startPos-prevPos-1);
hGroup = m_tree.InsertItem( subGroupName,0,0,hGroup );
m_tree.SetItemData( hGroup,(DWORD_PTR)hGroup );// Fort sorting.
pathmap[subpath] = hGroup;
}
else
hGroup = hItem;
}
}
}
int nImage = 1;
if (stricmp(ext,".cga")==0)
{
nImage = 2;
}
HTREEITEM hNewItem = m_tree.InsertItem( filename, nImage, nImage, hGroup );
m_tree.SetItemData( hNewItem,(DWORD_PTR)hNewItem );// Fort sorting.
//m_tree.SetItemState(hNewItem, TVIS_BOLD, TVIS_BOLD);
CString filename = Path::AddBackslash(m_path) + finfo.files[i];
m_itemsMap[hNewItem] = filename;
m_fileToItem[filename] = hNewItem;
}
SortTree();
m_tree.SetRedraw( TRUE );
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::OnDblclkBrowserTree(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
if (m_tree.GetSelectedItem() == NULL)
return;
CString file = GetSelectedFile();
if (file.IsEmpty())
return;
AcceptFile( file );
}
CString CPanelTreeBrowser::GetSelectedFile()
{
////////////////////////////////////////////////////////////////////////
// Return the path of the currently selected file. If there is no
// currently selected file, just a NULL terminated string will be
// returned
////////////////////////////////////////////////////////////////////////
CString strFileName;
m_itemsMap.Find( m_tree.GetSelectedItem(),strFileName );
return strFileName;
}
void CPanelTreeBrowser::AcceptFile( const CString &file )
{
if (!file.IsEmpty())
{
// Select this file.
if (m_selectCallback)
m_selectCallback( file );
//GetIEditor()->StartObjectCreation( m_objectType,file );
}
}
bool CPanelTreeBrowser::GetTreeItemIndex( HTREEITEM hRoot,HTREEITEM hItem,int &index )
{
HTREEITEM hIt = hRoot;
while (hIt != NULL)
{
if (hIt == hItem)
return true;
index++;
if (m_tree.ItemHasChildren(hIt))
{
if (GetTreeItemIndex( m_tree.GetNextItem(hIt,TVGN_CHILD),hItem,index ))
{
return true;
}
}
hIt = m_tree.GetNextSiblingItem( hIt );
}
return false;
}
HTREEITEM CPanelTreeBrowser::GetTreeItemByIndex( HTREEITEM hRoot,int itemIndex,int &index )
{
HTREEITEM hIt = hRoot;
while (hIt != NULL)
{
if (index == itemIndex)
return hIt;
index++;
if (m_tree.ItemHasChildren(hIt))
{
HTREEITEM h = GetTreeItemByIndex( m_tree.GetNextItem(hIt,TVGN_CHILD),itemIndex,index );
if (h != NULL)
{
return h;
}
}
hIt = m_tree.GetNextSiblingItem( hIt );
}
return 0;
}
void CPanelTreeBrowser::OnSelchangedBrowserTree(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
int index = 0;
GetTreeItemIndex( m_tree.GetRootItem(),m_tree.GetSelectedItem(),index );
// Store selected item in history for this browser.
m_selectionHistory[m_path+m_fileSpec] = index;
// If geometry update preview.
if (m_panelPreview)
{
CString file = "";
m_itemsMap.Find( pNMTreeView->itemNew.hItem,file );
if (!file.IsEmpty())
{
// Check if preview panel is expended.
m_panelPreview->LoadFile( file );
}
}
if (m_bSelectOnClick)
{
CString file = "";
m_itemsMap.Find( pNMTreeView->itemNew.hItem,file );
if (!file.IsEmpty())
{
if (m_selectCallback)
m_selectCallback( file );
}
}
*pResult = 0;
}
void CPanelTreeBrowser::OnBeginDrag(NMHDR* pNMHDR, LRESULT* pResult)
{
NM_TREEVIEW* pNMTreeView = (NM_TREEVIEW*)pNMHDR;
if (!m_bDragDropEnabled)
return;
HTREEITEM hItem = pNMTreeView->itemNew.hItem;
m_draggedFile = "";
m_itemsMap.Find( hItem,m_draggedFile );
if (m_draggedFile.IsEmpty())
return;
m_tree.Select( hItem,TVGN_CARET );
m_dragImage = m_tree.CreateDragImage( hItem );
if (m_dragImage)
{
m_dragImage->BeginDrag(0, CPoint(-10, -10));
CRect rc;
AfxGetMainWnd()->GetWindowRect( rc );
CPoint p = pNMTreeView->ptDrag;
ClientToScreen( &p );
p.x -= rc.left;
p.y -= rc.top;
m_dragImage->DragEnter( AfxGetMainWnd(),p );
SetCapture();
GetIEditor()->EnableUpdate( false );
}
*pResult = 0;
}
void CPanelTreeBrowser::OnMouseMove(UINT nFlags, CPoint point)
{
CRect rc;
AfxGetMainWnd()->GetWindowRect( rc );
ClientToScreen( &point );
point.x -= rc.left;
point.y -= rc.top;
if (m_dragImage)
{
m_dragImage->DragMove( point );
}
//CXTResizeDialog::OnMouseMove(nFlags, point);
}
void CPanelTreeBrowser::OnLButtonUp(UINT nFlags, CPoint point)
{
//CXTResizeDialog::OnLButtonUp(nFlags, point);
if (m_dragImage)
{
CPoint p;
GetCursorPos( &p );
GetIEditor()->EnableUpdate( true );
m_dragImage->DragLeave( AfxGetMainWnd() );
m_dragImage->EndDrag();
delete m_dragImage;
m_dragImage = 0;
ReleaseCapture();
CViewport *pView = GetIEditor()->GetViewManager()->GetViewportAtPoint(p);
if (pView)
{
// Drag and drop into one of views.
// Start object creation.
AcceptFile( m_draggedFile );
}
}
}
void CPanelTreeBrowser::OnClickBrowserTree(NMHDR* pNMHDR, LRESULT* pResult)
{
*pResult = 0;
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::OnReload()
{
Refresh(true);
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::SortItem( HTREEITEM hParent )
{
TVSORTCB tvs;
tvs.hParent = hParent;
tvs.lpfnCompare = TreeCompareProc;
tvs.lParam = (LPARAM)&m_tree;
m_tree.SortChildrenCB(&tvs);
// Look at all of the root-level items
HTREEITEM hCurrent = m_tree.GetNextItem( hParent,TVGN_CHILD );
while (hCurrent != NULL)
{
SortItem( hCurrent );
// Try to get the next item
hCurrent = m_tree.GetNextItem(hCurrent, TVGN_NEXT);
}
}
//////////////////////////////////////////////////////////////////////////
void CPanelTreeBrowser::SortTree()
{
SortItem( TVI_ROOT );
}