aboutsummaryrefslogtreecommitdiff
path: root/sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp
diff options
context:
space:
mode:
authorJørgen P. Tjernø <[email protected]>2013-12-02 19:31:46 -0800
committerJørgen P. Tjernø <[email protected]>2013-12-02 19:46:31 -0800
commitf56bb35301836e56582a575a75864392a0177875 (patch)
treede61ddd39de3e7df52759711950b4c288592f0dc /sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp
parentMark some more files as text. (diff)
downloadsource-sdk-2013-f56bb35301836e56582a575a75864392a0177875.tar.xz
source-sdk-2013-f56bb35301836e56582a575a75864392a0177875.zip
Fix line endings. WHAMMY.
Diffstat (limited to 'sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp')
-rw-r--r--sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp1186
1 files changed, 593 insertions, 593 deletions
diff --git a/sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp b/sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp
index a7474fb1..0e9eac52 100644
--- a/sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp
+++ b/sp/src/vgui2/vgui_controls/DirectorySelectDialog.cpp
@@ -1,594 +1,594 @@
-//========= Copyright Valve Corporation, All rights reserved. ============//
-//
-// Purpose:
-//
-//=============================================================================//
-
-#define PROTECTED_THINGS_DISABLE
-
-#include <vgui_controls/Button.h>
-#include <vgui_controls/ComboBox.h>
-#include <vgui_controls/DirectorySelectDialog.h>
-#include <vgui_controls/TreeView.h>
-#include <vgui_controls/ImageList.h>
-#include <vgui_controls/MessageBox.h>
-#include <vgui/Cursor.h>
-#include <KeyValues.h>
-#include <vgui/IInput.h>
-#include <vgui/ISurface.h>
-#include <vgui/ISystem.h>
-#include <filesystem.h>
-
-#ifdef WIN32
-#include <direct.h>
-#include <stdio.h>
-#include <io.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-
-// memdbgon must be the last include file in a .cpp file!!!
-#include <tier0/memdbgon.h>
-
-using namespace vgui;
-
-DirectoryTreeView::DirectoryTreeView(DirectorySelectDialog *parent, const char *name) : TreeView(parent, name)
-{
- m_pParent = parent;
-}
-
-void DirectoryTreeView::GenerateChildrenOfNode(int itemIndex)
-{
- m_pParent->GenerateChildrenOfDirectoryNode(itemIndex);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Used to prompt the user to create a directory
-//-----------------------------------------------------------------------------
-class CreateDirectoryDialog : public Frame
-{
- DECLARE_CLASS_SIMPLE(CreateDirectoryDialog, Frame);
-
-public:
- CreateDirectoryDialog(Panel *parent, const char *defaultCreateDirName) : BaseClass(parent, NULL)
- {
- SetSize(320, 100);
- SetSizeable(false);
- SetTitle("Choose directory name", false);
- MoveToCenterOfScreen();
-
- m_pOKButton = new Button(this, "OKButton", "#vgui_ok");
- m_pCancelButton = new Button(this, "OKButton", "#vgui_cancel");
- m_pNameEntry = new TextEntry(this, "NameEntry");
-
- m_pOKButton->SetCommand("OK");
- m_pCancelButton->SetCommand("Close");
- m_pNameEntry->SetText(defaultCreateDirName);
- m_pNameEntry->RequestFocus();
- m_pNameEntry->SelectAllText(true);
-
- // If some other window was hogging the input focus, then we have to hog it or else we'll never get input.
- m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
- if ( m_PrevAppFocusPanel )
- vgui::input()->SetAppModalSurface( GetVPanel() );
- }
-
- ~CreateDirectoryDialog()
- {
- if ( m_PrevAppFocusPanel )
- vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
- }
-
- virtual void PerformLayout()
- {
- BaseClass::PerformLayout();
-
- m_pNameEntry->SetBounds(24, 32, GetWide() - 48, 24);
- m_pOKButton->SetBounds(GetWide() - 176, 64, 72, 24);
- m_pCancelButton->SetBounds(GetWide() - 94, 64, 72, 24);
- }
-
- virtual void OnCommand(const char *command)
- {
- if (!stricmp(command, "OK"))
- {
- PostActionSignal(new KeyValues("CreateDirectory", "dir", GetControlString("NameEntry")));
- Close();
- }
- else
- {
- BaseClass::OnCommand(command);
- }
- }
-
- virtual void OnClose()
- {
- BaseClass::OnClose();
- MarkForDeletion();
- }
-
-private:
- vgui::Button *m_pOKButton;
- vgui::Button *m_pCancelButton;
- vgui::TextEntry *m_pNameEntry;
- vgui::VPANEL m_PrevAppFocusPanel;
-};
-
-//-----------------------------------------------------------------------------
-// Purpose: Constructor
-//-----------------------------------------------------------------------------
-DirectorySelectDialog::DirectorySelectDialog(vgui::Panel *parent, const char *title) : Frame(parent, NULL)
-{
- SetTitle(title, true);
- SetSize(320, 360);
- SetMinimumSize(300, 240);
- m_szCurrentDir[0] = 0;
- m_szDefaultCreateDirName[0] = 0;
-
- m_pDirTree = new DirectoryTreeView(this, "DirTree");
- m_pDriveCombo = new ComboBox(this, "DriveCombo", 6, false);
- m_pCancelButton = new Button(this, "CancelButton", "#VGui_Cancel");
- m_pSelectButton = new Button(this, "SelectButton", "#VGui_Select");
- m_pCreateButton = new Button(this, "CreateButton", "#VGui_CreateFolder");
- m_pCancelButton->SetCommand("Cancel");
- m_pSelectButton->SetCommand("Select");
- m_pCreateButton->SetCommand("Create");
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: lays out controls
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::PerformLayout()
-{
- BaseClass::PerformLayout();
-
- // lay out all the controls
- m_pDriveCombo->SetBounds(24, 30, GetWide() - 48, 24);
- m_pDirTree->SetBounds(24, 64, GetWide() - 48, GetTall() - 128);
-
- m_pCreateButton->SetBounds(24, GetTall() - 48, 104, 24);
- m_pSelectButton->SetBounds(GetWide() - 172, GetTall() - 48, 72, 24);
- m_pCancelButton->SetBounds(GetWide() - 96, GetTall() - 48, 72, 24);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: lays out controls
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::ApplySchemeSettings(IScheme *pScheme)
-{
- ImageList *imageList = new ImageList(false);
- imageList->AddImage(scheme()->GetImage("Resource/icon_folder", false));
- imageList->AddImage(scheme()->GetImage("Resource/icon_folder_selected", false));
- m_pDirTree->SetImageList(imageList, true);
-
- BaseClass::ApplySchemeSettings(pScheme);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Move the start string forward until we hit a slash and return the
-// the first character past the trailing slash
-//-----------------------------------------------------------------------------
-inline const char *MoveToNextSubDir( const char *pStart, int *nCount )
-{
- int nMoved = 0;
-
- // Move past pre-pended slash
- if ( pStart[nMoved] == '\\' )
- {
- nMoved++;
- }
-
- // Move past the current block of text until we've hit the next path seperator (or end)
- while ( pStart[nMoved] != '\\' && pStart[nMoved] != '\0' )
- {
- nMoved++;
- }
-
- // Move past trailing slash
- if ( pStart[nMoved] == '\\' )
- {
- nMoved++;
- }
-
- // Give back a count if they've supplied a pointer
- if ( nCount != NULL )
- {
- *nCount = nMoved;
- }
-
- // The beginning of the next string, past slash
- return (pStart+nMoved);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Walk through our directory structure given a path as our guide, while expanding
-// and populating the nodes of the tree view to match
-// Input : *path - path (with drive letter) to show
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::ExpandTreeToPath( const char *lpszPath, bool bSelectFinalDirectory /*= true*/ )
-{
- // Make sure our slashes are correct!
- char workPath[MAX_PATH];
- Q_strncpy( workPath, lpszPath, sizeof(workPath) );
- Q_FixSlashes( workPath );
-
- // Set us to the work drive
- SetStartDirectory( workPath );
-
- // Check that the path is valid
- if ( workPath[0] == '\0' || DoesDirectoryHaveSubdirectories( m_szCurrentDrive, "" ) == false )
- {
- // Failing, start in C:
- SetStartDirectory( "C:\\" );
- }
-
- // Start at the root of our tree
- int nItemIndex = m_pDirTree->GetRootItemIndex();
-
- // Move past the drive letter to the first subdir
- int nPathPos = 0;
- const char *lpszSubDirName = MoveToNextSubDir( workPath, &nPathPos );
- const char *lpszLastSubDirName = NULL;
- int nPathIncr = 0;
- char subDirName[MAX_PATH];
-
- // While there are subdirectory names present, expand and populate the tree with their subdirectories
- while ( lpszSubDirName[0] != '\0' )
- {
- // Move our string pointer forward while keeping where our last subdir started off
- lpszLastSubDirName = lpszSubDirName;
- lpszSubDirName = MoveToNextSubDir( lpszSubDirName, &nPathIncr );
-
- // Get the span between the last subdir and the new one
- Q_StrLeft( lpszLastSubDirName, nPathIncr, subDirName, sizeof(subDirName) );
- Q_StripTrailingSlash( subDirName );
-
- // Increment where we are in the string for use later
- nPathPos += nPathIncr;
-
- // Run through the list and expand to our currently selected directory
- for ( int i = 0; i < m_pDirTree->GetNumChildren( nItemIndex ); i++ )
- {
- // Get the child and data for it
- int nChild = m_pDirTree->GetChild( nItemIndex, i );
- KeyValues *pValues = m_pDirTree->GetItemData( nChild );
-
- // See if this matches
- if ( Q_stricmp( pValues->GetString( "Text" ), subDirName ) == 0 )
- {
- // This is the new root item
- nItemIndex = nChild;
-
- // Get the full path (starting from the drive letter) up to our current subdir
- Q_strncpy( subDirName, workPath, nPathPos );
- Q_AppendSlash( subDirName, sizeof(subDirName) );
-
- // Expand the tree node and populate its subdirs for our next iteration
- ExpandTreeNode( subDirName, nItemIndex );
- break;
- }
- }
- }
-
- // Select our last directory if we've been asked to (and it's valid)
- if ( bSelectFinalDirectory && m_pDirTree->IsItemIDValid( nItemIndex ) )
- {
- // If we don't call this once before selecting an item, the tree will not be properly expanded
- // before it calculates how to show the selected item in the view
- PerformLayout();
-
- // Select that item
- m_pDirTree->AddSelectedItem( nItemIndex, true );
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: sets where it should start searching
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::SetStartDirectory(const char *path)
-{
- strncpy(m_szCurrentDir, path, sizeof(m_szCurrentDir));
- strncpy(m_szCurrentDrive, path, sizeof(m_szCurrentDrive));
- m_szCurrentDrive[sizeof(m_szCurrentDrive) - 1] = 0;
- char *firstSlash = strstr(m_szCurrentDrive, "\\");
- if (firstSlash)
- {
- firstSlash[1] = 0;
- }
-
- BuildDirTree();
- BuildDriveChoices();
-
- // update state of create directory button
- int selectedIndex = m_pDirTree->GetFirstSelectedItem();
- if (m_pDirTree->IsItemIDValid(selectedIndex))
- {
- m_pCreateButton->SetEnabled(true);
- }
- else
- {
- m_pCreateButton->SetEnabled(false);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: sets what name should show up by default in the create directory dialog
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::SetDefaultCreateDirectoryName(const char *defaultCreateDirName)
-{
- strncpy(m_szDefaultCreateDirName, defaultCreateDirName, sizeof(m_szDefaultCreateDirName));
- m_szDefaultCreateDirName[sizeof(m_szDefaultCreateDirName) - 1] = 0;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: opens the dialog
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::DoModal()
-{
- input()->SetAppModalSurface(GetVPanel());
- BaseClass::Activate();
- MoveToCenterOfScreen();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Builds drive choices
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::BuildDriveChoices()
-{
- m_pDriveCombo->DeleteAllItems();
-
- char drives[256] = { 0 };
- int len = system()->GetAvailableDrives(drives, sizeof(drives));
- char *pBuf = drives;
- KeyValues *kv = new KeyValues("drive");
- for (int i = 0; i < len / 4; i++)
- {
- kv->SetString("drive", pBuf);
- int itemID = m_pDriveCombo->AddItem(pBuf, kv);
- if (!stricmp(pBuf, m_szCurrentDrive))
- {
- m_pDriveCombo->ActivateItem(itemID);
- }
-
- pBuf += 4;
- }
- kv->deleteThis();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Builds the base tree directory
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::BuildDirTree()
-{
- // clear current tree
- m_pDirTree->RemoveAll();
-
- // add in a root
- int rootIndex = m_pDirTree->AddItem(new KeyValues("root", "Text", m_szCurrentDrive), -1);
-
- // build first level of the tree
- ExpandTreeNode(m_szCurrentDrive, rootIndex);
-
- // start the root expanded
- m_pDirTree->ExpandItem(rootIndex, true);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: expands a path
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::ExpandTreeNode(const char *path, int parentNodeIndex)
-{
- // set the small wait cursor
- surface()->SetCursor(dc_waitarrow);
-
- // get all the subfolders of the current drive
- char searchString[512];
- sprintf(searchString, "%s*.*", path);
-
- FileFindHandle_t h;
- const char *pFileName = g_pFullFileSystem->FindFirstEx( searchString, NULL, &h );
- for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
- {
- if ( !Q_stricmp( pFileName, ".." ) || !Q_stricmp( pFileName, "." ) )
- continue;
-
- KeyValues *kv = new KeyValues("item");
- kv->SetString("Text", pFileName);
- // set the folder image
- kv->SetInt("Image", 1);
- kv->SetInt("SelectedImage", 1);
- kv->SetInt("Expand", DoesDirectoryHaveSubdirectories(path, pFileName));
- m_pDirTree->AddItem(kv, parentNodeIndex);
- }
- g_pFullFileSystem->FindClose( h );
-}
-
-//-----------------------------------------------------------------------------
-// Purpose:
-//-----------------------------------------------------------------------------
-bool DirectorySelectDialog::DoesDirectoryHaveSubdirectories(const char *path, const char *dir)
-{
- char searchString[512];
- sprintf(searchString, "%s%s\\*.*", path, dir);
-
- FileFindHandle_t h;
- const char *pFileName = g_pFullFileSystem->FindFirstEx( searchString, NULL, &h );
- for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
- {
- char szFullPath[ MAX_PATH ];
- Q_snprintf( szFullPath, sizeof(szFullPath), "%s\\%s", path, pFileName );
- Q_FixSlashes( szFullPath );
- if ( g_pFullFileSystem->IsDirectory( szFullPath ) )
- {
- g_pFullFileSystem->FindClose( h );
- return true;
- }
- }
- g_pFullFileSystem->FindClose( h );
- return false;
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Generates the children for the specified node
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::GenerateChildrenOfDirectoryNode(int nodeIndex)
-{
- // generate path
- char path[512];
- GenerateFullPathForNode(nodeIndex, path, sizeof(path));
-
- // expand out
- ExpandTreeNode(path, nodeIndex);
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: creates the full path for a node
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::GenerateFullPathForNode(int nodeIndex, char *path, int pathBufferSize)
-{
- // get all the nodes
- CUtlLinkedList<int, int> nodes;
- nodes.AddToTail(nodeIndex);
- int parentIndex = nodeIndex;
- while (1)
- {
- parentIndex = m_pDirTree->GetItemParent(parentIndex);
- if (parentIndex == -1)
- break;
- nodes.AddToHead(parentIndex);
- }
-
- // walk the nodes, adding to the path
- path[0] = 0;
- bool bFirst = true;
- FOR_EACH_LL( nodes, i )
- {
- KeyValues *kv = m_pDirTree->GetItemData( nodes[i] );
- strcat(path, kv->GetString("Text"));
-
- if (!bFirst)
- {
- strcat(path, "\\");
- }
- bFirst = false;
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Handles combo box changes
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::OnTextChanged()
-{
- KeyValues *kv = m_pDriveCombo->GetActiveItemUserData();
- if (!kv)
- return;
- const char *newDrive = kv->GetString("drive");
- if (stricmp(newDrive, m_szCurrentDrive))
- {
- // drive changed, reset
- SetStartDirectory(newDrive);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: creates a directory
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::OnCreateDirectory(const char *dir)
-{
- int selectedIndex = m_pDirTree->GetFirstSelectedItem();
- if (m_pDirTree->IsItemIDValid(selectedIndex))
- {
- char fullPath[512];
- GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
-
- // create the new directory underneath
- strcat(fullPath, dir);
- if (_mkdir(fullPath) == 0)
- {
- // add new path to tree view
- KeyValues *kv = new KeyValues("item");
- kv->SetString("Text", dir);
- // set the folder image
- kv->SetInt("Image", 1);
- kv->SetInt("SelectedImage", 1);
- int itemID = m_pDirTree->AddItem(kv, selectedIndex);
-
- // select the item
- m_pDirTree->AddSelectedItem( itemID, true );
- }
- else
- {
- // print error message
- MessageBox *box = new MessageBox("#vgui_CreateDirectoryFail_Title", "#vgui_CreateDirectoryFail_Info");
- box->DoModal(this);
- }
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: dialog closes
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::OnClose()
-{
- BaseClass::OnClose();
- MarkForDeletion();
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: handles button commands
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::OnCommand(const char *command)
-{
- if (!stricmp(command, "Cancel"))
- {
- Close();
- }
- else if (!stricmp(command, "Select"))
- {
- // path selected
- int selectedIndex = m_pDirTree->GetFirstSelectedItem();
- if (m_pDirTree->IsItemIDValid(selectedIndex))
- {
- char fullPath[512];
- GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
- PostActionSignal(new KeyValues("DirectorySelected", "dir", fullPath));
- Close();
- }
- }
- else if (!stricmp(command, "Create"))
- {
- int selectedIndex = m_pDirTree->GetFirstSelectedItem();
- if (m_pDirTree->IsItemIDValid(selectedIndex))
- {
- CreateDirectoryDialog *dlg = new CreateDirectoryDialog(this, m_szDefaultCreateDirName);
- dlg->AddActionSignalTarget(this);
- dlg->Activate();
- }
- }
- else
- {
- BaseClass::OnCommand(command);
- }
-}
-
-//-----------------------------------------------------------------------------
-// Purpose: Update the text in the combo
-//-----------------------------------------------------------------------------
-void DirectorySelectDialog::OnTreeViewItemSelected()
-{
- int selectedIndex = m_pDirTree->GetFirstSelectedItem();
- if (!m_pDirTree->IsItemIDValid(selectedIndex))
- {
- m_pCreateButton->SetEnabled(false);
- return;
- }
- m_pCreateButton->SetEnabled(true);
-
- // build the string
- char fullPath[512];
- GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
-
- int itemID = m_pDriveCombo->GetActiveItem();
- m_pDriveCombo->UpdateItem(itemID, fullPath, NULL);
- m_pDriveCombo->SetText(fullPath);
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+//=============================================================================//
+
+#define PROTECTED_THINGS_DISABLE
+
+#include <vgui_controls/Button.h>
+#include <vgui_controls/ComboBox.h>
+#include <vgui_controls/DirectorySelectDialog.h>
+#include <vgui_controls/TreeView.h>
+#include <vgui_controls/ImageList.h>
+#include <vgui_controls/MessageBox.h>
+#include <vgui/Cursor.h>
+#include <KeyValues.h>
+#include <vgui/IInput.h>
+#include <vgui/ISurface.h>
+#include <vgui/ISystem.h>
+#include <filesystem.h>
+
+#ifdef WIN32
+#include <direct.h>
+#include <stdio.h>
+#include <io.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include <tier0/memdbgon.h>
+
+using namespace vgui;
+
+DirectoryTreeView::DirectoryTreeView(DirectorySelectDialog *parent, const char *name) : TreeView(parent, name)
+{
+ m_pParent = parent;
+}
+
+void DirectoryTreeView::GenerateChildrenOfNode(int itemIndex)
+{
+ m_pParent->GenerateChildrenOfDirectoryNode(itemIndex);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Used to prompt the user to create a directory
+//-----------------------------------------------------------------------------
+class CreateDirectoryDialog : public Frame
+{
+ DECLARE_CLASS_SIMPLE(CreateDirectoryDialog, Frame);
+
+public:
+ CreateDirectoryDialog(Panel *parent, const char *defaultCreateDirName) : BaseClass(parent, NULL)
+ {
+ SetSize(320, 100);
+ SetSizeable(false);
+ SetTitle("Choose directory name", false);
+ MoveToCenterOfScreen();
+
+ m_pOKButton = new Button(this, "OKButton", "#vgui_ok");
+ m_pCancelButton = new Button(this, "OKButton", "#vgui_cancel");
+ m_pNameEntry = new TextEntry(this, "NameEntry");
+
+ m_pOKButton->SetCommand("OK");
+ m_pCancelButton->SetCommand("Close");
+ m_pNameEntry->SetText(defaultCreateDirName);
+ m_pNameEntry->RequestFocus();
+ m_pNameEntry->SelectAllText(true);
+
+ // If some other window was hogging the input focus, then we have to hog it or else we'll never get input.
+ m_PrevAppFocusPanel = vgui::input()->GetAppModalSurface();
+ if ( m_PrevAppFocusPanel )
+ vgui::input()->SetAppModalSurface( GetVPanel() );
+ }
+
+ ~CreateDirectoryDialog()
+ {
+ if ( m_PrevAppFocusPanel )
+ vgui::input()->SetAppModalSurface( m_PrevAppFocusPanel );
+ }
+
+ virtual void PerformLayout()
+ {
+ BaseClass::PerformLayout();
+
+ m_pNameEntry->SetBounds(24, 32, GetWide() - 48, 24);
+ m_pOKButton->SetBounds(GetWide() - 176, 64, 72, 24);
+ m_pCancelButton->SetBounds(GetWide() - 94, 64, 72, 24);
+ }
+
+ virtual void OnCommand(const char *command)
+ {
+ if (!stricmp(command, "OK"))
+ {
+ PostActionSignal(new KeyValues("CreateDirectory", "dir", GetControlString("NameEntry")));
+ Close();
+ }
+ else
+ {
+ BaseClass::OnCommand(command);
+ }
+ }
+
+ virtual void OnClose()
+ {
+ BaseClass::OnClose();
+ MarkForDeletion();
+ }
+
+private:
+ vgui::Button *m_pOKButton;
+ vgui::Button *m_pCancelButton;
+ vgui::TextEntry *m_pNameEntry;
+ vgui::VPANEL m_PrevAppFocusPanel;
+};
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+DirectorySelectDialog::DirectorySelectDialog(vgui::Panel *parent, const char *title) : Frame(parent, NULL)
+{
+ SetTitle(title, true);
+ SetSize(320, 360);
+ SetMinimumSize(300, 240);
+ m_szCurrentDir[0] = 0;
+ m_szDefaultCreateDirName[0] = 0;
+
+ m_pDirTree = new DirectoryTreeView(this, "DirTree");
+ m_pDriveCombo = new ComboBox(this, "DriveCombo", 6, false);
+ m_pCancelButton = new Button(this, "CancelButton", "#VGui_Cancel");
+ m_pSelectButton = new Button(this, "SelectButton", "#VGui_Select");
+ m_pCreateButton = new Button(this, "CreateButton", "#VGui_CreateFolder");
+ m_pCancelButton->SetCommand("Cancel");
+ m_pSelectButton->SetCommand("Select");
+ m_pCreateButton->SetCommand("Create");
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: lays out controls
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::PerformLayout()
+{
+ BaseClass::PerformLayout();
+
+ // lay out all the controls
+ m_pDriveCombo->SetBounds(24, 30, GetWide() - 48, 24);
+ m_pDirTree->SetBounds(24, 64, GetWide() - 48, GetTall() - 128);
+
+ m_pCreateButton->SetBounds(24, GetTall() - 48, 104, 24);
+ m_pSelectButton->SetBounds(GetWide() - 172, GetTall() - 48, 72, 24);
+ m_pCancelButton->SetBounds(GetWide() - 96, GetTall() - 48, 72, 24);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: lays out controls
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::ApplySchemeSettings(IScheme *pScheme)
+{
+ ImageList *imageList = new ImageList(false);
+ imageList->AddImage(scheme()->GetImage("Resource/icon_folder", false));
+ imageList->AddImage(scheme()->GetImage("Resource/icon_folder_selected", false));
+ m_pDirTree->SetImageList(imageList, true);
+
+ BaseClass::ApplySchemeSettings(pScheme);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Move the start string forward until we hit a slash and return the
+// the first character past the trailing slash
+//-----------------------------------------------------------------------------
+inline const char *MoveToNextSubDir( const char *pStart, int *nCount )
+{
+ int nMoved = 0;
+
+ // Move past pre-pended slash
+ if ( pStart[nMoved] == '\\' )
+ {
+ nMoved++;
+ }
+
+ // Move past the current block of text until we've hit the next path seperator (or end)
+ while ( pStart[nMoved] != '\\' && pStart[nMoved] != '\0' )
+ {
+ nMoved++;
+ }
+
+ // Move past trailing slash
+ if ( pStart[nMoved] == '\\' )
+ {
+ nMoved++;
+ }
+
+ // Give back a count if they've supplied a pointer
+ if ( nCount != NULL )
+ {
+ *nCount = nMoved;
+ }
+
+ // The beginning of the next string, past slash
+ return (pStart+nMoved);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Walk through our directory structure given a path as our guide, while expanding
+// and populating the nodes of the tree view to match
+// Input : *path - path (with drive letter) to show
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::ExpandTreeToPath( const char *lpszPath, bool bSelectFinalDirectory /*= true*/ )
+{
+ // Make sure our slashes are correct!
+ char workPath[MAX_PATH];
+ Q_strncpy( workPath, lpszPath, sizeof(workPath) );
+ Q_FixSlashes( workPath );
+
+ // Set us to the work drive
+ SetStartDirectory( workPath );
+
+ // Check that the path is valid
+ if ( workPath[0] == '\0' || DoesDirectoryHaveSubdirectories( m_szCurrentDrive, "" ) == false )
+ {
+ // Failing, start in C:
+ SetStartDirectory( "C:\\" );
+ }
+
+ // Start at the root of our tree
+ int nItemIndex = m_pDirTree->GetRootItemIndex();
+
+ // Move past the drive letter to the first subdir
+ int nPathPos = 0;
+ const char *lpszSubDirName = MoveToNextSubDir( workPath, &nPathPos );
+ const char *lpszLastSubDirName = NULL;
+ int nPathIncr = 0;
+ char subDirName[MAX_PATH];
+
+ // While there are subdirectory names present, expand and populate the tree with their subdirectories
+ while ( lpszSubDirName[0] != '\0' )
+ {
+ // Move our string pointer forward while keeping where our last subdir started off
+ lpszLastSubDirName = lpszSubDirName;
+ lpszSubDirName = MoveToNextSubDir( lpszSubDirName, &nPathIncr );
+
+ // Get the span between the last subdir and the new one
+ Q_StrLeft( lpszLastSubDirName, nPathIncr, subDirName, sizeof(subDirName) );
+ Q_StripTrailingSlash( subDirName );
+
+ // Increment where we are in the string for use later
+ nPathPos += nPathIncr;
+
+ // Run through the list and expand to our currently selected directory
+ for ( int i = 0; i < m_pDirTree->GetNumChildren( nItemIndex ); i++ )
+ {
+ // Get the child and data for it
+ int nChild = m_pDirTree->GetChild( nItemIndex, i );
+ KeyValues *pValues = m_pDirTree->GetItemData( nChild );
+
+ // See if this matches
+ if ( Q_stricmp( pValues->GetString( "Text" ), subDirName ) == 0 )
+ {
+ // This is the new root item
+ nItemIndex = nChild;
+
+ // Get the full path (starting from the drive letter) up to our current subdir
+ Q_strncpy( subDirName, workPath, nPathPos );
+ Q_AppendSlash( subDirName, sizeof(subDirName) );
+
+ // Expand the tree node and populate its subdirs for our next iteration
+ ExpandTreeNode( subDirName, nItemIndex );
+ break;
+ }
+ }
+ }
+
+ // Select our last directory if we've been asked to (and it's valid)
+ if ( bSelectFinalDirectory && m_pDirTree->IsItemIDValid( nItemIndex ) )
+ {
+ // If we don't call this once before selecting an item, the tree will not be properly expanded
+ // before it calculates how to show the selected item in the view
+ PerformLayout();
+
+ // Select that item
+ m_pDirTree->AddSelectedItem( nItemIndex, true );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets where it should start searching
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::SetStartDirectory(const char *path)
+{
+ strncpy(m_szCurrentDir, path, sizeof(m_szCurrentDir));
+ strncpy(m_szCurrentDrive, path, sizeof(m_szCurrentDrive));
+ m_szCurrentDrive[sizeof(m_szCurrentDrive) - 1] = 0;
+ char *firstSlash = strstr(m_szCurrentDrive, "\\");
+ if (firstSlash)
+ {
+ firstSlash[1] = 0;
+ }
+
+ BuildDirTree();
+ BuildDriveChoices();
+
+ // update state of create directory button
+ int selectedIndex = m_pDirTree->GetFirstSelectedItem();
+ if (m_pDirTree->IsItemIDValid(selectedIndex))
+ {
+ m_pCreateButton->SetEnabled(true);
+ }
+ else
+ {
+ m_pCreateButton->SetEnabled(false);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: sets what name should show up by default in the create directory dialog
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::SetDefaultCreateDirectoryName(const char *defaultCreateDirName)
+{
+ strncpy(m_szDefaultCreateDirName, defaultCreateDirName, sizeof(m_szDefaultCreateDirName));
+ m_szDefaultCreateDirName[sizeof(m_szDefaultCreateDirName) - 1] = 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: opens the dialog
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::DoModal()
+{
+ input()->SetAppModalSurface(GetVPanel());
+ BaseClass::Activate();
+ MoveToCenterOfScreen();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Builds drive choices
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::BuildDriveChoices()
+{
+ m_pDriveCombo->DeleteAllItems();
+
+ char drives[256] = { 0 };
+ int len = system()->GetAvailableDrives(drives, sizeof(drives));
+ char *pBuf = drives;
+ KeyValues *kv = new KeyValues("drive");
+ for (int i = 0; i < len / 4; i++)
+ {
+ kv->SetString("drive", pBuf);
+ int itemID = m_pDriveCombo->AddItem(pBuf, kv);
+ if (!stricmp(pBuf, m_szCurrentDrive))
+ {
+ m_pDriveCombo->ActivateItem(itemID);
+ }
+
+ pBuf += 4;
+ }
+ kv->deleteThis();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Builds the base tree directory
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::BuildDirTree()
+{
+ // clear current tree
+ m_pDirTree->RemoveAll();
+
+ // add in a root
+ int rootIndex = m_pDirTree->AddItem(new KeyValues("root", "Text", m_szCurrentDrive), -1);
+
+ // build first level of the tree
+ ExpandTreeNode(m_szCurrentDrive, rootIndex);
+
+ // start the root expanded
+ m_pDirTree->ExpandItem(rootIndex, true);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: expands a path
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::ExpandTreeNode(const char *path, int parentNodeIndex)
+{
+ // set the small wait cursor
+ surface()->SetCursor(dc_waitarrow);
+
+ // get all the subfolders of the current drive
+ char searchString[512];
+ sprintf(searchString, "%s*.*", path);
+
+ FileFindHandle_t h;
+ const char *pFileName = g_pFullFileSystem->FindFirstEx( searchString, NULL, &h );
+ for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
+ {
+ if ( !Q_stricmp( pFileName, ".." ) || !Q_stricmp( pFileName, "." ) )
+ continue;
+
+ KeyValues *kv = new KeyValues("item");
+ kv->SetString("Text", pFileName);
+ // set the folder image
+ kv->SetInt("Image", 1);
+ kv->SetInt("SelectedImage", 1);
+ kv->SetInt("Expand", DoesDirectoryHaveSubdirectories(path, pFileName));
+ m_pDirTree->AddItem(kv, parentNodeIndex);
+ }
+ g_pFullFileSystem->FindClose( h );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool DirectorySelectDialog::DoesDirectoryHaveSubdirectories(const char *path, const char *dir)
+{
+ char searchString[512];
+ sprintf(searchString, "%s%s\\*.*", path, dir);
+
+ FileFindHandle_t h;
+ const char *pFileName = g_pFullFileSystem->FindFirstEx( searchString, NULL, &h );
+ for ( ; pFileName; pFileName = g_pFullFileSystem->FindNext( h ) )
+ {
+ char szFullPath[ MAX_PATH ];
+ Q_snprintf( szFullPath, sizeof(szFullPath), "%s\\%s", path, pFileName );
+ Q_FixSlashes( szFullPath );
+ if ( g_pFullFileSystem->IsDirectory( szFullPath ) )
+ {
+ g_pFullFileSystem->FindClose( h );
+ return true;
+ }
+ }
+ g_pFullFileSystem->FindClose( h );
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Generates the children for the specified node
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::GenerateChildrenOfDirectoryNode(int nodeIndex)
+{
+ // generate path
+ char path[512];
+ GenerateFullPathForNode(nodeIndex, path, sizeof(path));
+
+ // expand out
+ ExpandTreeNode(path, nodeIndex);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: creates the full path for a node
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::GenerateFullPathForNode(int nodeIndex, char *path, int pathBufferSize)
+{
+ // get all the nodes
+ CUtlLinkedList<int, int> nodes;
+ nodes.AddToTail(nodeIndex);
+ int parentIndex = nodeIndex;
+ while (1)
+ {
+ parentIndex = m_pDirTree->GetItemParent(parentIndex);
+ if (parentIndex == -1)
+ break;
+ nodes.AddToHead(parentIndex);
+ }
+
+ // walk the nodes, adding to the path
+ path[0] = 0;
+ bool bFirst = true;
+ FOR_EACH_LL( nodes, i )
+ {
+ KeyValues *kv = m_pDirTree->GetItemData( nodes[i] );
+ strcat(path, kv->GetString("Text"));
+
+ if (!bFirst)
+ {
+ strcat(path, "\\");
+ }
+ bFirst = false;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Handles combo box changes
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::OnTextChanged()
+{
+ KeyValues *kv = m_pDriveCombo->GetActiveItemUserData();
+ if (!kv)
+ return;
+ const char *newDrive = kv->GetString("drive");
+ if (stricmp(newDrive, m_szCurrentDrive))
+ {
+ // drive changed, reset
+ SetStartDirectory(newDrive);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: creates a directory
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::OnCreateDirectory(const char *dir)
+{
+ int selectedIndex = m_pDirTree->GetFirstSelectedItem();
+ if (m_pDirTree->IsItemIDValid(selectedIndex))
+ {
+ char fullPath[512];
+ GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
+
+ // create the new directory underneath
+ strcat(fullPath, dir);
+ if (_mkdir(fullPath) == 0)
+ {
+ // add new path to tree view
+ KeyValues *kv = new KeyValues("item");
+ kv->SetString("Text", dir);
+ // set the folder image
+ kv->SetInt("Image", 1);
+ kv->SetInt("SelectedImage", 1);
+ int itemID = m_pDirTree->AddItem(kv, selectedIndex);
+
+ // select the item
+ m_pDirTree->AddSelectedItem( itemID, true );
+ }
+ else
+ {
+ // print error message
+ MessageBox *box = new MessageBox("#vgui_CreateDirectoryFail_Title", "#vgui_CreateDirectoryFail_Info");
+ box->DoModal(this);
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: dialog closes
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::OnClose()
+{
+ BaseClass::OnClose();
+ MarkForDeletion();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: handles button commands
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::OnCommand(const char *command)
+{
+ if (!stricmp(command, "Cancel"))
+ {
+ Close();
+ }
+ else if (!stricmp(command, "Select"))
+ {
+ // path selected
+ int selectedIndex = m_pDirTree->GetFirstSelectedItem();
+ if (m_pDirTree->IsItemIDValid(selectedIndex))
+ {
+ char fullPath[512];
+ GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
+ PostActionSignal(new KeyValues("DirectorySelected", "dir", fullPath));
+ Close();
+ }
+ }
+ else if (!stricmp(command, "Create"))
+ {
+ int selectedIndex = m_pDirTree->GetFirstSelectedItem();
+ if (m_pDirTree->IsItemIDValid(selectedIndex))
+ {
+ CreateDirectoryDialog *dlg = new CreateDirectoryDialog(this, m_szDefaultCreateDirName);
+ dlg->AddActionSignalTarget(this);
+ dlg->Activate();
+ }
+ }
+ else
+ {
+ BaseClass::OnCommand(command);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Update the text in the combo
+//-----------------------------------------------------------------------------
+void DirectorySelectDialog::OnTreeViewItemSelected()
+{
+ int selectedIndex = m_pDirTree->GetFirstSelectedItem();
+ if (!m_pDirTree->IsItemIDValid(selectedIndex))
+ {
+ m_pCreateButton->SetEnabled(false);
+ return;
+ }
+ m_pCreateButton->SetEnabled(true);
+
+ // build the string
+ char fullPath[512];
+ GenerateFullPathForNode(selectedIndex, fullPath, sizeof(fullPath));
+
+ int itemID = m_pDriveCombo->GetActiveItem();
+ m_pDriveCombo->UpdateItem(itemID, fullPath, NULL);
+ m_pDriveCombo->SetText(fullPath);
} \ No newline at end of file