//====== Copyright 1996-2005, Valve Corporation, All rights reserved. ======= // // Purpose: // //============================================================================= #if defined(WIN32) && !defined( _GAMECONSOLE ) #include #endif #undef PropertySheet #include "matsys_controls/gamefiletreeview.h" #include "filesystem.h" #include "tier1/keyvalues.h" #include "vgui/ISurface.h" #include "vgui/Cursor.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" using namespace vgui; //----------------------------------------------------------------------------- // list of all tree view icons //----------------------------------------------------------------------------- enum { IMAGE_FOLDER = 1, IMAGE_OPENFOLDER, IMAGE_FILE, }; //----------------------------------------------------------------------------- // Constructor //----------------------------------------------------------------------------- CGameFileTreeView::CGameFileTreeView( Panel *parent, const char *name, const char *pRootFolderName, const char *pRootDir, const char *pExtension ) : BaseClass(parent, name), m_Images( false ) { m_RootDir = pRootDir; m_Ext = pExtension; m_bUseExt = ( pExtension != NULL ); m_RootFolderName = pRootFolderName; // build our list of images m_Images.AddImage( scheme()->GetImage( "resource/icon_folder", false ) ); m_Images.AddImage( scheme()->GetImage( "resource/icon_folder_selected", false ) ); m_Images.AddImage( scheme()->GetImage( "resource/icon_file", false ) ); SetImageList( &m_Images, false ); } //----------------------------------------------------------------------------- // Purpose: Refreshes the active file list //----------------------------------------------------------------------------- void CGameFileTreeView::RefreshFileList() { RemoveAll(); SetFgColor(Color(216, 222, 211, 255)); // add the base node KeyValues *pkv = new KeyValues( "root" ); pkv->SetString( "text", m_RootFolderName ); pkv->SetInt( "root", 1 ); pkv->SetInt( "expand", 1 ); int iRoot = AddItem( pkv, GetRootItemIndex() ); pkv->deleteThis(); ExpandItem( iRoot, true ); } //----------------------------------------------------------------------------- // Selects the root folder //----------------------------------------------------------------------------- void CGameFileTreeView::SelectRoot() { AddSelectedItem( GetRootItemIndex(), true ); } //----------------------------------------------------------------------------- // Gets the number of root directories //----------------------------------------------------------------------------- int CGameFileTreeView::GetRootDirectoryCount() { return GetNumChildren( GetRootItemIndex() ); } //----------------------------------------------------------------------------- // Gets the ith root directory //----------------------------------------------------------------------------- const char *CGameFileTreeView::GetRootDirectory( int nIndex ) { int nItemIndex = GetChild( GetRootItemIndex(), nIndex ); KeyValues *kv = GetItemData( nItemIndex ); if ( !kv ) return NULL; return kv->GetString( "path", NULL ); } //----------------------------------------------------------------------------- // Populate the root node (necessary since tree view can't have multiple roots) //----------------------------------------------------------------------------- void CGameFileTreeView::PopulateRootNode( int itemIndex ) { AddDirectoriesOfNode( itemIndex, m_RootDir ); if ( m_bUseExt ) { AddFilesOfNode( itemIndex, m_RootDir, m_Ext ); } } //----------------------------------------------------------------------------- // Populate the root node with directories //----------------------------------------------------------------------------- bool CGameFileTreeView::DoesDirectoryHaveSubdirectories( const char *pFilePath ) { char pSearchString[MAX_PATH]; Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath ); // get the list of files FileFindHandle_t findHandle; // generate children // add all the items const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle ); while ( pszFileName ) { bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle ); if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) ) return true; pszFileName = g_pFullFileSystem->FindNext( findHandle ); } g_pFullFileSystem->FindClose( findHandle ); return false; } //----------------------------------------------------------------------------- // Populate the root node with directories //----------------------------------------------------------------------------- void CGameFileTreeView::AddDirectoriesOfNode( int itemIndex, const char *pFilePath ) { char pSearchString[MAX_PATH]; Q_snprintf( pSearchString, MAX_PATH, "%s\\*", pFilePath ); // get the list of files FileFindHandle_t findHandle; // generate children // add all the items const char *pszFileName = g_pFullFileSystem->FindFirstEx( pSearchString, "GAME", &findHandle ); while ( pszFileName ) { bool bIsDirectory = g_pFullFileSystem->FindIsDirectory( findHandle ); if ( bIsDirectory && Q_strnicmp( pszFileName, ".", 2 ) && Q_strnicmp( pszFileName, "..", 3 ) ) { KeyValues *kv = new KeyValues( "node", "text", pszFileName ); char pFullPath[MAX_PATH]; Q_snprintf( pFullPath, sizeof(pFullPath), "%s/%s", pFilePath, pszFileName ); Q_FixSlashes( pFullPath ); Q_strlower( pFullPath ); bool bHasSubdirectories = DoesDirectoryHaveSubdirectories( pFullPath ); kv->SetString( "path", pFullPath ); kv->SetInt( "expand", bHasSubdirectories ); kv->SetInt( "dir", 1 ); kv->SetInt( "image", IMAGE_FOLDER ); int itemID = AddItem(kv, itemIndex); kv->deleteThis(); // mark directories in orange SetItemColorForDirectories( itemID ); } pszFileName = g_pFullFileSystem->FindNext( findHandle ); } g_pFullFileSystem->FindClose( findHandle ); } //----------------------------------------------------------------------------- // Populate the root node with files //----------------------------------------------------------------------------- void CGameFileTreeView::AddFilesOfNode( int itemIndex, const char *pFilePath, const char *pExt ) { char pSearchString[MAX_PATH]; Q_snprintf( pSearchString, MAX_PATH, "%s\\*.%s", pFilePath, pExt ); // get the list of files FileFindHandle_t findHandle; // generate children // add all the items const char *pszFileName = g_pFullFileSystem->FindFirst( pSearchString, &findHandle ); while ( pszFileName ) { if ( !g_pFullFileSystem->FindIsDirectory( findHandle ) ) { KeyValues *kv = new KeyValues( "node", "text", pszFileName ); char pFullPath[MAX_PATH]; Q_snprintf( pFullPath, MAX_PATH, "%s\\%s", pFilePath, pszFileName ); kv->SetString( "path", pFullPath ); kv->SetInt( "image", IMAGE_FILE ); AddItem(kv, itemIndex); kv->deleteThis(); } pszFileName = g_pFullFileSystem->FindNext( findHandle ); } g_pFullFileSystem->FindClose( findHandle ); } //----------------------------------------------------------------------------- // override to incremental request and show p4 directories //----------------------------------------------------------------------------- void CGameFileTreeView::GenerateChildrenOfNode(int itemIndex) { KeyValues *pkv = GetItemData(itemIndex); if ( pkv->GetInt("root") ) { PopulateRootNode( itemIndex ); return; } if (!pkv->GetInt("dir")) return; const char *pFilePath = pkv->GetString("path", ""); if (!pFilePath[0]) return; surface()->SetCursor(dc_waitarrow); AddDirectoriesOfNode( itemIndex, pFilePath ); if ( m_bUseExt ) { AddFilesOfNode( itemIndex, pFilePath, m_Ext ); } } //----------------------------------------------------------------------------- // setup a context menu whenever a directory is clicked on //----------------------------------------------------------------------------- void CGameFileTreeView::GenerateContextMenu( int itemIndex, int x, int y ) { return; /* KeyValues *pkv = GetItemData(itemIndex); const char *pFilePath = pkv->GetString("path", ""); if (!pFilePath[0]) return; Menu *pContext = new Menu(this, "FileContext"); pContext->AddMenuItem("Cloak folder", new KeyValues("CloakFolder", "item", itemIndex), GetParent(), NULL); // show the context menu pContext->SetPos(x, y); pContext->SetVisible(true); */ } //----------------------------------------------------------------------------- // Sets an item to be colored as if its a menu //----------------------------------------------------------------------------- void CGameFileTreeView::SetItemColorForDirectories( int itemID ) { // mark directories in orange SetItemFgColor( itemID, Color(224, 192, 0, 255) ); } //----------------------------------------------------------------------------- // setup a smaller font //----------------------------------------------------------------------------- void CGameFileTreeView::ApplySchemeSettings(IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); SetFont( pScheme->GetFont("DefaultSmall") ); }