[keel,studio] Add ability to rename files
This commit is contained in:
@ -9,6 +9,7 @@ add_library(
|
||||
newmenu.cpp
|
||||
newproject.cpp
|
||||
projectexplorer.cpp
|
||||
renamefile.cpp
|
||||
studioapp.cpp
|
||||
)
|
||||
target_compile_definitions(
|
||||
|
@ -31,6 +31,9 @@ void ProjectExplorer::fileContextMenu(ox::StringViewCR path) const noexcept {
|
||||
if (ImGui::MenuItem("Delete")) {
|
||||
deleteItem.emit(path);
|
||||
}
|
||||
if (ImGui::MenuItem("Rename")) {
|
||||
renameItem.emit(path);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ class ProjectExplorer final: public FileExplorer {
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> addItem;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> addDir;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> deleteItem;
|
||||
ox::Signal<ox::Error(ox::StringViewCR)> renameItem;
|
||||
|
||||
explicit ProjectExplorer(keel::Context &kctx) noexcept;
|
||||
|
||||
|
63
src/olympic/studio/applib/src/renamefile.cpp
Normal file
63
src/olympic/studio/applib/src/renamefile.cpp
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#include <studio/imguiutil.hpp>
|
||||
|
||||
#include "renamefile.hpp"
|
||||
|
||||
namespace studio {
|
||||
|
||||
RenameFile::RenameFile() {
|
||||
setTitle("Rename File");
|
||||
}
|
||||
|
||||
ox::Error RenameFile::openPath(ox::StringParam path) noexcept {
|
||||
m_oldPath = std::move(path);
|
||||
OX_REQUIRE(idx, ox::findIdx(m_oldPath.rbegin(), m_oldPath.rend(), '/'));
|
||||
m_name = substr(m_oldPath, idx + 1);
|
||||
m_path = substr(m_oldPath, 0, idx + 1);
|
||||
open();
|
||||
return {};
|
||||
}
|
||||
|
||||
void RenameFile::open() noexcept {
|
||||
m_stage = Stage::Opening;
|
||||
}
|
||||
|
||||
void RenameFile::close() noexcept {
|
||||
m_stage = Stage::Closed;
|
||||
m_open = false;
|
||||
}
|
||||
|
||||
bool RenameFile::isOpen() const noexcept {
|
||||
return m_open;
|
||||
}
|
||||
|
||||
void RenameFile::draw(StudioContext &ctx) noexcept {
|
||||
switch (m_stage) {
|
||||
case Stage::Closed:
|
||||
break;
|
||||
case Stage::Opening:
|
||||
ImGui::OpenPopup(title().c_str());
|
||||
m_open = true;
|
||||
m_stage = Stage::Open;
|
||||
[[fallthrough]];
|
||||
case Stage::Open:
|
||||
setSize({250, 0});
|
||||
drawWindow(ctx.tctx, m_open, [this] {
|
||||
if (ImGui::IsWindowAppearing()) {
|
||||
ImGui::SetKeyboardFocusHere();
|
||||
}
|
||||
ig::InputText("Name", m_name);
|
||||
ImGui::Text("%s%s", m_path.c_str(), m_name.c_str());
|
||||
if (ig::PopupControlsOkCancel(m_open) == ig::PopupResponse::OK) {
|
||||
moveFile.emit(m_oldPath, m_path + m_name);
|
||||
close();
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
44
src/olympic/studio/applib/src/renamefile.hpp
Normal file
44
src/olympic/studio/applib/src/renamefile.hpp
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <studio/context.hpp>
|
||||
#include <studio/popup.hpp>
|
||||
|
||||
namespace studio {
|
||||
|
||||
class RenameFile: public Popup {
|
||||
|
||||
private:
|
||||
enum class Stage {
|
||||
Closed,
|
||||
Opening,
|
||||
Open,
|
||||
};
|
||||
Stage m_stage{};
|
||||
ox::String m_oldPath;
|
||||
ox::String m_path;
|
||||
ox::IString<255> m_name;
|
||||
bool m_open{};
|
||||
|
||||
public:
|
||||
ox::Signal<ox::Error(ox::StringViewCR src, ox::StringViewCR dst)> moveFile;
|
||||
|
||||
RenameFile();
|
||||
|
||||
ox::Error openPath(ox::StringParam path) noexcept;
|
||||
|
||||
void open() noexcept override;
|
||||
|
||||
void close() noexcept override;
|
||||
|
||||
[[nodiscard]]
|
||||
bool isOpen() const noexcept override;
|
||||
|
||||
void draw(StudioContext &ctx) noexcept override;
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -47,20 +47,20 @@ OX_MODEL_BEGIN(StudioConfig)
|
||||
OX_MODEL_END()
|
||||
|
||||
StudioUI::StudioUI(turbine::Context &ctx, ox::StringParam projectDataDir) noexcept:
|
||||
m_sctx(*this, ctx),
|
||||
m_tctx(ctx),
|
||||
m_projectDataDir(std::move(projectDataDir)),
|
||||
m_projectExplorer(keelCtx(m_tctx)),
|
||||
m_newProject(m_projectDataDir),
|
||||
m_aboutPopup(m_tctx) {
|
||||
m_sctx{*this, ctx},
|
||||
m_tctx{ctx},
|
||||
m_projectDataDir{std::move(projectDataDir)},
|
||||
m_projectExplorer{keelCtx(m_tctx)},
|
||||
m_newProject{m_projectDataDir},
|
||||
m_aboutPopup{m_tctx} {
|
||||
turbine::setApplicationData(m_tctx, &m_sctx);
|
||||
m_projectExplorer.fileChosen.connect(this, &StudioUI::openFile);
|
||||
m_projectExplorer.addDir.connect(this, &StudioUI::addDir);
|
||||
m_projectExplorer.addItem.connect(this, &StudioUI::addFile);
|
||||
m_projectExplorer.deleteItem.connect(this, &StudioUI::deleteFile);
|
||||
m_projectExplorer.renameItem.connect(this, &StudioUI::renameFile);
|
||||
m_newProject.finished.connect(this, &StudioUI::createOpenProject);
|
||||
m_newMenu.finished.connect(this, &StudioUI::openFile);
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
loadModules();
|
||||
// open project and files
|
||||
auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_tctx));
|
||||
@ -369,6 +369,14 @@ ox::Error StudioUI::deleteFile(ox::StringViewCR path) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error StudioUI::renameFile(ox::StringViewCR path) noexcept {
|
||||
return m_renameFile.openPath(path);
|
||||
}
|
||||
|
||||
ox::Error StudioUI::handleMoveFile(ox::StringViewCR, ox::UUID const&) noexcept {
|
||||
return m_projectExplorer.refreshProjectTreeModel();
|
||||
}
|
||||
|
||||
ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(toStdStringView(path), ec);
|
||||
@ -386,10 +394,12 @@ 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);
|
||||
m_project->fileDeleted.connect(&m_projectExplorer, &ProjectExplorer::refreshProjectTreeModel);
|
||||
m_project->fileMoved.connect(this, &StudioUI::handleMoveFile);
|
||||
m_openFiles.clear();
|
||||
m_editors.clear();
|
||||
studio::editConfig<StudioConfig>(keelCtx(m_tctx), [&](StudioConfig &config) {
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "newmenu.hpp"
|
||||
#include "newproject.hpp"
|
||||
#include "projectexplorer.hpp"
|
||||
#include "renamefile.hpp"
|
||||
|
||||
namespace studio {
|
||||
|
||||
@ -42,14 +43,16 @@ class StudioUI: public ox::SignalHandler {
|
||||
NewMenu m_newMenu{keelCtx(m_tctx)};
|
||||
DeleteConfirmation m_deleteConfirmation;
|
||||
NewDir m_newDirDialog;
|
||||
RenameFile m_renameFile;
|
||||
NewProject m_newProject;
|
||||
AboutPopup m_aboutPopup;
|
||||
ox::Array<Popup*, 5> const m_popups = {
|
||||
ox::Array<Popup*, 6> const m_popups = {
|
||||
&m_newMenu,
|
||||
&m_newProject,
|
||||
&m_aboutPopup,
|
||||
&m_deleteConfirmation,
|
||||
&m_newDirDialog,
|
||||
&m_renameFile,
|
||||
};
|
||||
bool m_showProjectExplorer = true;
|
||||
|
||||
@ -95,6 +98,10 @@ class StudioUI: public ox::SignalHandler {
|
||||
|
||||
ox::Error deleteFile(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error renameFile(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error handleMoveFile(ox::StringViewCR path, ox::UUID const&id) noexcept;
|
||||
|
||||
ox::Error createOpenProject(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error openProjectPath(ox::StringParam path) noexcept;
|
||||
|
Reference in New Issue
Block a user