Files
jasper/deps/nostalgia/src/olympic/studio/applib/src/newmenu.cpp

139 lines
3.4 KiB
C++

/*
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <algorithm>
#include <imgui.h>
#include <studio/imguiutil.hpp>
#include "newmenu.hpp"
namespace studio {
NewMenu::NewMenu() noexcept {
setTitle("New Item");
setSize({230, 140});
}
void NewMenu::open() noexcept {
m_stage = Stage::Opening;
m_selectedType = 0;
m_itemName = "";
m_typeName = "";
}
void NewMenu::close() noexcept {
m_stage = Stage::Closed;
m_open = false;
}
bool NewMenu::isOpen() const noexcept {
return m_open;
}
void NewMenu::draw(studio::StudioContext &sctx) noexcept {
switch (m_stage) {
case Stage::Opening:
ImGui::OpenPopup(title().c_str());
m_stage = Stage::NewItemType;
m_open = true;
[[fallthrough]];
case Stage::NewItemType:
drawNewItemType(sctx);
break;
case Stage::NewItemName:
drawNewItemName(sctx);
break;
case Stage::Closed:
m_open = false;
break;
}
}
void NewMenu::addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept {
m_types.emplace_back(std::move(im));
std::sort(
m_types.begin(), m_types.end(),
[](ox::UPtr<ItemMaker> const&im1, ox::UPtr<ItemMaker> const&im2) {
return im1->typeName < im2->typeName;
});
}
void NewMenu::drawNewItemType(studio::StudioContext &sctx) noexcept {
drawWindow(sctx.tctx, &m_open, [this] {
auto const allocSz = m_types.size() * sizeof(char const*);
auto mem = ox_malloca(allocSz, char const*, nullptr);
auto items = ox::Span{mem.get(), allocSz};
for (auto i = 0u; auto const&im : m_types) {
items[i] = im->typeName.c_str();
++i;
}
ImGui::ListBox("Item Type", &m_selectedType, items.data(), static_cast<int>(m_types.size()));
drawFirstPageButtons();
});
}
void NewMenu::drawNewItemName(studio::StudioContext &sctx) noexcept {
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
auto const typeIdx = static_cast<std::size_t>(m_selectedType);
if (typeIdx < m_types.size()) {
ig::InputText("Name", m_itemName);
}
drawLastPageButtons(sctx);
});
}
void NewMenu::drawFirstPageButtons() noexcept {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 130);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
auto const btnSz = ImVec2(60, 20);
if (ImGui::Button("Next", btnSz)) {
m_stage = Stage::NewItemName;
}
ImGui::SameLine();
if (ImGui::Button("Cancel", btnSz)) {
ImGui::CloseCurrentPopup();
m_stage = Stage::Closed;
}
}
void NewMenu::drawLastPageButtons(studio::StudioContext &sctx) noexcept {
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 138);
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
if (ImGui::Button("Back")) {
m_stage = Stage::NewItemType;
}
ImGui::SameLine();
if (ImGui::Button("Finish")) {
finish(sctx);
}
ImGui::SameLine();
if (ImGui::Button("Quit")) {
ImGui::CloseCurrentPopup();
m_stage = Stage::Closed;
}
}
void NewMenu::finish(studio::StudioContext &sctx) noexcept {
if (m_itemName.len() == 0) {
oxLogError(ox::Error(1, "New file error: no file name"));
return;
}
auto const&typeMaker = *m_types[static_cast<std::size_t>(m_selectedType)];
if (sctx.project->exists(typeMaker.itemPath(m_itemName))) {
oxLogError(ox::Error(1, "New file error: file already exists"));
return;
}
auto const [path, err] = typeMaker.write(sctx, m_itemName);
if (err) {
oxLogError(err);
return;
}
finished.emit(path);
m_stage = Stage::Closed;
}
}