//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: A panel "metaclass" is a name given to a particular type of // panel with particular instance data. Such panels tend to be dynamically // added and removed from their parent panels. // // $Workfile: $ // $NoKeywords: $ //=============================================================================// #if !defined( PANELMETACLASSMGR_H ) #define PANELMETACLASSMGR_H #ifdef _WIN32 #pragma once #endif #include "tier0/dbg.h" #include "basetypes.h" #include //----------------------------------------------------------------------------- // forward declarations //----------------------------------------------------------------------------- class KeyValues; class Color; namespace vgui { class Panel; } //----------------------------------------------------------------------------- // Class factory interface for metaclasses //----------------------------------------------------------------------------- abstract_class IPanelFactory { public: // Creation, destruction methods virtual vgui::Panel *Create( const char *pMetaClassName, KeyValues* pKeyValues, void *pInitData, vgui::Panel *pParent ) = 0; }; //----------------------------------------------------------------------------- // Purpose: Singleton class responsible for managing vgui panel metaclasses // A metaclass is simply an association of panel implementation class with // various initialization data //----------------------------------------------------------------------------- abstract_class IPanelMetaClassMgr { public: // Call this to load up a file containing metaclass definitions virtual void LoadMetaClassDefinitionFile( const char *pFileName ) = 0; // Call this to install a new panel type // MetaClasses will refer to the panel type to create along with // various initialization data virtual void InstallPanelType( const char *pPanelName, IPanelFactory *pFactory ) = 0; // Creates a metaclass panel with the specified parent panel. // Chain name is used as a filter of the metaclass data; if specified, // it recursively iterates through the keyvalue sections and calls // chainKeyValue on sections whose name matches the chain name virtual vgui::Panel *CreatePanelMetaClass( const char *pMetaClassType, int sortorder, void *pInitData, vgui::Panel *pParent, const char *pChainName = NULL ) = 0; // removes a particular panel meta class virtual void DestroyPanelMetaClass( vgui::Panel *pPanel ) = 0; protected: // Don't delete me! virtual ~IPanelMetaClassMgr() {} }; //----------------------------------------------------------------------------- // Returns the panel meta class manager //----------------------------------------------------------------------------- IPanelMetaClassMgr *PanelMetaClassMgr(); //----------------------------------------------------------------------------- // Helper class for simple construction of planel class factories // This class is expected to be a singleton // Note the panel must have a constructor of the following form: // CPanel( vgui::Panel* ); // and it must have the following member function: // bool CPanel::Init( KeyValues* pInitData ) // which returns true if the panel initialized successfully //----------------------------------------------------------------------------- #include "tier0/memdbgon.h" template< class CPanel, class CInitData > class CPanelFactory : public IPanelFactory { public: CPanelFactory( const char *pTypeName ) { // Hook us up baby Assert( pTypeName ); PanelMetaClassMgr()->InstallPanelType( pTypeName, this ); } // Creation, destruction methods virtual vgui::Panel *Create( const char *pMetaClassName, KeyValues* pKeyValues, void *pVoidInitData, vgui::Panel *pParent ) { // NOTE: make sure this matches the panel allocation pattern; // it will break if panels are deleted differently CPanel* pPanel = new CPanel( pParent, pMetaClassName ); if (pPanel) { // Set parent before Init; it may be needed there... CInitData* pInitData = (CInitData*)(pVoidInitData); if (!pPanel->Init( pKeyValues, pInitData )) { delete pPanel; pPanel = NULL; } } return pPanel; } }; #include "tier0/memdbgoff.h" //----------------------------------------------------------------------------- // Helper macro to make panel factories one line of code. Use like this: // DECLARE_PANEL_FACTORY( CEntityImagePanel, CInitData, "image" ); // The type string is used in a panel script file to specify the type. // CInitData is the type of the data to pass to the init function //----------------------------------------------------------------------------- #define DECLARE_PANEL_FACTORY( _PanelClass, _InitData, _nameString ) \ CPanelFactory< _PanelClass, _InitData > g_ ## _PanelClass ## Factory( _nameString ) //----------------------------------------------------------------------------- // Helper class to make meta class panels //----------------------------------------------------------------------------- class CPanelWrapper { public: CPanelWrapper(); ~CPanelWrapper(); void Activate( char const* pMetaClassName, vgui::Panel *pParent, int sortorder, void *pVoidInitData ); void Deactivate( void ); vgui::Panel *GetPanel( ); private: vgui::Panel *m_pPanel; }; //----------------------------------------------------------------------------- // Macros for help with simple registration of panel metaclass // Put DECLARE_METACLASS_PANEL() in your class definition // and CONSTRUCT_METACLASS_PANEL() in your class constructor //----------------------------------------------------------------------------- #define DECLARE_METACLASS_PANEL( _memberName ) CPanelWrapper _memberName #define CONSTRUCT_METACLASS_PANEL( _memberName, _metaClassName, _parentPanel, _sortorder, _initData ) \ _memberName.Activate( _metaClassName, _parentPanel, _sortorder, _initData ) #define DESTRUCT_METACLASS_PANEL( _memberName ) \ _memberName.Deactivate() //----------------------------------------------------------------------------- // Helper KeyValues parsing methods //----------------------------------------------------------------------------- bool ParseRGBA( KeyValues* pValues, const char* pFieldName, int& r, int& g, int& b, int& a ); bool ParseRGBA( KeyValues* pValues, const char* pFieldName, Color& c ); bool ParseCoord( KeyValues* pValues, const char* pFieldName, int& x, int& y ); bool ParseRect( KeyValues* pValues, const char* pFieldName, int& x, int& y, int& w, int& h ); /* FIXME: Why do we have KeyValues too!?!??! Bleah bool ParseRGBA( KeyValues *pValues, const char* pFieldName, int& r, int& g, int& b, int& a ); bool ParseRGBA( KeyValues* pValues, const char* pFieldName, vgui::Color& c ); */ #endif // PANELMETACLASSMGR_H