diff --git a/src/olympic/studio/applib/src/projectexplorer.cpp b/src/olympic/studio/applib/src/projectexplorer.cpp index fd1fdcc6..942548c5 100644 --- a/src/olympic/studio/applib/src/projectexplorer.cpp +++ b/src/olympic/studio/applib/src/projectexplorer.cpp @@ -26,6 +26,10 @@ void ProjectExplorer::fileDeleted(ox::StringViewCR path) const noexcept { deleteItem.emit(path); } +void ProjectExplorer::fileMoved(ox::StringViewCR src, ox::StringViewCR dst) const noexcept { + moveItem.emit(src, dst); +} + void ProjectExplorer::fileContextMenu(ox::StringViewCR path) const noexcept { if (ImGui::BeginPopupContextItem("FileMenu", ImGuiPopupFlags_MouseButtonRight)) { if (ImGui::MenuItem("Delete")) { diff --git a/src/olympic/studio/applib/src/projectexplorer.hpp b/src/olympic/studio/applib/src/projectexplorer.hpp index 8abe6e2d..e35d7e05 100644 --- a/src/olympic/studio/applib/src/projectexplorer.hpp +++ b/src/olympic/studio/applib/src/projectexplorer.hpp @@ -20,6 +20,7 @@ class ProjectExplorer final: public FileExplorer { ox::Signal addDir; ox::Signal deleteItem; ox::Signal renameItem; + ox::Signal moveItem; explicit ProjectExplorer(keel::Context &kctx) noexcept; @@ -30,6 +31,8 @@ class ProjectExplorer final: public FileExplorer { void fileDeleted(ox::StringViewCR path) const noexcept override; + void fileMoved(ox::StringViewCR src, ox::StringViewCR dst) const noexcept override; + void fileContextMenu(ox::StringViewCR path) const noexcept override; void dirContextMenu(ox::StringViewCR path) const noexcept override; diff --git a/src/olympic/studio/applib/src/studioapp.cpp b/src/olympic/studio/applib/src/studioapp.cpp index 827979d5..54ecc628 100644 --- a/src/olympic/studio/applib/src/studioapp.cpp +++ b/src/olympic/studio/applib/src/studioapp.cpp @@ -59,6 +59,8 @@ StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexce m_projectExplorer.addItem.connect(this, &StudioUI::addFile); m_projectExplorer.deleteItem.connect(this, &StudioUI::deleteFile); m_projectExplorer.renameItem.connect(this, &StudioUI::renameFile); + m_projectExplorer.moveItem.connect(this, &StudioUI::queueFileMove); + m_renameFile.moveFile.connect(this, &StudioUI::queueFileMove); m_newProject.finished.connect(this, &StudioUI::createOpenProject); m_newMenu.finished.connect(this, &StudioUI::openFile); loadModules(); @@ -135,6 +137,7 @@ void StudioUI::draw() noexcept { ImGui::End(); handleKeyInput(); m_taskRunner.update(m_tctx); + procFileMoves(); } void StudioUI::drawMenu() noexcept { @@ -409,7 +412,6 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept { m_sctx.project = m_project.get(); turbine::setWindowTitle(m_tctx, ox::sfmt("{} - {}", keelCtx(m_tctx).appName, m_project->projectPath())); m_deleteConfirmation.deleteFile.connect(m_sctx.project, &Project::deleteItem); - m_renameFile.moveFile.connect(m_project.get(), &Project::moveItem); m_newDirDialog.newDir.connect(m_sctx.project, &Project::mkdir); m_project->dirAdded.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel); m_project->fileAdded.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel); @@ -484,4 +486,16 @@ ox::Error StudioUI::closeFile(ox::StringViewCR path) noexcept { return {}; } +ox::Error StudioUI::queueFileMove(ox::StringParam src, ox::StringParam dst) noexcept { + m_queuedMoves.emplace_back(std::move(src), std::move(dst)); + return {}; +} + +void StudioUI::procFileMoves() noexcept { + for (auto const &m : m_queuedMoves) { + oxLogError(m_project->moveItem(m.a, m.b)); + } + m_queuedMoves.clear(); +} + } diff --git a/src/olympic/studio/applib/src/studioapp.hpp b/src/olympic/studio/applib/src/studioapp.hpp index 06fef01e..7e0a960d 100644 --- a/src/olympic/studio/applib/src/studioapp.hpp +++ b/src/olympic/studio/applib/src/studioapp.hpp @@ -40,6 +40,7 @@ class StudioUI: public ox::SignalHandler { BaseEditor *m_activeEditorOnLastDraw = nullptr; BaseEditor *m_activeEditor = nullptr; BaseEditor *m_activeEditorUpdatePending = nullptr; + ox::Vector> m_queuedMoves; NewMenu m_newMenu{keelCtx(m_tctx)}; DeleteConfirmation m_deleteConfirmation; NewDir m_newDirDialog; @@ -111,6 +112,11 @@ class StudioUI: public ox::SignalHandler { ox::Error openFileActiveTab(ox::StringViewCR path, bool makeActiveTab) noexcept; ox::Error closeFile(ox::StringViewCR path) noexcept; + + ox::Error queueFileMove(ox::StringParam src, ox::StringParam dst) noexcept; + + void procFileMoves() noexcept; + }; } diff --git a/src/olympic/studio/modlib/include/studio/filetreemodel.hpp b/src/olympic/studio/modlib/include/studio/filetreemodel.hpp index ea92ad74..673f7b94 100644 --- a/src/olympic/studio/modlib/include/studio/filetreemodel.hpp +++ b/src/olympic/studio/modlib/include/studio/filetreemodel.hpp @@ -45,6 +45,8 @@ class FileExplorer: public ox::SignalHandler { virtual void fileDeleted(ox::StringViewCR path) const noexcept; + virtual void fileMoved(ox::StringViewCR src, ox::StringViewCR dst) const noexcept; + void drawFileContextMenu(ox::CStringViewCR path) const noexcept; void drawDirContextMenu(ox::CStringViewCR path) const noexcept; diff --git a/src/olympic/studio/modlib/src/filetreemodel.cpp b/src/olympic/studio/modlib/src/filetreemodel.cpp index 3b483a1c..f0ac65e3 100644 --- a/src/olympic/studio/modlib/src/filetreemodel.cpp +++ b/src/olympic/studio/modlib/src/filetreemodel.cpp @@ -41,6 +41,8 @@ void FileExplorer::fileOpened(ox::StringViewCR) const noexcept {} void FileExplorer::fileDeleted(ox::StringViewCR) const noexcept {} +void FileExplorer::fileMoved(ox::StringViewCR, ox::StringViewCR) const noexcept {} + void FileExplorer::drawFileContextMenu(ox::CStringViewCR path) const noexcept { ig::IDStackItem const idStackItem{path}; fileContextMenu(path); @@ -91,6 +93,13 @@ void FileTreeModel::draw(turbine::Context &tctx) const noexcept { } ig::IDStackItem const idStackItem{m_name}; m_explorer.drawDirContextMenu(m_fullPath); + if (ig::DragDropTarget const dragDropTarget; dragDropTarget) { + auto const [ref, err] = ig::getDragDropPayload("FileRef"); + if (!err) { + auto const name = substr(ref.path, find(ref.path.rbegin(), ref.path.rend(), '/').offset() + 1); + m_explorer.fileMoved(ref.path, sfmt("{}/{}", m_fullPath, name)); + } + } if (nodeOpen) { for (auto const&child : m_children) { child->draw(tctx);