[olympic/studio] Fix several crashes
This commit is contained in:
parent
2167a46266
commit
db961739ad
@ -53,7 +53,7 @@ static ox::Error runApp(
|
|||||||
turbine::setConstantRefresh(*ctx, false);
|
turbine::setConstantRefresh(*ctx, false);
|
||||||
studio::StudioContext studioCtx;
|
studio::StudioContext studioCtx;
|
||||||
turbine::setApplicationData(*ctx, &studioCtx);
|
turbine::setApplicationData(*ctx, &studioCtx);
|
||||||
StudioUI ui(ctx.get(), projectDataDir);
|
StudioUI ui(*ctx, projectDataDir);
|
||||||
studioCtx.ui = &ui;
|
studioCtx.ui = &ui;
|
||||||
StudioUIDrawer drawer(ui);
|
StudioUIDrawer drawer(ui);
|
||||||
turbine::gl::addDrawer(*ctx, &drawer);
|
turbine::gl::addDrawer(*ctx, &drawer);
|
||||||
|
@ -15,7 +15,12 @@
|
|||||||
|
|
||||||
namespace studio {
|
namespace studio {
|
||||||
|
|
||||||
ox::Vector<const studio::Module*> modules;
|
static ox::Vector<const studio::Module*> modules;
|
||||||
|
|
||||||
|
void registerModule(studio::Module const*mod) noexcept {
|
||||||
|
modules.emplace_back(mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
struct StudioConfig {
|
struct StudioConfig {
|
||||||
static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig";
|
static constexpr auto TypeName = "net.drinkingtea.studio.StudioConfig";
|
||||||
@ -33,23 +38,25 @@ oxModelBegin(StudioConfig)
|
|||||||
oxModelFieldRename(show_project_explorer, showProjectExplorer)
|
oxModelFieldRename(show_project_explorer, showProjectExplorer)
|
||||||
oxModelEnd()
|
oxModelEnd()
|
||||||
|
|
||||||
StudioUI::StudioUI(turbine::Context *ctx, ox::StringView projectDir) noexcept:
|
StudioUI::StudioUI(turbine::Context &ctx, ox::StringView projectDataDir) noexcept:
|
||||||
m_ctx(*ctx),
|
m_ctx(ctx),
|
||||||
m_projectDir(projectDir),
|
m_projectDataDir(projectDataDir),
|
||||||
m_projectExplorer(ox::make_unique<ProjectExplorer>(m_ctx)),
|
m_projectExplorer(ox::make_unique<ProjectExplorer>(m_ctx)),
|
||||||
m_aboutPopup(*ctx) {
|
m_aboutPopup(m_ctx) {
|
||||||
m_projectExplorer->fileChosen.connect(this, &StudioUI::openFile);
|
m_projectExplorer->fileChosen.connect(this, &StudioUI::openFile);
|
||||||
ImGui::GetIO().IniFilename = nullptr;
|
ImGui::GetIO().IniFilename = nullptr;
|
||||||
loadModules();
|
loadModules();
|
||||||
// open project and files
|
// open project and files
|
||||||
const auto [config, err] = studio::readConfig<StudioConfig>(keelCtx(*ctx));
|
auto const [config, err] = studio::readConfig<StudioConfig>(keelCtx(m_ctx));
|
||||||
m_showProjectExplorer = config.showProjectExplorer;
|
m_showProjectExplorer = config.showProjectExplorer;
|
||||||
if (!err) {
|
if (!err) {
|
||||||
oxIgnoreError(openProject(config.projectPath));
|
auto const openProjErr = openProject(config.projectPath);
|
||||||
for (const auto &f : config.openFiles) {
|
if (!openProjErr) {
|
||||||
auto openFileErr = openFileActiveTab(f, config.activeTabItemName == f);
|
for (const auto &f: config.openFiles) {
|
||||||
if (openFileErr) {
|
auto openFileErr = openFileActiveTab(f, config.activeTabItemName == f);
|
||||||
oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
|
if (openFileErr) {
|
||||||
|
oxErrorf("\nCould not open editor for file:\n\t{}\nReason:\n\t{}\n", f, toStr(openFileErr));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -83,7 +90,9 @@ void StudioUI::handleKeyEvent(turbine::Key key, bool down) noexcept {
|
|||||||
toggleProjectExplorer();
|
toggleProjectExplorer();
|
||||||
break;
|
break;
|
||||||
case turbine::Key::Alpha_C:
|
case turbine::Key::Alpha_C:
|
||||||
m_activeEditor->copy();
|
if (m_activeEditor && m_activeEditor->copyEnabled()) {
|
||||||
|
m_activeEditor->copy();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case turbine::Key::Alpha_N:
|
case turbine::Key::Alpha_N:
|
||||||
m_newMenu.open();
|
m_newMenu.open();
|
||||||
@ -98,10 +107,14 @@ void StudioUI::handleKeyEvent(turbine::Key key, bool down) noexcept {
|
|||||||
save();
|
save();
|
||||||
break;
|
break;
|
||||||
case turbine::Key::Alpha_V:
|
case turbine::Key::Alpha_V:
|
||||||
m_activeEditor->paste();
|
if (m_activeEditor && m_activeEditor->pasteEnabled()) {
|
||||||
|
m_activeEditor->paste();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case turbine::Key::Alpha_X:
|
case turbine::Key::Alpha_X:
|
||||||
m_activeEditor->cut();
|
if (m_activeEditor && m_activeEditor->cutEnabled()) {
|
||||||
|
m_activeEditor->cut();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case turbine::Key::Alpha_Y:
|
case turbine::Key::Alpha_Y:
|
||||||
redo();
|
redo();
|
||||||
@ -169,19 +182,19 @@ void StudioUI::drawMenu() noexcept {
|
|||||||
if (ImGui::BeginMenu("Edit")) {
|
if (ImGui::BeginMenu("Edit")) {
|
||||||
auto undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
auto undoStack = m_activeEditor ? m_activeEditor->undoStack() : nullptr;
|
||||||
if (ImGui::MenuItem("Undo", "Ctrl+Z", false, undoStack && undoStack->canUndo())) {
|
if (ImGui::MenuItem("Undo", "Ctrl+Z", false, undoStack && undoStack->canUndo())) {
|
||||||
m_activeEditor->undoStack()->undo();
|
undoStack->undo();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Redo", "Ctrl+Y", false, undoStack && undoStack->canRedo())) {
|
if (ImGui::MenuItem("Redo", "Ctrl+Y", false, undoStack && undoStack->canRedo())) {
|
||||||
m_activeEditor->undoStack()->redo();
|
undoStack->redo();
|
||||||
}
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
if (ImGui::MenuItem("Copy", "Ctrl+C")) {
|
if (ImGui::MenuItem("Copy", "Ctrl+C", false, m_activeEditor && m_activeEditor->copyEnabled())) {
|
||||||
m_activeEditor->copy();
|
m_activeEditor->copy();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Cut", "Ctrl+X")) {
|
if (ImGui::MenuItem("Cut", "Ctrl+X", false, m_activeEditor && m_activeEditor->cutEnabled())) {
|
||||||
m_activeEditor->cut();
|
m_activeEditor->cut();
|
||||||
}
|
}
|
||||||
if (ImGui::MenuItem("Paste", "Ctrl+V")) {
|
if (ImGui::MenuItem("Paste", "Ctrl+V", false, m_activeEditor && m_activeEditor->pasteEnabled()) && m_activeEditor) {
|
||||||
m_activeEditor->paste();
|
m_activeEditor->paste();
|
||||||
}
|
}
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
@ -240,6 +253,9 @@ void StudioUI::drawTabs() noexcept {
|
|||||||
}
|
}
|
||||||
if (!open) {
|
if (!open) {
|
||||||
e->close();
|
e->close();
|
||||||
|
if (m_activeEditor == (*it).get()) {
|
||||||
|
m_activeEditor = nullptr;
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
oxThrowError(m_editors.erase(it).moveTo(&it));
|
oxThrowError(m_editors.erase(it).moveTo(&it));
|
||||||
} catch (const ox::Exception &ex) {
|
} catch (const ox::Exception &ex) {
|
||||||
@ -305,7 +321,7 @@ ox::Error StudioUI::openProject(ox::CRStringView path) noexcept {
|
|||||||
oxRequireM(fs, keel::loadRomFs(path));
|
oxRequireM(fs, keel::loadRomFs(path));
|
||||||
oxReturnError(keel::setRomFs(keelCtx(m_ctx), std::move(fs)));
|
oxReturnError(keel::setRomFs(keelCtx(m_ctx), std::move(fs)));
|
||||||
turbine::setWindowTitle(m_ctx, ox::sfmt("{} - {}", keelCtx(m_ctx).appName, path));
|
turbine::setWindowTitle(m_ctx, ox::sfmt("{} - {}", keelCtx(m_ctx).appName, path));
|
||||||
m_project = ox::make_unique<studio::Project>(keelCtx(m_ctx), ox::String(path), m_projectDir);
|
m_project = ox::make_unique<studio::Project>(keelCtx(m_ctx), ox::String(path), m_projectDataDir);
|
||||||
auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
auto sctx = applicationData<studio::StudioContext>(m_ctx);
|
||||||
sctx->project = m_project.get();
|
sctx->project = m_project.get();
|
||||||
m_project->fileAdded.connect(m_projectExplorer.get(), &ProjectExplorer::refreshProjectTreeModel);
|
m_project->fileAdded.connect(m_projectExplorer.get(), &ProjectExplorer::refreshProjectTreeModel);
|
||||||
@ -324,6 +340,9 @@ ox::Error StudioUI::openFile(ox::CRStringView path) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab) noexcept {
|
ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab) noexcept {
|
||||||
|
if (!m_project) {
|
||||||
|
return OxError(1, "No project open to open a file from");
|
||||||
|
}
|
||||||
if (m_openFiles.contains(path)) {
|
if (m_openFiles.contains(path)) {
|
||||||
for (auto &e : m_editors) {
|
for (auto &e : m_editors) {
|
||||||
if (makeActiveTab && e->itemPath() == path) {
|
if (makeActiveTab && e->itemPath() == path) {
|
||||||
@ -332,7 +351,7 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
oxRequire(ext, studio::fileExt(path).to<ox::String>([](auto const&v) {return ox::String(v);}));
|
oxRequire(ext, studio::fileExt(path).to<ox::String>([](auto const&v) {return ox::String(v);}));
|
||||||
// create Editor
|
// create Editor
|
||||||
@ -372,18 +391,14 @@ ox::Error StudioUI::openFileActiveTab(ox::CRStringView path, bool makeActiveTab)
|
|||||||
|
|
||||||
ox::Error StudioUI::closeFile(ox::CRStringView path) noexcept {
|
ox::Error StudioUI::closeFile(ox::CRStringView path) noexcept {
|
||||||
if (!m_openFiles.contains(path)) {
|
if (!m_openFiles.contains(path)) {
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
}
|
||||||
oxIgnoreError(m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path)));
|
oxIgnoreError(m_openFiles.erase(std::remove(m_openFiles.begin(), m_openFiles.end(), path)));
|
||||||
// save to config
|
// save to config
|
||||||
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
studio::editConfig<StudioConfig>(keelCtx(m_ctx), [&](StudioConfig *config) {
|
||||||
oxIgnoreError(config->openFiles.erase(std::remove(config->openFiles.begin(), config->openFiles.end(), path)));
|
oxIgnoreError(config->openFiles.erase(std::remove(config->openFiles.begin(), config->openFiles.end(), path)));
|
||||||
});
|
});
|
||||||
return OxError(0);
|
return {};
|
||||||
}
|
|
||||||
|
|
||||||
void registerModule(const studio::Module *mod) noexcept {
|
|
||||||
modules.emplace_back(mod);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,27 +24,27 @@ class StudioUI: public ox::SignalHandler {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
turbine::Context &m_ctx;
|
turbine::Context &m_ctx;
|
||||||
ox::String m_projectDir;
|
ox::String m_projectDataDir;
|
||||||
ox::UniquePtr<studio::Project> m_project;
|
ox::UPtr<studio::Project> m_project;
|
||||||
studio::TaskRunner m_taskRunner;
|
studio::TaskRunner m_taskRunner;
|
||||||
ox::Vector<ox::UniquePtr<studio::BaseEditor>> m_editors;
|
ox::Vector<ox::UPtr<studio::BaseEditor>> m_editors;
|
||||||
ox::Vector<ox::UniquePtr<studio::Widget>> m_widgets;
|
ox::Vector<ox::UPtr<studio::Widget>> m_widgets;
|
||||||
ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
|
ox::HashMap<ox::String, studio::EditorMaker::Func> m_editorMakers;
|
||||||
ox::UniquePtr<ProjectExplorer> m_projectExplorer;
|
ox::UPtr<ProjectExplorer> m_projectExplorer;
|
||||||
ox::Vector<ox::String> m_openFiles;
|
ox::Vector<ox::String> m_openFiles;
|
||||||
studio::BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
studio::BaseEditor *m_activeEditorOnLastDraw = nullptr;
|
||||||
studio::BaseEditor *m_activeEditor = nullptr;
|
studio::BaseEditor *m_activeEditor = nullptr;
|
||||||
studio::BaseEditor *m_activeEditorUpdatePending = nullptr;
|
studio::BaseEditor *m_activeEditorUpdatePending = nullptr;
|
||||||
NewMenu m_newMenu;
|
NewMenu m_newMenu;
|
||||||
AboutPopup m_aboutPopup;
|
AboutPopup m_aboutPopup;
|
||||||
const ox::Array<studio::Popup*, 2> m_popups = {
|
ox::Array<studio::Popup*, 2> const m_popups = {
|
||||||
&m_newMenu,
|
&m_newMenu,
|
||||||
&m_aboutPopup
|
&m_aboutPopup
|
||||||
};
|
};
|
||||||
bool m_showProjectExplorer = true;
|
bool m_showProjectExplorer = true;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit StudioUI(turbine::Context *ctx, ox::StringView projectDir) noexcept;
|
explicit StudioUI(turbine::Context &ctx, ox::StringView projectDataDir) noexcept;
|
||||||
|
|
||||||
void update() noexcept;
|
void update() noexcept;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user