source-engine/utils/scenemanager/workspace.cpp

473 lines
9.8 KiB
C++
Raw Permalink Normal View History

2020-04-23 00:56:21 +08:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=============================================================================//
#include "cbase.h"
#include "workspace.h"
#include <KeyValues.h>
#include "project.h"
#include "vstdlib/random.h"
#include "cmdlib.h"
#include "FileSystem_Tools.h"
#include "utlbuffer.h"
#include "workspacemanager.h"
#include "workspacebrowser.h"
#include "soundbrowser.h"
#include "wavebrowser.h"
CWorkspace::CWorkspace( char const *filename )
{
m_szVSSUserName[ 0 ] = 0;
m_szVSSProject[ 0 ] = 0;
Q_strncpy( m_szFile, filename, sizeof( m_szFile ) );
// By default, name is the same as the filename
Q_FileBase( m_szFile, m_szName, sizeof( m_szName ) );
m_bDirty = false;
LoadFromFile();
}
CWorkspace::~CWorkspace()
{
while ( m_Projects.Count() > 0 )
{
CProject *p = m_Projects[ 0 ];
m_Projects.Remove( 0 );
delete p;
}
}
char const *CWorkspace::GetName() const
{
return m_szName;
}
bool CWorkspace::IsDirty( void ) const
{
int c = GetProjectCount();
for ( int i = 0; i < c; i++ )
{
CProject *p = GetProject( i );
Assert( p );
if ( p->IsDirty() )
return true;
}
return m_bDirty;
}
void CWorkspace::SetDirty( bool dirty )
{
m_bDirty = dirty;
}
int CWorkspace::GetProjectCount() const
{
return m_Projects.Count();
}
CProject *CWorkspace::GetProject( int index ) const
{
if ( index < 0 || index >= m_Projects.Count() )
return NULL;
return m_Projects[ index ];
}
void CWorkspace::RemoveProject( CProject *project )
{
if ( m_Projects.Find( project ) == m_Projects.InvalidIndex() )
return;
m_Projects.FindAndRemove( project );
SetDirty( true );
}
void CWorkspace::AddProject( CProject *project )
{
SetDirty( true );
Assert( m_Projects.Find( project ) == m_Projects.InvalidIndex() );
m_Projects.AddToTail( project );
}
CProject *CWorkspace::FindProjectFile( char const *filename ) const
{
int c = GetProjectCount();
for ( int i = 0 ; i < c; i++ )
{
CProject *p = GetProject( i );
Assert( p );
if ( !Q_stricmp( p->GetFileName(), filename ) )
return p;
}
return NULL;
}
void CWorkspace::LoadFromFile()
{
KeyValues *kv = new KeyValues( m_szName );
if ( kv->LoadFromFile( filesystem, m_szFile ) )
{
for ( KeyValues *proj = kv->GetFirstSubKey(); proj; proj = proj->GetNextKey() )
{
// Add named projects
if ( !Q_stricmp( proj->GetName(), "project" ) )
{
bool expanded = false;
char filename[ 256 ];
filename[0] = 0;
for ( KeyValues *sub = proj->GetFirstSubKey(); sub; sub = sub->GetNextKey() )
{
if ( !Q_stricmp( sub->GetName(), "file" ) )
{
Q_strcpy( filename, sub->GetString() );
continue;
}
else if ( !Q_stricmp( sub->GetName(), "expanded" ) )
{
expanded = sub->GetInt() ? true : false;
continue;
}
else
{
Assert( 0 );
}
}
CProject *p = new CProject( this, filename );
p->SetExpanded( expanded );
p->SetDirty( false );
m_Projects.AddToTail( p );
continue;
}
else if ( !Q_stricmp( proj->GetName(), "vss_username" ) )
{
SetVSSUserName( proj->GetString() );
Con_Printf( "VSS User: '%s'\n", GetVSSUserName() );
continue;
}
else if ( !Q_stricmp( proj->GetName(), "vss_project" ) )
{
SetVSSProject( proj->GetString() );
Con_Printf( "VSS Project: '%s'\n", GetVSSProject() );
continue;
}
else if ( !Q_stricmp( proj->GetName(), "window" ) )
{
SetDirty( true );
char const *windowname = proj->GetString( "windowname", "" );
if ( !Q_stricmp( windowname, "workspace" ) )
{
SceneManager_LoadWindowPositions( proj, GetWorkspaceManager()->GetBrowser() );
continue;
}
else if ( !Q_stricmp( windowname, "soundbrowser" ) )
{
SceneManager_LoadWindowPositions( proj, GetWorkspaceManager()->GetSoundBrowser() );
continue;
}
else if ( !Q_stricmp( windowname, "wavebrowser" ) )
{
SceneManager_LoadWindowPositions( proj, GetWorkspaceManager()->GetWaveBrowser() );
continue;
}
else if ( !Q_stricmp( windowname, "main" ) )
{
SceneManager_LoadWindowPositions( proj, GetWorkspaceManager() );
continue;
}
else
{
Assert( 0 );
}
}
Assert( 0 );
}
}
kv->deleteThis();
}
static void SaveWindowPositions( CUtlBuffer& buf, char const *windowname, mxWindow *wnd )
{
buf.Printf( "\t\"window\"\n" );
buf.Printf( "\t{\n" );
buf.Printf( "\t\twindowname\t\"%s\"\n", windowname );
SceneManager_SaveWindowPositions( buf, 2, wnd );
buf.Printf( "\t}\n" );
}
void CWorkspace::SaveToFile()
{
SetDirty( false );
CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
buf.Printf( "%s\n{\n", GetName() );
// walk projects
int c = GetProjectCount();
for ( int i = 0; i < c; i++ )
{
CProject *p = GetProject( i );
Assert( p );
buf.Printf( "\t\"project\"\n" );
buf.Printf( "\t{\n" );
buf.Printf( "\t\t\"expanded\"\t\"%i\"\n", p->IsExpanded() );
buf.Printf( "\t\t\"file\"\t\"%s\"\n", p->GetFileName() );
buf.Printf( "\t}\n" );
p->SaveChanges();
}
buf.Printf( "\t\"vss_username\"\t\"%s\"\n", GetVSSUserName() );
buf.Printf( "\t\"vss_project\"\t\"%s\"\n", GetVSSProject() );
// Save window positions
SaveWindowPositions( buf, "main", GetWorkspaceManager() );
SaveWindowPositions( buf, "workspace", GetWorkspaceManager()->GetBrowser() );
SaveWindowPositions( buf, "soundbrowser", GetWorkspaceManager()->GetSoundBrowser() );
SaveWindowPositions( buf, "wavebrowser", GetWorkspaceManager()->GetWaveBrowser() );
buf.Printf( "}\n" );
if ( filesystem->FileExists( m_szFile ) && !filesystem->IsFileWritable( m_szFile ) )
{
int retval = mxMessageBox( NULL, va( "Check out '%s'?", m_szFile ), g_appTitle, MX_MB_YESNOCANCEL );
if ( retval != 0 )
return;
VSS_Checkout( m_szFile );
if ( !filesystem->IsFileWritable( m_szFile ) )
{
mxMessageBox( NULL, va( "Unable to check out'%s'!!!", m_szFile ), g_appTitle, MX_MB_OK );
return;
}
}
// Write it out baby
FileHandle_t fh = filesystem->Open( m_szFile, "wt" );
if (fh)
{
filesystem->Write( buf.Base(), buf.TellPut(), fh );
filesystem->Close(fh);
}
else
{
Con_Printf( "CWorkspace::SaveToFile: Unable to write file %s!!!\n", m_szFile );
}
}
void CWorkspace::SaveChanges()
{
if ( !IsDirty() )
return;
SaveToFile();
}
void CWorkspace::ValidateTree( mxTreeView *tree, mxTreeViewItem *parent )
{
CUtlVector< mxTreeViewItem * > m_KnownItems;
int c = GetProjectCount();
CProject *proj;
for ( int i = 0; i < c; i++ )
{
proj = GetProject( i );
if ( !proj )
continue;
char sz[ 256 ];
if ( proj->GetComments() && proj->GetComments()[0] )
{
Q_snprintf( sz, sizeof( sz ), "%s : %s", proj->GetName(), proj->GetComments() );
}
else
{
Q_strncpy( sz, proj->GetName(), sizeof( sz ) );
}
mxTreeViewItem *spot = proj->FindItem( tree, parent );
if ( !spot )
{
spot = tree->add( parent, sz );
}
m_KnownItems.AddToTail( spot );
proj->SetOrdinal ( i );
tree->setLabel( spot, sz );
tree->setImages( spot, proj->GetIconIndex(), proj->GetIconIndex() );
tree->setUserData( spot, proj );
//tree->setOpen( spot, proj->IsExpanded() );
proj->ValidateTree( tree, spot );
}
// Now check for dangling items
mxTreeViewItem *start = tree->getFirstChild( parent );
while ( start )
{
mxTreeViewItem *next = tree->getNextChild( start );
if ( m_KnownItems.Find( start ) == m_KnownItems.InvalidIndex() )
{
tree->remove( start );
}
start = next;
}
tree->sortTree( parent, true, CWorkspaceBrowser::CompareFunc, 0 );
}
bool CWorkspace::CanClose( void )
{
if ( !IsDirty() )
return true;
int retval = mxMessageBox( NULL, va( "Save changes to workspace '%s'?", GetName() ), g_appTitle, MX_MB_YESNOCANCEL );
if ( retval == 2 )
return false;
if ( retval == 0 )
{
SaveChanges();
}
return true;
}
char const *CWorkspace::GetVSSUserName() const
{
return m_szVSSUserName;
}
char const *CWorkspace::GetVSSProject() const
{
return m_szVSSProject;
}
void CWorkspace::SetVSSUserName( char const *username )
{
Q_strncpy( m_szVSSUserName, username, sizeof( m_szVSSUserName ) );
}
void CWorkspace::SetVSSProject( char const *projectname )
{
Q_strncpy( m_szVSSProject, projectname, sizeof( m_szVSSProject ) );
while ( Q_strlen( m_szVSSProject ) > 0 )
{
if ( m_szVSSProject[ Q_strlen( m_szVSSProject ) - 1 ] == '/' ||
m_szVSSProject[ Q_strlen( m_szVSSProject ) - 1 ] == '\\' )
{
m_szVSSProject[ Q_strlen( m_szVSSProject ) - 1 ] = 0;
}
else
{
break;
}
}
}
void CWorkspace::Checkout( bool updatestateicons /*= true*/ )
{
VSS_Checkout( GetFileName(), updatestateicons );
}
void CWorkspace::Checkin(bool updatestateicons /*= true*/)
{
VSS_Checkin( GetFileName(), updatestateicons );
}
bool CWorkspace::IsCheckedOut() const
{
return filesystem->IsFileWritable( GetFileName() );
}
int CWorkspace::GetIconIndex() const
{
if ( IsCheckedOut() )
{
return IMAGE_WORKSPACE_CHECKEDOUT;
}
else
{
return IMAGE_WORKSPACE;
}
}
void CWorkspace::MoveChildUp( ITreeItem *child )
{
int c = GetProjectCount();
for ( int i = 1; i < c; i++ )
{
CProject *p = GetProject( i );
if ( p != child )
continue;
CProject *prev = GetProject( i - 1 );
// Swap
m_Projects[ i - 1 ] = p;
m_Projects[ i ] = prev;
return;
}
}
void CWorkspace::MoveChildDown( ITreeItem *child )
{
int c = GetProjectCount();
for ( int i = 0; i < c - 1; i++ )
{
CProject *p = GetProject( i );
if ( p != child )
continue;
CProject *next = GetProject( i + 1 );
// Swap
m_Projects[ i ] = next;
m_Projects[ i + 1 ] = p;
return;
}
}
bool CWorkspace::IsChildFirst( ITreeItem *child )
{
int idx = m_Projects.Find( (CProject *)child );
if ( idx == m_Projects.InvalidIndex() )
return false;
if ( idx != 0 )
return false;
return true;
}
bool CWorkspace::IsChildLast( ITreeItem *child )
{
int idx = m_Projects.Find( (CProject *)child );
if ( idx == m_Projects.InvalidIndex() )
return false;
if ( idx != m_Projects.Count() - 1 )
return false;
return true;
}