Files
sophia/engine/include/sophia/ui/panel_registry.hpp
T
2026-09-15 02:23:22 -07:00

108 lines
2.5 KiB
C++

#pragma once
#include <memory>
#include <sophia/frame_info.hpp>
#include <sophia/handles.hpp>
#include <sophia/ui/panel.hpp>
#include <sophia/util/assert.hpp>
#include <string_view>
#include <typeinfo>
#include <utility>
#include <vector>
namespace sophia {
class PanelRegistry {
public:
PanelRegistry(const PanelRegistry&) = delete;
PanelRegistry& operator=(const PanelRegistry&) = delete;
PanelRegistry() = default;
~PanelRegistry() = default;
PanelHandle add(std::unique_ptr<Panel> panel);
template <typename T, typename... Args>
PanelHandle emplace(Args&&... args) {
return add(std::make_unique<T>(std::forward<Args>(args)...));
}
const Panel& get(PanelHandle handle) const;
Panel& get(PanelHandle handle) {
return const_cast<Panel&>(std::as_const(*this).get(handle));
}
template <typename T>
const T& get(PanelHandle handle) const {
const Panel& panel = get(handle);
SOPHIA_ASSERT(dynamic_cast<const T*>(&panel) != nullptr,
"PanelHandle does not refer to a", typeid(T).name());
return static_cast<const T&>(panel);
}
template <typename T>
T& get(PanelHandle handle) {
return const_cast<T&>(std::as_const(*this).template get<T>(handle));
}
void remove(PanelHandle handle);
bool isValid(PanelHandle handle) const;
template <typename T>
const T* find() const {
for (const Slot& slot : slots) {
if (slot.panel) {
if (const T* panel = dynamic_cast<const T*>(slot.panel.get())) {
return panel;
}
}
}
return nullptr;
}
template <typename T>
T* find() {
return const_cast<T*>(std::as_const(*this).template find<T>());
}
const Panel* find(std::string_view name) const {
for (const Slot& slot : slots) {
if (slot.panel && slot.panel->getName() == name) {
return slot.panel.get();
}
}
return nullptr;
}
Panel* find(std::string_view name) {
return const_cast<Panel*>(std::as_const(*this).find(name));
}
u32 size() const;
u32 visibleCount() const;
std::vector<std::string_view> names() const {
std::vector<std::string_view> result;
result.reserve(slots.size());
for (const Slot& slot : slots) {
if (slot.panel) {
result.push_back(slot.panel->getName());
}
}
return result;
}
void update(const FrameInfo& frameInfo);
private:
struct Slot {
std::unique_ptr<Panel> panel;
u32 generation = 0;
};
std::vector<Slot> slots;
std::vector<u32> freeList;
};
} // namespace sophia