diff options
Diffstat (limited to 'app/legion/menumanager.cpp')
| -rw-r--r-- | app/legion/menumanager.cpp | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/app/legion/menumanager.cpp b/app/legion/menumanager.cpp new file mode 100644 index 0000000..9fdd438 --- /dev/null +++ b/app/legion/menumanager.cpp @@ -0,0 +1,195 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: The menu manager +// +// $Revision: $ +// $NoKeywords: $ +//===========================================================================// + +#include "menumanager.h" +#include "vgui_controls/panel.h" +#include "vgui_controls/frame.h" +#include "uimanager.h" + + +//----------------------------------------------------------------------------- +// Singleton +//----------------------------------------------------------------------------- +static CMenuManager s_MenuManager; +extern CMenuManager *g_pMenuManager = &s_MenuManager; + + +//----------------------------------------------------------------------------- +// Static members. +// NOTE: Do *not* set this to 0; it could cause us to lose some registered +// menus since that list is set up during construction +//----------------------------------------------------------------------------- +IMenuFactory *CMenuManager::m_pFirstFactory; + + +//----------------------------------------------------------------------------- +// Call to register methods which can construct menus w/ particular names +//----------------------------------------------------------------------------- +IMenuFactory *CMenuManager::RegisterMenu( IMenuFactory *pMenuFactory ) +{ + // NOTE: This method is expected to be called during global constructor + // time, so it must not require any global constructors to be called to work + IMenuFactory *pPrevFactory = m_pFirstFactory; + m_pFirstFactory = pMenuFactory; + return pPrevFactory; +} + + +//----------------------------------------------------------------------------- +// Init, shutdown +//----------------------------------------------------------------------------- +bool CMenuManager::Init() +{ + // Build a dictionary of all registered menus + IMenuFactory *pFactory; + for ( pFactory = m_pFirstFactory; pFactory; pFactory = pFactory->GetNextFactory() ) + { + m_MenuFactories.Insert( pFactory->GetMenuName(), pFactory ); + } + + m_bPopRequested = false; + m_bPopAllRequested = false; + m_pPushRequested = NULL; + + return true; +} + +void CMenuManager::Shutdown() +{ + CleanUpAllMenus(); +} + + +//----------------------------------------------------------------------------- +// Push, pop menus +//----------------------------------------------------------------------------- +void CMenuManager::PushMenu( const char *pMenuName ) +{ + AssertMsg( !m_pPushRequested, "Can't request to push two menus in a single frame!" ); + + MenuFactoryIndex_t i = m_MenuFactories.Find( pMenuName ); + if ( i == m_MenuFactories.InvalidIndex() ) + { + Warning( "Tried to push unknown menu %s\n", pMenuName ); + return; + } + m_pPushRequested = m_MenuFactories[i]; +} + +void CMenuManager::PopMenu( ) +{ + AssertMsg( !m_bPopRequested, "Can't request to pop two menus in a single frame!" ); + AssertMsg( !m_pPushRequested, "Can't request to pop after requesting to push a menu in a single frame!" ); + m_bPopRequested = true; +} + +void CMenuManager::PopAllMenus( ) +{ + AssertMsg( !m_pPushRequested, "Can't request to pop after requesting to push a menu in a single frame!" ); + m_bPopAllRequested = true; +} + + +//----------------------------------------------------------------------------- +// Request a menu to switch to +//----------------------------------------------------------------------------- +void CMenuManager::SwitchToMenu( const char *pMenuName ) +{ + AssertMsg( !m_bPopRequested, "Can't request to pop two menus in a single frame!" ); + AssertMsg( !m_pPushRequested, "Can't request to push two menus in a single frame!" ); + + MenuFactoryIndex_t i = m_MenuFactories.Find( pMenuName ); + if ( i == m_MenuFactories.InvalidIndex() ) + { + Warning( "Tried to switch to unknown menu %s\n", pMenuName ); + return; + } + m_bPopRequested = true; + m_pPushRequested = m_MenuFactories[i]; +} + + +//----------------------------------------------------------------------------- +// Returns the name of the topmost panel +//----------------------------------------------------------------------------- +const char *CMenuManager::GetTopmostPanelName() +{ + if ( !m_nActiveMenu.Count() ) + return NULL; + return m_nActiveMenu.Top()->GetName(); +} + + +//----------------------------------------------------------------------------- +// Request a menu to switch to +//----------------------------------------------------------------------------- +void CMenuManager::Update( ) +{ + if ( m_bPopAllRequested ) + { + CleanUpAllMenus(); + m_bPopAllRequested = false; + return; + } + + if ( m_bPopRequested ) + { + AssertMsg( m_nActiveMenu.Count(), "Tried to pop a menu when no menus are active" ); + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->MarkForDeletion(); + m_nActiveMenu.Pop(); + + // Mark the new active menu as visible, attach it to hierarchy. + if ( m_nActiveMenu.Count() > 0 ) + { + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->SetVisible( true ); + pTop->SetParent( g_pUIManager->GetRootPanel( UI_ROOT_MENU ) ); + } + else + { + g_pUIManager->EnablePanel( UI_ROOT_MENU, false ); + } + m_bPopRequested = false; + } + + if ( m_pPushRequested ) + { + // Mark the previous menu as not visible, detach it from hierarchy. + if ( m_nActiveMenu.Count() > 0 ) + { + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->SetVisible( false ); + pTop->SetParent( (vgui::Panel*)NULL ); + } + else + { + g_pUIManager->EnablePanel( UI_ROOT_MENU, true ); + } + vgui::Panel *pMenu = m_pPushRequested->CreateMenu( g_pUIManager->GetRootPanel( UI_ROOT_MENU ) ); + m_nActiveMenu.Push( pMenu ); + static_cast<vgui::Frame*>( pMenu )->Activate(); + m_pPushRequested = NULL; + } +} + + +//----------------------------------------------------------------------------- +// Cleans up all menus +//----------------------------------------------------------------------------- +void CMenuManager::CleanUpAllMenus() +{ + while ( m_nActiveMenu.Count() ) + { + vgui::Panel *pTop = m_nActiveMenu.Top(); + pTop->MarkForDeletion(); + m_nActiveMenu.Pop(); + } + g_pUIManager->EnablePanel( UI_ROOT_MENU, false ); +} + |