osb/source/windowing/StarRegisteredPaneManager.hpp
2023-07-04 22:36:27 +10:00

137 lines
4.3 KiB
C++

#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 <typename KeyT>
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 <typename T = Pane>
shared_ptr<T> registeredPane(KeyT const& paneId) const;
template <typename T = Pane>
shared_ptr<T> maybeRegisteredPane(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<KeyT, PaneInfo> m_registeredPanes;
};
template <typename KeyT>
template <typename T>
shared_ptr<T> RegisteredPaneManager<KeyT>::registeredPane(KeyT const& paneId) const {
if (auto v = m_registeredPanes.ptr(paneId))
return convert<T>(v->pane);
throw GuiException(strf("No pane named '{}' found in RegisteredPaneManager", outputAny(paneId)));
}
template <typename KeyT>
template <typename T>
shared_ptr<T> RegisteredPaneManager<KeyT>::maybeRegisteredPane(KeyT const& paneId) const {
if (auto v = m_registeredPanes.ptr(paneId))
return convert<T>(v->pane);
return {};
}
template <typename KeyT>
void RegisteredPaneManager<KeyT>::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 <typename KeyT>
PanePtr RegisteredPaneManager<KeyT>::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 <typename KeyT>
void RegisteredPaneManager<KeyT>::deregisterAllPanes() {
for (auto const& k : m_registeredPanes.keys())
deregisterPane(k);
}
template <typename KeyT>
bool RegisteredPaneManager<KeyT>::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 <typename KeyT>
bool RegisteredPaneManager<KeyT>::registeredPaneIsDisplayed(KeyT const& paneId) const {
return isDisplayed(getRegisteredPaneInfo(paneId).pane);
}
template <typename KeyT>
bool RegisteredPaneManager<KeyT>::dismissRegisteredPane(KeyT const& paneId) {
auto const& paneInfo = getRegisteredPaneInfo(paneId);
if (isDisplayed(paneInfo.pane)) {
dismissPane(paneInfo.pane);
return true;
}
return false;
}
template <typename KeyT>
bool RegisteredPaneManager<KeyT>::toggleRegisteredPane(KeyT const& paneId) {
if (registeredPaneIsDisplayed(paneId)) {
dismissRegisteredPane(paneId);
return false;
} else {
displayRegisteredPane(paneId);
return true;
}
}
template <typename KeyT>
typename RegisteredPaneManager<KeyT>::PaneInfo const& RegisteredPaneManager<KeyT>::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