Squashed 'deps/nostalgia/' changes from 7e3e0461..be518387
be518387 [nostalgia/gfx/studio/tilesheet] Add flip x and flip y functionality 1207dade [studio] Add ability to move directories 109e1898 [studio] Add ability to drag files between directories a24bf7ff [studio] Fix config to update when open file name changes 046834c2 [studio,nostalgia] Update tab name when corresponding file's name changes f840240a [nostalgia/gfx/studio/tilesheeteditor] Rework system for tracking current palette path cfa91d3d [keel,studio] Add ability to rename files f7a7a66a [ox/event] Add Signal::connectionCnt 5145595d [ox/std] Fix HashMap collision handling f01d3033 [ox/std] Fix UPtr compare with nullptr 098c8cb8 [nostalgia/gfx/studio] Make move color commands affect all pages 04ad0f02 [studio] Add drag/drop functions that use model TypeName for name 695e7a45 [nostalgia/gfx/studio/paletteeditor] Change move color mechanism to use drag/drop 7d53028f [studio] Cleanup git-subtree-dir: deps/nostalgia git-subtree-split: be51838775cd37d8c0778378a5d944f8f261830c
This commit is contained in:
@@ -9,6 +9,7 @@ add_library(
|
||||
newmenu.cpp
|
||||
newproject.cpp
|
||||
projectexplorer.cpp
|
||||
renamefile.cpp
|
||||
studioapp.cpp
|
||||
)
|
||||
target_compile_definitions(
|
||||
|
@@ -9,7 +9,7 @@
|
||||
namespace studio {
|
||||
|
||||
ClawEditor::ClawEditor(StudioContext &sctx, ox::StringParam path):
|
||||
Editor(std::move(path)),
|
||||
Editor(sctx, std::move(path)),
|
||||
m_obj(sctx.project->loadObj<ox::ModelObject>(itemPath()).unwrapThrow()) {
|
||||
}
|
||||
|
||||
|
@@ -26,11 +26,22 @@ 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::dirMoved(ox::StringViewCR src, ox::StringViewCR dst) const noexcept {
|
||||
moveDir.emit(src, dst);
|
||||
}
|
||||
|
||||
void ProjectExplorer::fileContextMenu(ox::StringViewCR path) const noexcept {
|
||||
if (ImGui::BeginPopupContextItem("FileMenu", ImGuiPopupFlags_MouseButtonRight)) {
|
||||
if (ImGui::MenuItem("Delete")) {
|
||||
deleteItem.emit(path);
|
||||
}
|
||||
if (ImGui::MenuItem("Rename")) {
|
||||
renameItem.emit(path);
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <ox/event/signal.hpp>
|
||||
#include <ox/std/memory.hpp>
|
||||
|
||||
#include <studio/filetreemodel.hpp>
|
||||
#include <studio/widget.hpp>
|
||||
@@ -20,6 +19,9 @@ 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;
|
||||
ox::Signal<ox::Error(ox::StringViewCR src, ox::StringViewCR dst)> moveDir;
|
||||
ox::Signal<ox::Error(ox::StringViewCR src, ox::StringViewCR dst)> moveItem;
|
||||
|
||||
explicit ProjectExplorer(keel::Context &kctx) noexcept;
|
||||
|
||||
@@ -30,6 +32,10 @@ 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 dirMoved(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;
|
||||
|
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,23 @@ 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_projectExplorer.moveDir.connect(this, &StudioUI::queueDirMove);
|
||||
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);
|
||||
ImGui::GetIO().IniFilename = nullptr;
|
||||
loadModules();
|
||||
// open project and files
|
||||
auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_tctx));
|
||||
@@ -135,6 +138,7 @@ void StudioUI::draw() noexcept {
|
||||
ImGui::End();
|
||||
handleKeyInput();
|
||||
m_taskRunner.update(m_tctx);
|
||||
procFileMoves();
|
||||
}
|
||||
|
||||
void StudioUI::drawMenu() noexcept {
|
||||
@@ -369,6 +373,29 @@ 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 oldPath, ox::StringViewCR newPath, ox::UUID const&) noexcept {
|
||||
for (auto &f : m_openFiles) {
|
||||
if (f == oldPath) {
|
||||
f = newPath;
|
||||
editConfig<StudioConfig>(keelCtx(m_sctx), [&](StudioConfig &cfg) {
|
||||
auto p = find(cfg.openFiles.begin(), cfg.openFiles.end(), oldPath);
|
||||
*p = newPath;
|
||||
cfg.activeTabItemName = newPath;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
// needed to keep this tab open, ImGui loses track when the name changes
|
||||
if (m_activeEditor) {
|
||||
m_activeEditorUpdatePending = m_activeEditor;
|
||||
}
|
||||
return m_projectExplorer.refreshProjectTreeModel();
|
||||
}
|
||||
|
||||
ox::Error StudioUI::createOpenProject(ox::StringViewCR path) noexcept {
|
||||
std::error_code ec;
|
||||
std::filesystem::create_directories(toStdStringView(path), ec);
|
||||
@@ -390,6 +417,7 @@ ox::Error StudioUI::openProjectPath(ox::StringParam path) noexcept {
|
||||
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) {
|
||||
@@ -459,4 +487,25 @@ ox::Error StudioUI::closeFile(ox::StringViewCR path) noexcept {
|
||||
return {};
|
||||
}
|
||||
|
||||
ox::Error StudioUI::queueDirMove(ox::StringParam src, ox::StringParam dst) noexcept {
|
||||
m_queuedDirMoves.emplace_back(std::move(src), std::move(dst));
|
||||
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();
|
||||
for (auto const &m : m_queuedDirMoves) {
|
||||
oxLogError(m_project->moveDir(m.a, m.b));
|
||||
}
|
||||
m_queuedDirMoves.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,6 +19,7 @@
|
||||
#include "newmenu.hpp"
|
||||
#include "newproject.hpp"
|
||||
#include "projectexplorer.hpp"
|
||||
#include "renamefile.hpp"
|
||||
|
||||
namespace studio {
|
||||
|
||||
@@ -39,17 +40,21 @@ class StudioUI: public ox::SignalHandler {
|
||||
BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
||||
BaseEditor *m_activeEditor = nullptr;
|
||||
BaseEditor *m_activeEditorUpdatePending = nullptr;
|
||||
ox::Vector<ox::Pair<ox::String>> m_queuedMoves;
|
||||
ox::Vector<ox::Pair<ox::String>> m_queuedDirMoves;
|
||||
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 +100,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 oldPath, ox::StringViewCR newPath, ox::UUID const&id) noexcept;
|
||||
|
||||
ox::Error createOpenProject(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error openProjectPath(ox::StringParam path) noexcept;
|
||||
@@ -104,6 +113,13 @@ class StudioUI: public ox::SignalHandler {
|
||||
ox::Error openFileActiveTab(ox::StringViewCR path, bool makeActiveTab) noexcept;
|
||||
|
||||
ox::Error closeFile(ox::StringViewCR path) noexcept;
|
||||
|
||||
ox::Error queueDirMove(ox::StringParam src, ox::StringParam dst) noexcept;
|
||||
|
||||
ox::Error queueFileMove(ox::StringParam src, ox::StringParam dst) noexcept;
|
||||
|
||||
void procFileMoves() noexcept;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user