Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

286 lines
7.1 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================
  6. #include "toolutils/savewindowpositions.h"
  7. #include "iregistry.h"
  8. #include "vgui_controls/Panel.h"
  9. #include "vgui_controls/PHandle.h"
  10. #include "vgui_controls/ToolWindow.h"
  11. #include "vgui/ISurface.h"
  12. #include "vgui_controls/PropertySheet.h"
  13. #include "tier1/utlsymbol.h"
  14. #include "tier1/utlbuffer.h"
  15. #include "tier1/KeyValues.h"
  16. #include "filesystem.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. using namespace vgui;
  20. //-----------------------------------------------------------------------------
  21. // Purpose: This will save the bounds and the visibility state of UI elements registered during startup
  22. // FIXME: Preserve Z order?
  23. //-----------------------------------------------------------------------------
  24. class CWindowPositionMgr : public IWindowPositionMgr
  25. {
  26. public:
  27. // Inherited from IWindowPositionMgr
  28. virtual void SavePositions( char const *filename, char const *key );
  29. virtual bool LoadPositions( char const *filename, Panel *parent, vgui::IToolWindowFactory *factory, char const *key, bool force = false );
  30. virtual void RegisterPanel( char const *saveName, Panel *panel, bool contextMenu );
  31. virtual void UnregisterPanel( vgui::Panel *panel );
  32. private:
  33. struct LoadInfo_t
  34. {
  35. CUtlSymbol m_Name;
  36. PHandle m_hPanel;
  37. bool m_bLoaded;
  38. bool m_bContextMenu;
  39. };
  40. LoadInfo_t *Find( Panel *panel );
  41. LoadInfo_t *Find( char const *panelName );
  42. CUtlVector< LoadInfo_t > m_Panels;
  43. };
  44. //-----------------------------------------------------------------------------
  45. // Singleton instance
  46. //-----------------------------------------------------------------------------
  47. static CWindowPositionMgr g_WindowPositionMgr;
  48. IWindowPositionMgr *windowposmgr = &g_WindowPositionMgr;
  49. CWindowPositionMgr::LoadInfo_t *CWindowPositionMgr::Find( Panel *panel )
  50. {
  51. if ( !panel )
  52. return NULL;
  53. int c = m_Panels.Count();
  54. for ( int i = 0; i < c; ++i )
  55. {
  56. LoadInfo_t *info = &m_Panels[ i ];
  57. if ( info->m_hPanel.Get() == panel )
  58. return info;
  59. }
  60. return NULL;
  61. }
  62. CWindowPositionMgr::LoadInfo_t *CWindowPositionMgr::Find( char const *panelName )
  63. {
  64. if ( !panelName )
  65. return NULL;
  66. int c = m_Panels.Count();
  67. for ( int i = 0; i < c; ++i )
  68. {
  69. LoadInfo_t *info = &m_Panels[ i ];
  70. if ( !Q_stricmp( info->m_Name.String(), panelName ) )
  71. return info;
  72. }
  73. return NULL;
  74. }
  75. static void BufPrint( CUtlBuffer& buf, int level, char const *fmt, ... )
  76. {
  77. char string[ 2048 ];
  78. va_list argptr;
  79. va_start( argptr, fmt );
  80. _vsnprintf( string, sizeof( string ) - 1, fmt, argptr );
  81. va_end( argptr );
  82. string[ sizeof( string ) - 1 ] = 0;
  83. while ( --level >= 0 )
  84. {
  85. buf.Printf( " " );
  86. }
  87. buf.Printf( "%s", string );
  88. }
  89. void CWindowPositionMgr::SavePositions( char const *filename, char const *key )
  90. {
  91. CUtlBuffer buf( 0, 0, CUtlBuffer::TEXT_BUFFER );
  92. buf.Printf( "%s\n", key );
  93. buf.Printf( "{\n" );
  94. int sw, sh;
  95. vgui::surface()->GetScreenSize( sw, sh );
  96. float flOOW = (sw != 0.0f) ? 1.0f / (float)sw : 1.0f;
  97. float flOOH = (sh != 0.0f) ? 1.0f / (float)sh : 1.0f;
  98. int c = ToolWindow::GetToolWindowCount();
  99. for ( int i = 0 ; i < c; ++i )
  100. {
  101. ToolWindow *tw = ToolWindow::GetToolWindow( i );
  102. Assert( tw );
  103. if ( !tw )
  104. continue;
  105. BufPrint( buf, 1, "toolwindow\n" );
  106. BufPrint( buf, 1, "{\n" );
  107. // Get panel bounds
  108. int x, y, w, h;
  109. tw->GetBounds( x, y, w, h );
  110. float fx = (float)x * flOOW;
  111. float fy = (float)y * flOOH;
  112. float fw = (float)w * flOOW;
  113. float fh = (float)h * flOOH;
  114. BufPrint( buf, 2, "bounds \"%.10f %.10f %.10f %.10f\"\n", fx, fy, fw, fh );
  115. // Now iterate the actual contained panels
  116. PropertySheet *sheet = tw->GetPropertySheet();
  117. Assert( sheet );
  118. if ( sheet )
  119. {
  120. int subCount = sheet->GetNumPages();
  121. Assert( subCount > 0 );
  122. if ( subCount > 0 )
  123. {
  124. BufPrint( buf, 2, "windows\n" );
  125. BufPrint( buf, 2, "{\n" );
  126. for ( int s = 0 ; s < subCount; ++s )
  127. {
  128. Panel *subPanel = sheet->GetPage( s );
  129. if ( !subPanel )
  130. continue;
  131. LoadInfo_t *info = Find( subPanel );
  132. if ( !info )
  133. continue;
  134. BufPrint( buf, 3, "panel \"%s\"\n", info->m_Name.String() );
  135. }
  136. BufPrint( buf, 2, "}\n" );
  137. }
  138. }
  139. BufPrint( buf, 1, "}\n" );
  140. }
  141. buf.Printf( "}\n" );
  142. if ( g_pFullFileSystem->FileExists( filename, "DEFAULT_WRITE_PATH" ) &&
  143. !g_pFullFileSystem->IsFileWritable( filename, "DEFAULT_WRITE_PATH" ) )
  144. {
  145. Warning( "IFM window layout file '%s' is read-only!!!\n", filename );
  146. }
  147. FileHandle_t h = g_pFullFileSystem->Open( filename, "wb", "DEFAULT_WRITE_PATH" );
  148. if ( FILESYSTEM_INVALID_HANDLE != h )
  149. {
  150. g_pFullFileSystem->Write( buf.Base(), buf.TellPut(), h );
  151. g_pFullFileSystem->Close( h );
  152. }
  153. }
  154. bool CWindowPositionMgr::LoadPositions( char const *filename, vgui::Panel *parent, vgui::IToolWindowFactory *factory, char const *key, bool force /*=false*/ )
  155. {
  156. bool success = false;
  157. int sw, sh;
  158. vgui::surface()->GetScreenSize( sw, sh );
  159. KeyValues *kv = new KeyValues( key );
  160. if ( kv->LoadFromFile( g_pFullFileSystem, filename, "GAME" ) )
  161. {
  162. // Walk through tools
  163. for ( KeyValues *tw = kv->GetFirstSubKey(); tw != NULL; tw = tw->GetNextKey() )
  164. {
  165. if ( Q_stricmp( tw->GetName(), "toolwindow" ) )
  166. continue;
  167. // read bounds
  168. float fx, fy, fw, fh;
  169. int x, y, w, h;
  170. char const *bounds = tw->GetString( "bounds", "" );
  171. if ( !bounds || !bounds[ 0 ] )
  172. continue;
  173. if ( 4 != sscanf( bounds, "%f %f %f %f", &fx, &fy, &fw, &fh ) )
  174. continue;
  175. x = (int)( sw * fx + 0.5f );
  176. y = (int)( sh * fy + 0.5f );
  177. w = (int)( sw * fw + 0.5f );
  178. h = (int)( sh * fh + 0.5f );
  179. w = clamp( w, 0, sw );
  180. h = clamp( h, 0, sh );
  181. // Now load pages
  182. KeyValues *pages = tw->FindKey( "windows", false );
  183. if ( !pages )
  184. continue;
  185. ToolWindow *newTool = factory->InstanceToolWindow( parent, true, NULL, NULL, false );
  186. newTool->SetBounds( x, y, w, h );
  187. for ( KeyValues *page = pages->GetFirstSubKey(); page != NULL; page = page->GetNextKey() )
  188. {
  189. if ( Q_stricmp( page->GetName(), "panel" ) )
  190. continue;
  191. char const *pageName = page->GetString();
  192. if ( !pageName || !pageName[ 0 ] )
  193. continue;
  194. LoadInfo_t *info = Find( pageName );
  195. if ( !info )
  196. continue;
  197. newTool->AddPage( info->m_hPanel.Get(), info->m_Name.String(), info->m_bContextMenu );
  198. success = true;
  199. }
  200. // If we didn't successfully create something, delete the tool
  201. if ( !success )
  202. {
  203. delete newTool;
  204. }
  205. }
  206. }
  207. kv->deleteThis();
  208. return success;
  209. }
  210. void CWindowPositionMgr::RegisterPanel( char const *saveName, Panel *panel, bool contextMenu )
  211. {
  212. char const *panelName = panel->GetName();
  213. if ( !panelName || !panelName[ 0 ] )
  214. {
  215. Warning( "CWindowPositionMgr::RegisterPanel: Panel has NULL or blank name!!!\n" );
  216. return;
  217. }
  218. LoadInfo_t info;
  219. info.m_hPanel = panel;
  220. info.m_Name = saveName;
  221. info.m_bLoaded = false;
  222. info.m_bContextMenu = contextMenu;
  223. m_Panels.AddToTail( info );
  224. }
  225. void CWindowPositionMgr::UnregisterPanel( vgui::Panel *panel )
  226. {
  227. int c = m_Panels.Count();
  228. for ( int i = c - 1; i >= 0; --i )
  229. {
  230. if ( m_Panels[ i ].m_hPanel.Get() != panel )
  231. continue;
  232. m_Panels.Remove( i );
  233. break;
  234. }
  235. }