[studio] Add ability to add file through dir context menu
All checks were successful
Build / build (push) Successful in 3m15s
All checks were successful
Build / build (push) Successful in 3m15s
Also, fix dir context menu to work when dir is closed, and fix it not to override last file in the directory.
This commit is contained in:
parent
6e2b4fa7b4
commit
6924147686
@ -22,6 +22,12 @@ void NewMenu::open() noexcept {
|
||||
m_selectedType = 0;
|
||||
m_itemName = "";
|
||||
m_typeName = "";
|
||||
m_path = "";
|
||||
}
|
||||
|
||||
void NewMenu::openPath(ox::StringParam path) noexcept {
|
||||
open();
|
||||
m_path = std::move(path);
|
||||
}
|
||||
|
||||
void NewMenu::close() noexcept {
|
||||
@ -158,14 +164,14 @@ void NewMenu::finish(StudioContext &sctx) noexcept {
|
||||
oxLogError(ox::Error{1, "New file error: no file name"});
|
||||
return;
|
||||
}
|
||||
auto const&im = *m_types[static_cast<std::size_t>(m_selectedType)];
|
||||
if (sctx.project->exists(im.itemPath(m_itemName))) {
|
||||
auto const&im = *m_types[m_selectedType];
|
||||
auto const path = m_path.len() ?
|
||||
im.itemPath(m_itemName, m_path) : im.itemPath(m_itemName);
|
||||
if (sctx.project->exists(path)) {
|
||||
oxLogError(ox::Error{1, "New file error: file already exists"});
|
||||
return;
|
||||
}
|
||||
auto const [path, err] =
|
||||
im.write(sctx, m_itemName, m_selectedTemplate);
|
||||
if (err) {
|
||||
if (auto const err = im.write(sctx, path, m_selectedTemplate)) {
|
||||
oxLogError(err);
|
||||
return;
|
||||
}
|
||||
|
@ -30,6 +30,7 @@ class NewMenu final: public Popup {
|
||||
Stage m_stage = Stage::Closed;
|
||||
ox::String m_typeName;
|
||||
ox::IString<255> m_itemName;
|
||||
ox::String m_path;
|
||||
ox::Vector<ox::UPtr<studio::ItemMaker>> m_types;
|
||||
size_t m_selectedType = 0;
|
||||
size_t m_selectedTemplate = 0;
|
||||
@ -38,6 +39,8 @@ class NewMenu final: public Popup {
|
||||
public:
|
||||
NewMenu() noexcept;
|
||||
|
||||
void openPath(ox::StringParam path) noexcept;
|
||||
|
||||
void open() noexcept override;
|
||||
|
||||
void close() noexcept override;
|
||||
|
@ -19,7 +19,8 @@ class ProjectExplorer: public Widget {
|
||||
|
||||
public:
|
||||
// slots
|
||||
ox::Signal<ox::Error(ox::StringView const&)> fileChosen;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> fileChosen;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> addItem;
|
||||
|
||||
explicit ProjectExplorer(turbine::Context &ctx) noexcept;
|
||||
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <studio/imguiutil.hpp>
|
||||
|
||||
#include "projectexplorer.hpp"
|
||||
#include "projecttreemodel.hpp"
|
||||
|
||||
@ -30,10 +32,14 @@ bool ProjectTreeModel::draw(turbine::Context &ctx) const noexcept {
|
||||
constexpr auto dirFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick;
|
||||
if (!m_children.empty()) {
|
||||
if (ImGui::TreeNodeEx(m_name.c_str(), dirFlags)) {
|
||||
drawDirContextMenu();
|
||||
for (auto const&child : m_children) {
|
||||
updated = child->draw(ctx) || updated;
|
||||
}
|
||||
ImGui::TreePop();
|
||||
} else {
|
||||
ig::IDStackItem const idStackItem{m_name};
|
||||
drawDirContextMenu();
|
||||
}
|
||||
} else {
|
||||
auto const path = fullPath();
|
||||
@ -58,6 +64,15 @@ void ProjectTreeModel::setChildren(ox::Vector<ox::UPtr<ProjectTreeModel>> childr
|
||||
m_children = std::move(children);
|
||||
}
|
||||
|
||||
void ProjectTreeModel::drawDirContextMenu() const noexcept {
|
||||
if (ImGui::BeginPopupContextItem("DirMenu", ImGuiPopupFlags_MouseButtonRight)) {
|
||||
if (ImGui::MenuItem("Add Item")) {
|
||||
m_explorer.addItem.emit(fullPath());
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
||||
ox::BasicString<255> ProjectTreeModel::fullPath() const noexcept {
|
||||
if (m_parent) {
|
||||
return m_parent->fullPath() + "/" + ox::StringView(m_name);
|
||||
|
@ -31,6 +31,8 @@ class ProjectTreeModel {
|
||||
void setChildren(ox::Vector<ox::UPtr<ProjectTreeModel>> children) noexcept;
|
||||
|
||||
private:
|
||||
void drawDirContextMenu() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::BasicString<255> fullPath() const noexcept;
|
||||
|
||||
|
@ -52,6 +52,7 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce
|
||||
m_aboutPopup(m_tctx) {
|
||||
turbine::setApplicationData(m_tctx, &m_sctx);
|
||||
m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile);
|
||||
m_projectExplorer.addItem.connect(this, &StudioUI::addFile);
|
||||
m_newProject.finished.connect(this, &StudioUI::createOpenProject);
|
||||
m_newMenu.finished.connect(this, &StudioUI::openFile);
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
@ -342,6 +343,11 @@ void StudioUI::handleKeyInput() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
ox::Error StudioUI::addFile(ox::StringViewCR path) noexcept {
|
||||
m_newMenu.openPath(path);
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(toStdStringView(path), ec);
|
||||
|
@ -83,6 +83,8 @@ class StudioUI: public ox::SignalHandler {
|
||||
|
||||
void handleKeyInput() noexcept;
|
||||
|
||||
ox::Error addFile(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error createOpenProject(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error openProjectPath(ox::StringParam path) noexcept;
|
||||
|
@ -128,6 +128,16 @@ class ItemMaker {
|
||||
return m_templates;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String const&defaultPath() const noexcept {
|
||||
return m_parentDir;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String itemPath(ox::StringViewCR pName, ox::StringViewCR pPath) const noexcept {
|
||||
return ox::sfmt("/{}/{}.{}", pPath, pName, m_fileExt);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String itemPath(ox::StringViewCR pName) const noexcept {
|
||||
return ox::sfmt("/{}/{}.{}", m_parentDir, pName, m_fileExt);
|
||||
@ -142,12 +152,40 @@ class ItemMaker {
|
||||
/**
|
||||
* Returns path of the file created.
|
||||
* @param ctx
|
||||
* @param pPath
|
||||
* @param pTemplateIdx
|
||||
* @return path of file or error in Result
|
||||
*/
|
||||
ox::Error write(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
size_t pTemplateIdx) const noexcept {
|
||||
return writeItem(ctx, pPath, pTemplateIdx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns path of the file created.
|
||||
* @param ctx
|
||||
* @param pPath
|
||||
* @param pName
|
||||
* @param pTemplateIdx
|
||||
* @return path of file or error in Result
|
||||
*/
|
||||
virtual ox::Result<ox::String> write(
|
||||
StudioContext &ctx, ox::StringViewCR pName, size_t pTemplateIdx) const noexcept = 0;
|
||||
ox::Error write(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
ox::StringViewCR pName,
|
||||
size_t pTemplateIdx) const noexcept {
|
||||
auto const path = itemPath(pName, pPath);
|
||||
return writeItem(ctx, path, pTemplateIdx);
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual ox::Error writeItem(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
size_t pTemplateIdx) const noexcept = 0;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
@ -205,20 +243,19 @@ class ItemMakerT final: public ItemMaker {
|
||||
return ox::ModelTypeVersion_v<T>;
|
||||
}
|
||||
|
||||
ox::Result<ox::String> write(
|
||||
StudioContext &sctx,
|
||||
ox::StringViewCR pName,
|
||||
ox::Error writeItem(
|
||||
StudioContext &ctx,
|
||||
ox::StringViewCR pPath,
|
||||
size_t const pTemplateIdx) const noexcept override {
|
||||
auto const path = itemPath(pName);
|
||||
createUuidMapping(keelCtx(sctx.tctx), path, ox::UUID::generate().unwrap());
|
||||
createUuidMapping(keelCtx(ctx.tctx), pPath, ox::UUID::generate().unwrap());
|
||||
auto const&templates = itemTemplates();
|
||||
auto const tmplIdx = pTemplateIdx < templates.size() ? pTemplateIdx : 0;
|
||||
OX_REQUIRE_M(tmpl, templates[tmplIdx]->getItem(
|
||||
keelCtx(sctx), typeName(), typeVersion()));
|
||||
keelCtx(ctx), typeName(), typeVersion()));
|
||||
auto item = tmpl.template get<T>();
|
||||
OX_RETURN_ERROR(sctx.project->writeObj(path, *item, m_fmt));
|
||||
OX_RETURN_ERROR(ctx.project->writeObj(pPath, *item, m_fmt));
|
||||
tmpl.free();
|
||||
return path;
|
||||
return {};
|
||||
}
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user