#ifndef STAR_REGISTERED_PANE_MANAGER_HPP #define STAR_REGISTERED_PANE_MANAGER_HPP #include "StarPaneManager.hpp" namespace Star { // This class inherits PaneManager to allow for registered panes that are kept // internally by the class even when dismissed. They can be displayed, // dismissed, and toggled between the two without being lost. template class RegisteredPaneManager : public PaneManager { public: typedef KeyT Key; void registerPane(KeyT paneId, PaneLayer paneLayer, PanePtr pane, DismissCallback onDismiss = {}); PanePtr deregisterPane(KeyT const& paneId); void deregisterAllPanes(); template shared_ptr registeredPane(KeyT const& paneId) const; // Displays a registred pane if it is not already displayed. Returns true // if it is newly displayed. bool displayRegisteredPane(KeyT const& paneId); bool registeredPaneIsDisplayed(KeyT const& paneId) const; // Dismisses a registred pane if it is displayed. Returns true if it // has been dismissed. bool dismissRegisteredPane(KeyT const& paneId); // Returns whether the pane is now displayed. bool toggleRegisteredPane(KeyT const& paneId); private: struct PaneInfo { PaneLayer layer; PanePtr pane; DismissCallback dismissCallback; }; PaneInfo const& getRegisteredPaneInfo(KeyT const& paneId) const; // Map of registered panes by name. HashMap m_registeredPanes; }; template template shared_ptr RegisteredPaneManager::registeredPane(KeyT const& paneId) const { if (auto v = m_registeredPanes.ptr(paneId)) return convert(v->pane); throw GuiException(strf("No pane named '{}' found in RegisteredPaneManager", outputAny(paneId))); } template void RegisteredPaneManager::registerPane( KeyT paneId, PaneLayer paneLayer, PanePtr pane, DismissCallback onDismiss) { if (!m_registeredPanes.insert(move(paneId), {move(paneLayer), move(pane), move(onDismiss)}).second) throw GuiException( strf("Registered pane with name '{}' registered a second time in RegisteredPaneManager::registerPane", outputAny(paneId))); } template PanePtr RegisteredPaneManager::deregisterPane(KeyT const& paneId) { if (auto v = m_registeredPanes.maybeTake(paneId)) { if (isDisplayed(v->pane)) dismissPane(v->pane); return v->pane; } throw GuiException(strf("No pane named '{}' found in RegisteredPaneManager::deregisterPane", outputAny(paneId))); } template void RegisteredPaneManager::deregisterAllPanes() { for (auto const& k : m_registeredPanes.keys()) deregisterPane(k); } template bool RegisteredPaneManager::displayRegisteredPane(KeyT const& paneId) { auto const& paneInfo = getRegisteredPaneInfo(paneId); if (!isDisplayed(paneInfo.pane)) { displayPane(paneInfo.layer, paneInfo.pane, paneInfo.dismissCallback); return true; } return false; } template bool RegisteredPaneManager::registeredPaneIsDisplayed(KeyT const& paneId) const { return isDisplayed(getRegisteredPaneInfo(paneId).pane); } template bool RegisteredPaneManager::dismissRegisteredPane(KeyT const& paneId) { auto const& paneInfo = getRegisteredPaneInfo(paneId); if (isDisplayed(paneInfo.pane)) { dismissPane(paneInfo.pane); return true; } return false; } template bool RegisteredPaneManager::toggleRegisteredPane(KeyT const& paneId) { if (registeredPaneIsDisplayed(paneId)) { dismissRegisteredPane(paneId); return false; } else { displayRegisteredPane(paneId); return true; } } template typename RegisteredPaneManager::PaneInfo const& RegisteredPaneManager::getRegisteredPaneInfo( KeyT const& paneId) const { if (auto p = m_registeredPanes.ptr(paneId)) return *p; throw GuiException(strf("No registered pane with name '{}' found in RegisteredPaneManager", outputAny(paneId))); } } #endif