[nostalgia/studio] Start on ImGui version of Studio
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2016 - 2021 gary@drinkingtea.net
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <imgui.h>
|
||||
|
||||
#include <nostalgia/core/core.hpp>
|
||||
|
||||
#include "lib/configio.hpp"
|
||||
#include "filedialogmanager.hpp"
|
||||
#include "studioapp.hpp"
|
||||
|
||||
namespace nostalgia {
|
||||
|
||||
struct StudioConfig {
|
||||
static constexpr auto TypeName = "net.drinkingtea.nostalgia.studio.StudioConfig";
|
||||
static constexpr auto TypeVersion = 1;
|
||||
ox::String projectPath;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
constexpr ox::Error model(T *h, StudioConfig *config) noexcept {
|
||||
oxReturnError(h->field("project_path", &config->projectPath));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
StudioUI::StudioUI() noexcept {
|
||||
m_widgets.push_back(&m_projectExplorer);
|
||||
if (const auto [config, err] = studio::readConfig<StudioConfig>(); !err) {
|
||||
oxIgnoreError(openProject(config.projectPath));
|
||||
} else {
|
||||
oxErrf("Could not open studio config file: {}\n", err.msg);
|
||||
}
|
||||
}
|
||||
|
||||
static ox::Result<ox::UniquePtr<ProjectTreeModel>>
|
||||
buildProjectTreeModel(const ox::String &name, const ox::String &path, ox::FileSystem *fs) noexcept {
|
||||
ox::Vector<ox::UniquePtr<ProjectTreeModel>> outChildren;
|
||||
oxRequire(stat, fs->stat(path.c_str()));
|
||||
if (stat.fileType == ox::FileType::Directory) {
|
||||
oxRequireM(children, fs->ls(path));
|
||||
//std::sort(children.begin(), children.end());
|
||||
for (const auto &childName : children) {
|
||||
if (childName[0] != '.') {
|
||||
const auto childPath = ox::sfmt("{}/{}", path, childName);
|
||||
oxRequireM(child, buildProjectTreeModel(childName, childPath, fs));
|
||||
outChildren.emplace_back(std::move(child));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ox::make_unique<ProjectTreeModel>(name, std::move(outChildren));
|
||||
}
|
||||
|
||||
void StudioUI::update(core::Context *ctx) noexcept {
|
||||
m_taskRunner.update(ctx);
|
||||
}
|
||||
|
||||
void StudioUI::draw(core::Context *ctx) noexcept {
|
||||
drawMenu(ctx);
|
||||
drawToolbar(ctx);
|
||||
for (auto &w : m_widgets) {
|
||||
w->draw(ctx);
|
||||
}
|
||||
if (m_aboutEnabled &&
|
||||
ImGui::Begin("About", &m_aboutEnabled, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize)) {
|
||||
ImGui::End();
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::drawMenu(core::Context *ctx) noexcept {
|
||||
if (ImGui::BeginMainMenuBar()) {
|
||||
if (ImGui::BeginMenu("File")) {
|
||||
if (ImGui::MenuItem("New...", "Ctrl+N")) {
|
||||
}
|
||||
if (ImGui::MenuItem("Open Project...", "Ctrl+O")) {
|
||||
m_taskRunner.add(new FileDialogManager(this, &StudioUI::openProject));
|
||||
}
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S", false, m_saveEnabled)) {
|
||||
}
|
||||
if (ImGui::MenuItem("Quit", "Ctrl+Q")) {
|
||||
core::shutdown(ctx);
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Module", false)) {
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Help")) {
|
||||
if (ImGui::MenuItem("About")) {
|
||||
m_aboutEnabled = true;
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
void StudioUI::drawToolbar(core::Context*) noexcept {
|
||||
constexpr auto BtnWidth = 96;
|
||||
constexpr auto BtnHeight = 32;
|
||||
const auto viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x, viewport->Pos.y + 20));
|
||||
ImGui::SetNextWindowSize(ImVec2(viewport->Size.x, 48));
|
||||
const auto flags = ImGuiWindowFlags_NoTitleBar
|
||||
| ImGuiWindowFlags_NoResize
|
||||
| ImGuiWindowFlags_NoMove
|
||||
| ImGuiWindowFlags_NoScrollbar
|
||||
| ImGuiWindowFlags_NoSavedSettings;
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
|
||||
ImGui::Begin("MainToolbar", nullptr, flags);
|
||||
ImGui::PopStyleVar();
|
||||
{
|
||||
ImGui::Button("New##MainToolbar", ImVec2(BtnWidth, BtnHeight));
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Open Project##MainToolbar", ImVec2(BtnWidth, BtnHeight))) {
|
||||
m_taskRunner.add(new FileDialogManager(this, &StudioUI::openProject));
|
||||
}
|
||||
ImGui::SameLine();
|
||||
ImGui::Button("Save##MainToolbar", ImVec2(BtnWidth, BtnHeight));
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
ox::Error StudioUI::openProject(const ox::String &path) noexcept {
|
||||
m_project = ox::make_unique<studio::Project>(path);
|
||||
m_project->fileAdded.connect(this, &StudioUI::refreshProjectTreeModel);
|
||||
m_project->fileDeleted.connect(this, &StudioUI::refreshProjectTreeModel);
|
||||
oxReturnError(studio::editConfig<StudioConfig>([path](StudioConfig *config) {
|
||||
config->projectPath = path;
|
||||
}));
|
||||
return refreshProjectTreeModel();
|
||||
}
|
||||
|
||||
ox::Error StudioUI::refreshProjectTreeModel(const ox::String&) noexcept {
|
||||
oxRequireM(model, buildProjectTreeModel("Project", "/", m_project->romFs()));
|
||||
m_projectExplorer.setModel(std::move(model));
|
||||
return OxError(0);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user