diff options
Diffstat (limited to 'tools/toolutils/savewindowpositions.cpp')
| -rw-r--r-- | tools/toolutils/savewindowpositions.cpp | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/tools/toolutils/savewindowpositions.cpp b/tools/toolutils/savewindowpositions.cpp new file mode 100644 index 0000000..8447bf0 --- /dev/null +++ b/tools/toolutils/savewindowpositions.cpp @@ -0,0 +1,286 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//============================================================================= + +#include "toolutils/savewindowpositions.h" +#include "iregistry.h" +#include "vgui_controls/Panel.h" +#include "vgui_controls/PHandle.h" +#include "vgui_controls/ToolWindow.h" +#include "vgui/ISurface.h" +#include "vgui_controls/PropertySheet.h" +#include "tier1/utlsymbol.h" +#include "tier1/utlbuffer.h" +#include "tier1/KeyValues.h" +#include "filesystem.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +using namespace vgui; + +//----------------------------------------------------------------------------- +// Purpose: This will save the bounds and the visibility state of UI elements registered during startup +// FIXME: Preserve Z order? +//----------------------------------------------------------------------------- +class CWindowPositionMgr : public IWindowPositionMgr +{ +public: + // Inherited from IWindowPositionMgr + virtual void SavePositions( char const *filename, char const *key ); + virtual bool LoadPositions( char const *filename, Panel *parent, vgui::IToolWindowFactory *factory, char const *key, bool force = false ); + virtual void RegisterPanel( char const *saveName, Panel *panel, bool contextMenu ); + virtual void UnregisterPanel( vgui::Panel *panel ); + +private: + struct LoadInfo_t + { + CUtlSymbol m_Name; + PHandle m_hPanel; + bool m_bLoaded; + bool m_bContextMenu; + }; + + LoadInfo_t *Find( Panel *panel ); + LoadInfo_t *Find( char const *panelName ); + + CUtlVector< LoadInfo_t > m_Panels; +}; + + +//----------------------------------------------------------------------------- +// Singleton instance +//----------------------------------------------------------------------------- +static CWindowPositionMgr g_WindowPositionMgr; +IWindowPositionMgr *windowposmgr = &g_WindowPositionMgr; + +CWindowPositionMgr::LoadInfo_t *CWindowPositionMgr::Find( Panel *panel ) +{ + if ( !panel ) + return NULL; + + int c = m_Panels.Count(); + for ( int i = 0; i < c; ++i ) + { + LoadInfo_t *info = &m_Panels[ i ]; + if ( info->m_hPanel.Get() == panel ) + return info; + } + return NULL; +} + +CWindowPositionMgr::LoadInfo_t *CWindowPositionMgr::Find( char const *panelName ) +{ + if ( !panelName ) + return NULL; + + int c = m_Panels.Count(); + for ( int i = 0; i < c; ++i ) + { + LoadInfo_t *info = &m_Panels[ i ]; + if ( !Q_stricmp( info->m_Name.String(), panelName ) ) + return info; + } + return NULL; +} + +static void BufPrint( CUtlBuffer& buf, int level, char const *fmt, ... ) +{ + char string[ 2048 ]; + va_list argptr; + va_start( argptr, fmt ); + _vsnprintf( string, sizeof( string ) - 1, fmt, argptr ); + va_end( argptr ); + string[ sizeof( string ) - 1 ] = 0; + + while ( --level >= 0 ) + { + buf.Printf( " " ); + } + buf.Printf( "%s", string ); +} + +void CWindowPositionMgr::SavePositions( char const *filename, char const *key ) +{ + CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER ); + buf.Printf( "%s\n", key ); + buf.Printf( "{\n" ); + + int sw, sh; + vgui::surface()->GetScreenSize( sw, sh ); + float flOOW = (sw != 0.0f) ? 1.0f / (float)sw : 1.0f; + float flOOH = (sh != 0.0f) ? 1.0f / (float)sh : 1.0f; + + int c = ToolWindow::GetToolWindowCount(); + + for ( int i = 0 ; i < c; ++i ) + { + ToolWindow *tw = ToolWindow::GetToolWindow( i ); + Assert( tw ); + if ( !tw ) + continue; + + BufPrint( buf, 1, "toolwindow\n" ); + BufPrint( buf, 1, "{\n" ); + + // Get panel bounds + int x, y, w, h; + tw->GetBounds( x, y, w, h ); + + float fx = (float)x * flOOW; + float fy = (float)y * flOOH; + float fw = (float)w * flOOW; + float fh = (float)h * flOOH; + BufPrint( buf, 2, "bounds \"%.10f %.10f %.10f %.10f\"\n", fx, fy, fw, fh ); + + // Now iterate the actual contained panels + PropertySheet *sheet = tw->GetPropertySheet(); + Assert( sheet ); + if ( sheet ) + { + int subCount = sheet->GetNumPages(); + Assert( subCount > 0 ); + if ( subCount > 0 ) + { + BufPrint( buf, 2, "windows\n" ); + BufPrint( buf, 2, "{\n" ); + + for ( int s = 0 ; s < subCount; ++s ) + { + Panel *subPanel = sheet->GetPage( s ); + if ( !subPanel ) + continue; + + LoadInfo_t *info = Find( subPanel ); + if ( !info ) + continue; + + BufPrint( buf, 3, "panel \"%s\"\n", info->m_Name.String() ); + } + + BufPrint( buf, 2, "}\n" ); + } + } + + BufPrint( buf, 1, "}\n" ); + } + + buf.Printf( "}\n" ); + + if ( g_pFullFileSystem->FileExists( filename, "DEFAULT_WRITE_PATH" ) && + !g_pFullFileSystem->IsFileWritable( filename, "DEFAULT_WRITE_PATH" ) ) + { + Warning( "IFM window layout file '%s' is read-only!!!\n", filename ); + } + + FileHandle_t h = g_pFullFileSystem->Open( filename, "wb", "DEFAULT_WRITE_PATH" ); + if ( FILESYSTEM_INVALID_HANDLE != h ) + { + g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), h ); + g_pFullFileSystem->Close( h ); + } +} + +bool CWindowPositionMgr::LoadPositions( char const *filename, vgui::Panel *parent, vgui::IToolWindowFactory *factory, char const *key, bool force /*=false*/ ) +{ + bool success = false; + + int sw, sh; + vgui::surface()->GetScreenSize( sw, sh ); + + KeyValues *kv = new KeyValues( key ); + if ( kv->LoadFromFile( g_pFullFileSystem, filename, "GAME" ) ) + { + // Walk through tools + for ( KeyValues *tw = kv->GetFirstSubKey(); tw != NULL; tw = tw->GetNextKey() ) + { + if ( Q_stricmp( tw->GetName(), "toolwindow" ) ) + continue; + + // read bounds + float fx, fy, fw, fh; + int x, y, w, h; + char const *bounds = tw->GetString( "bounds", "" ); + if ( !bounds || !bounds[ 0 ] ) + continue; + + if ( 4 != sscanf( bounds, "%f %f %f %f", &fx, &fy, &fw, &fh ) ) + continue; + + x = (int)( sw * fx + 0.5f ); + y = (int)( sh * fy + 0.5f ); + w = (int)( sw * fw + 0.5f ); + h = (int)( sh * fh + 0.5f ); + + w = clamp( w, 0, sw ); + h = clamp( h, 0, sh ); + + // Now load pages + KeyValues *pages = tw->FindKey( "windows", false ); + if ( !pages ) + continue; + + ToolWindow *newTool = factory->InstanceToolWindow( parent, true, NULL, NULL, false ); + newTool->SetBounds( x, y, w, h ); + + for ( KeyValues *page = pages->GetFirstSubKey(); page != NULL; page = page->GetNextKey() ) + { + if ( Q_stricmp( page->GetName(), "panel" ) ) + continue; + + char const *pageName = page->GetString(); + if ( !pageName || !pageName[ 0 ] ) + continue; + + LoadInfo_t *info = Find( pageName ); + if ( !info ) + continue; + + newTool->AddPage( info->m_hPanel.Get(), info->m_Name.String(), info->m_bContextMenu ); + success = true; + } + + // If we didn't successfully create something, delete the tool + if ( !success ) + { + delete newTool; + } + } + } + kv->deleteThis(); + + return success; +} + +void CWindowPositionMgr::RegisterPanel( char const *saveName, Panel *panel, bool contextMenu ) +{ + char const *panelName = panel->GetName(); + if ( !panelName || !panelName[ 0 ] ) + { + Warning( "CWindowPositionMgr::RegisterPanel: Panel has NULL or blank name!!!\n" ); + return; + } + + LoadInfo_t info; + info.m_hPanel = panel; + info.m_Name = saveName; + info.m_bLoaded = false; + info.m_bContextMenu = contextMenu; + + m_Panels.AddToTail( info ); +} + +void CWindowPositionMgr::UnregisterPanel( vgui::Panel *panel ) +{ + int c = m_Panels.Count(); + for ( int i = c - 1; i >= 0; --i ) + { + if ( m_Panels[ i ].m_hPanel.Get() != panel ) + continue; + + m_Panels.Remove( i ); + break; + } +} |