[keel,studio] Add support for New Item templates
Some checks failed
Build / build (push) Failing after 1m3s
Some checks failed
Build / build (push) Failing after 1m3s
This commit is contained in:
@ -14,7 +14,7 @@ namespace studio {
|
||||
|
||||
NewMenu::NewMenu() noexcept {
|
||||
setTitle("New Item");
|
||||
setSize({230, 140});
|
||||
setSize({280, 180});
|
||||
}
|
||||
|
||||
void NewMenu::open() noexcept {
|
||||
@ -33,7 +33,7 @@ bool NewMenu::isOpen() const noexcept {
|
||||
return m_open;
|
||||
}
|
||||
|
||||
void NewMenu::draw(studio::StudioContext &sctx) noexcept {
|
||||
void NewMenu::draw(StudioContext &sctx) noexcept {
|
||||
switch (m_stage) {
|
||||
case Stage::Opening:
|
||||
ImGui::OpenPopup(title().c_str());
|
||||
@ -46,51 +46,73 @@ void NewMenu::draw(studio::StudioContext &sctx) noexcept {
|
||||
case Stage::NewItemName:
|
||||
drawNewItemName(sctx);
|
||||
break;
|
||||
case Stage::NewItemTemplate:
|
||||
drawNewItemTemplate(sctx);
|
||||
break;
|
||||
case Stage::Closed:
|
||||
m_open = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void NewMenu::addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept {
|
||||
void NewMenu::addItemMaker(ox::UPtr<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;
|
||||
return im1->typeDisplayName() < im2->typeDisplayName();
|
||||
});
|
||||
}
|
||||
|
||||
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;
|
||||
void NewMenu::installItemTemplate(ox::UPtr<ItemTemplate> &tmplt) noexcept {
|
||||
for (auto const&im : m_types) {
|
||||
if (im->installTemplate(tmplt)) {
|
||||
break;
|
||||
}
|
||||
ImGui::ListBox("Item Type", &m_selectedType, items.data(), static_cast<int>(m_types.size()));
|
||||
drawFirstPageButtons();
|
||||
}
|
||||
}
|
||||
|
||||
void NewMenu::drawNewItemType(StudioContext const&sctx) noexcept {
|
||||
drawWindow(sctx.tctx, m_open, [this] {
|
||||
ig::ListBox("Item Type", [&](size_t const i) -> ox::CStringView {
|
||||
return m_types[i]->typeDisplayName();
|
||||
}, m_types.size(), m_selectedType, {200, 100});
|
||||
auto const&im = *m_types[m_selectedType];
|
||||
drawFirstPageButtons(im.itemTemplates().size() == 1 ?
|
||||
Stage::NewItemName : Stage::NewItemTemplate);
|
||||
});
|
||||
}
|
||||
|
||||
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()) {
|
||||
void NewMenu::drawNewItemTemplate(StudioContext &sctx) noexcept {
|
||||
drawWindow(sctx.tctx, m_open, [this] {
|
||||
auto const&templates =
|
||||
m_types[m_selectedType]->itemTemplates();
|
||||
ig::ListBox("Template", [&](size_t const i) -> ox::CStringView {
|
||||
return templates[i]->name();
|
||||
}, templates.size(), m_selectedTemplate, {200, 100});
|
||||
drawButtons(Stage::NewItemType, Stage::NewItemName);
|
||||
});
|
||||
}
|
||||
|
||||
void NewMenu::drawNewItemName(StudioContext &sctx) noexcept {
|
||||
drawWindow(sctx.tctx, m_open, [this, &sctx] {
|
||||
if (m_selectedType < m_types.size()) {
|
||||
ig::InputText("Name", m_itemName);
|
||||
}
|
||||
drawLastPageButtons(sctx);
|
||||
});
|
||||
}
|
||||
|
||||
void NewMenu::drawFirstPageButtons() noexcept {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 130);
|
||||
void NewMenu::drawButtons(Stage const prev, Stage const next) noexcept {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 198);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
||||
auto const btnSz = ImVec2(60, 20);
|
||||
constexpr ImVec2 btnSz{60, 20};
|
||||
if (ImGui::Button("Back", btnSz)) {
|
||||
m_stage = prev;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Next", btnSz)) {
|
||||
m_stage = Stage::NewItemName;
|
||||
m_stage = next;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Cancel", btnSz)) {
|
||||
@ -99,34 +121,50 @@ void NewMenu::drawFirstPageButtons() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
void NewMenu::drawLastPageButtons(studio::StudioContext &sctx) noexcept {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 138);
|
||||
void NewMenu::drawFirstPageButtons(Stage const next) noexcept {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 130);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
||||
if (ImGui::Button("Back")) {
|
||||
m_stage = Stage::NewItemType;
|
||||
constexpr ImVec2 btnSz{60, 20};
|
||||
if (ImGui::Button("Next", btnSz)) {
|
||||
m_stage = next;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Finish")) {
|
||||
finish(sctx);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Quit")) {
|
||||
if (ImGui::Button("Cancel", btnSz)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
m_stage = Stage::Closed;
|
||||
}
|
||||
}
|
||||
|
||||
void NewMenu::finish(studio::StudioContext &sctx) noexcept {
|
||||
void NewMenu::drawLastPageButtons(StudioContext &sctx) noexcept {
|
||||
ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 198);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + ImGui::GetContentRegionAvail().y - 20);
|
||||
constexpr ImVec2 btnSz{60, 20};
|
||||
if (ImGui::Button("Back", btnSz)) {
|
||||
m_stage = Stage::NewItemType;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Finish", btnSz)) {
|
||||
finish(sctx);
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Quit", btnSz)) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
m_stage = Stage::Closed;
|
||||
}
|
||||
}
|
||||
|
||||
void NewMenu::finish(StudioContext &sctx) noexcept {
|
||||
if (m_itemName.len() == 0) {
|
||||
oxLogError(ox::Error(1, "New file error: no file name"));
|
||||
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"));
|
||||
auto const&im = *m_types[static_cast<std::size_t>(m_selectedType)];
|
||||
if (sctx.project->exists(im.itemPath(m_itemName))) {
|
||||
oxLogError(ox::Error{1, "New file error: file already exists"});
|
||||
return;
|
||||
}
|
||||
auto const [path, err] = typeMaker.write(sctx, m_itemName);
|
||||
auto const [path, err] =
|
||||
im.write(sctx, m_itemName, m_selectedTemplate);
|
||||
if (err) {
|
||||
oxLogError(err);
|
||||
return;
|
||||
|
@ -13,13 +13,14 @@
|
||||
|
||||
namespace studio {
|
||||
|
||||
class NewMenu: public studio::Popup {
|
||||
class NewMenu final: public Popup {
|
||||
public:
|
||||
enum class Stage {
|
||||
Closed,
|
||||
Opening,
|
||||
NewItemType,
|
||||
NewItemName,
|
||||
NewItemTemplate,
|
||||
};
|
||||
|
||||
// emits path parameter
|
||||
@ -29,8 +30,9 @@ class NewMenu: public studio::Popup {
|
||||
Stage m_stage = Stage::Closed;
|
||||
ox::String m_typeName;
|
||||
ox::IString<255> m_itemName;
|
||||
ox::Vector<ox::UniquePtr<studio::ItemMaker>> m_types;
|
||||
int m_selectedType = 0;
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> m_types;
|
||||
size_t m_selectedType = 0;
|
||||
size_t m_selectedTemplate = 0;
|
||||
bool m_open = false;
|
||||
|
||||
public:
|
||||
@ -43,37 +45,70 @@ class NewMenu: public studio::Popup {
|
||||
[[nodiscard]]
|
||||
bool isOpen() const noexcept override;
|
||||
|
||||
void draw(studio::StudioContext &sctx) noexcept override;
|
||||
void draw(StudioContext &sctx) noexcept override;
|
||||
|
||||
template<typename T>
|
||||
void addItemType(ox::String name, ox::String parentDir, ox::String fileExt, T itemTempl, ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
||||
void addItemType(
|
||||
ox::StringParam displayName,
|
||||
ox::StringParam parentDir,
|
||||
ox::StringParam fileExt,
|
||||
T itemTempl,
|
||||
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
||||
|
||||
template<typename T>
|
||||
void addItemType(ox::String name, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
||||
void addItemType(
|
||||
ox::StringParam displayName,
|
||||
ox::StringParam parentDir,
|
||||
ox::StringParam fileExt,
|
||||
ox::ClawFormat pFmt = ox::ClawFormat::Metal) noexcept;
|
||||
|
||||
void addItemMaker(ox::UniquePtr<studio::ItemMaker> &&im) noexcept;
|
||||
void addItemMaker(ox::UPtr<ItemMaker> &&im) noexcept;
|
||||
|
||||
void installItemTemplate(ox::UPtr<ItemTemplate> &tmplt) noexcept;
|
||||
|
||||
private:
|
||||
void drawNewItemType(studio::StudioContext &sctx) noexcept;
|
||||
void drawNewItemType(StudioContext const&sctx) noexcept;
|
||||
|
||||
void drawNewItemName(studio::StudioContext &sctx) noexcept;
|
||||
void drawNewItemName(StudioContext &sctx) noexcept;
|
||||
|
||||
void drawFirstPageButtons() noexcept;
|
||||
void drawNewItemTemplate(StudioContext &sctx) noexcept;
|
||||
|
||||
void drawLastPageButtons(studio::StudioContext &sctx) noexcept;
|
||||
void drawButtons(Stage prev, Stage next) noexcept;
|
||||
|
||||
void finish(studio::StudioContext &sctx) noexcept;
|
||||
void drawFirstPageButtons(Stage next) noexcept;
|
||||
|
||||
void drawLastPageButtons(StudioContext &sctx) noexcept;
|
||||
|
||||
void finish(StudioContext &sctx) noexcept;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, T itemTempl, ox::ClawFormat pFmt) noexcept {
|
||||
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), std::move(itemTempl), pFmt));
|
||||
void NewMenu::addItemType(
|
||||
ox::StringParam displayName,
|
||||
ox::StringParam parentDir,
|
||||
ox::StringParam fileExt,
|
||||
T itemTempl,
|
||||
ox::ClawFormat const pFmt) noexcept {
|
||||
m_types.emplace_back(ox::make<ItemMakerT<T>>(
|
||||
std::move(displayName),
|
||||
std::move(parentDir),
|
||||
std::move(fileExt),
|
||||
std::move(itemTempl),
|
||||
pFmt));
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void NewMenu::addItemType(ox::String displayName, ox::String parentDir, ox::String fileExt, ox::ClawFormat pFmt) noexcept {
|
||||
m_types.emplace_back(ox::make<studio::ItemMakerT<T>>(std::move(displayName), std::move(parentDir), std::move(fileExt), pFmt));
|
||||
void NewMenu::addItemType(
|
||||
ox::StringParam displayName,
|
||||
ox::StringParam parentDir,
|
||||
ox::StringParam fileExt,
|
||||
ox::ClawFormat const pFmt) noexcept {
|
||||
m_types.emplace_back(ox::make<ItemMakerT<T>>(
|
||||
std::move(displayName),
|
||||
std::move(parentDir),
|
||||
std::move(fileExt),
|
||||
pFmt));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ void NewProject::draw(studio::StudioContext &ctx) noexcept {
|
||||
}
|
||||
|
||||
void NewProject::drawNewProjectName(studio::StudioContext &sctx) noexcept {
|
||||
drawWindow(sctx.tctx, &m_open, [this, &sctx] {
|
||||
drawWindow(sctx.tctx, m_open, [this, &sctx] {
|
||||
ig::InputText("Name", m_projectName);
|
||||
ImGui::Text("Path: %s", m_projectPath.c_str());
|
||||
if (ImGui::Button("Browse")) {
|
||||
|
@ -251,6 +251,10 @@ void StudioUI::loadModule(Module const&mod) noexcept {
|
||||
for (auto &im : mod.itemMakers(m_sctx)) {
|
||||
m_newMenu.addItemMaker(std::move(im));
|
||||
}
|
||||
auto tmplts = mod.itemTemplates(m_sctx);
|
||||
for (auto &t : tmplts) {
|
||||
m_newMenu.installItemTemplate(t);
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::loadModules() noexcept {
|
||||
|
Reference in New Issue
Block a user