[studio] Add a file explorer to NewMenu to choose where new files go
All checks were successful
Build / build (push) Successful in 4m16s
All checks were successful
Build / build (push) Successful in 4m16s
This commit is contained in:
@@ -4,41 +4,96 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
|
||||
#include <turbine/context.hpp>
|
||||
|
||||
#include "widget.hpp"
|
||||
|
||||
namespace studio {
|
||||
|
||||
class FileExplorer {
|
||||
constexpr void safeDelete(class FileTreeModel *m) noexcept;
|
||||
|
||||
class FileExplorer: public ox::SignalHandler {
|
||||
|
||||
friend class FileTreeModel;
|
||||
|
||||
private:
|
||||
keel::Context &m_kctx;
|
||||
class FileTreeModel const *m_selected{};
|
||||
bool const m_fileDraggable{};
|
||||
ox::UPtr<FileTreeModel> m_treeModel;
|
||||
|
||||
public:
|
||||
explicit FileExplorer(keel::Context &kctx, bool const fileDraggable = false) noexcept:
|
||||
m_kctx{kctx},
|
||||
m_fileDraggable{fileDraggable} {}
|
||||
|
||||
virtual ~FileExplorer() = default;
|
||||
|
||||
virtual void fileOpened(ox::StringViewCR path) const noexcept = 0;
|
||||
void draw(StudioContext &ctx, ImVec2 const &sz) const noexcept;
|
||||
|
||||
virtual void drawFileContextMenu(ox::StringViewCR path) const noexcept = 0;
|
||||
void setModel(ox::UPtr<FileTreeModel> &&model, bool selectRoot = false) noexcept;
|
||||
|
||||
virtual void drawDirContextMenu(ox::StringViewCR path) const noexcept = 0;
|
||||
ox::Error setSelectedPath(ox::StringViewCR path) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Optional<ox::String> selectedPath() const;
|
||||
|
||||
virtual void fileOpened(ox::StringViewCR path) const noexcept;
|
||||
|
||||
void drawFileContextMenu(ox::CStringViewCR path) const noexcept;
|
||||
|
||||
void drawDirContextMenu(ox::CStringViewCR path) const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::FileSystem &romFs() const noexcept {
|
||||
return *m_kctx.rom;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual void fileContextMenu(ox::StringViewCR path) const noexcept;
|
||||
|
||||
virtual void dirContextMenu(ox::StringViewCR path) const noexcept;
|
||||
|
||||
void setSelectedNode(FileTreeModel const *const node) noexcept {
|
||||
m_selected = node;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool selected(FileTreeModel const *const node) const noexcept {
|
||||
return m_selected == node;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool fileDraggable() const noexcept {
|
||||
return m_fileDraggable;
|
||||
}
|
||||
|
||||
private:
|
||||
ox::Result<bool> setSelectedPath(ox::StringViewCR path, FileTreeModel const&node) noexcept;
|
||||
|
||||
};
|
||||
|
||||
class FileTreeModel {
|
||||
private:
|
||||
FileExplorer &m_explorer;
|
||||
FileTreeModel *m_parent = nullptr;
|
||||
ox::String m_name;
|
||||
ox::String m_fullPath{m_parent ? m_parent->m_fullPath + "/" + m_name : ox::String{}};
|
||||
ox::String m_imguiNodeName{ox::sfmt("{}##{}", m_name, m_fullPath)};
|
||||
ox::String m_fullPath;
|
||||
ox::Vector<ox::UPtr<FileTreeModel>> m_children;
|
||||
ox::FileType const m_fileType{};
|
||||
|
||||
public:
|
||||
virtual ~FileTreeModel() = default;
|
||||
|
||||
explicit FileTreeModel(
|
||||
FileExplorer &explorer, ox::StringParam name,
|
||||
FileTreeModel *parent = nullptr) noexcept;
|
||||
FileExplorer &explorer,
|
||||
ox::StringParam name,
|
||||
ox::FileType fileType,
|
||||
FileTreeModel const *parent = nullptr) noexcept;
|
||||
|
||||
virtual ~FileTreeModel() = default;
|
||||
|
||||
FileTreeModel(FileTreeModel &&other) noexcept = default;
|
||||
|
||||
@@ -46,6 +101,38 @@ class FileTreeModel {
|
||||
|
||||
void setChildren(ox::Vector<ox::UPtr<FileTreeModel>> children) noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::Vector<ox::UPtr<FileTreeModel>> const&children() const noexcept {
|
||||
return m_children;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
bool isEmptyDir() const noexcept;
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String const &path() const noexcept {
|
||||
return m_fullPath;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr void safeDelete(FileTreeModel *m) noexcept {
|
||||
delete m;
|
||||
}
|
||||
|
||||
ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
|
||||
FileExplorer &explorer,
|
||||
ox::StringParam name,
|
||||
ox::StringViewCR path,
|
||||
FileTreeModel *parent = nullptr,
|
||||
std::function<bool(ox::StringViewCR, ox::FileStat const&)> const&filter =
|
||||
[](ox::StringViewCR, ox::FileStat const&) {return true;},
|
||||
bool showEmptyDirs = true) noexcept;
|
||||
|
||||
ox::Result<ox::UPtr<FileTreeModel>> buildFileTreeModel(
|
||||
FileExplorer &explorer,
|
||||
std::function<bool(ox::StringViewCR, ox::FileStat const&)> const&filter =
|
||||
[](ox::StringViewCR, ox::FileStat const&) {return true;},
|
||||
bool showEmptyDirs = true) noexcept;
|
||||
|
||||
}
|
||||
|
@@ -95,9 +95,9 @@ class ItemMaker {
|
||||
public:
|
||||
constexpr ItemMaker(
|
||||
ox::StringParam pName,
|
||||
ox::StringParam pParentDir,
|
||||
ox::StringViewCR pParentDir,
|
||||
ox::StringParam pFileExt) noexcept:
|
||||
m_parentDir{std::move(pParentDir)},
|
||||
m_parentDir{sfmt("/{}", pParentDir)},
|
||||
m_fileExt{std::move(pFileExt)},
|
||||
m_typeDisplayName{std::move(pName)} {
|
||||
}
|
||||
@@ -128,6 +128,11 @@ class ItemMaker {
|
||||
return m_templates;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String const&fileExt() const noexcept {
|
||||
return m_fileExt;
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String const&defaultPath() const noexcept {
|
||||
return m_parentDir;
|
||||
@@ -140,7 +145,7 @@ class ItemMaker {
|
||||
|
||||
[[nodiscard]]
|
||||
ox::String itemPath(ox::StringViewCR pName) const noexcept {
|
||||
return ox::sfmt("/{}/{}.{}", m_parentDir, pName, m_fileExt);
|
||||
return ox::sfmt("{}/{}.{}", m_parentDir, pName, m_fileExt);
|
||||
}
|
||||
|
||||
[[nodiscard]]
|
||||
@@ -196,12 +201,12 @@ class ItemMakerT final: public ItemMaker {
|
||||
public:
|
||||
constexpr ItemMakerT(
|
||||
ox::StringParam pDisplayName,
|
||||
ox::StringParam pParentDir,
|
||||
ox::StringViewCR pParentDir,
|
||||
ox::StringParam fileExt,
|
||||
ox::ClawFormat const pFmt = ox::ClawFormat::Metal) noexcept:
|
||||
ItemMaker(
|
||||
std::move(pDisplayName),
|
||||
std::move(pParentDir),
|
||||
pParentDir,
|
||||
std::move(fileExt)),
|
||||
m_fmt{pFmt} {
|
||||
installTemplate(ox::make_unique<ItemTemplateT<T>>());
|
||||
@@ -209,13 +214,13 @@ class ItemMakerT final: public ItemMaker {
|
||||
|
||||
constexpr ItemMakerT(
|
||||
ox::StringParam pDisplayName,
|
||||
ox::StringParam pParentDir,
|
||||
ox::StringViewCR pParentDir,
|
||||
ox::StringParam fileExt,
|
||||
T const&pItem,
|
||||
ox::ClawFormat const pFmt) noexcept:
|
||||
ItemMaker(
|
||||
std::move(pDisplayName),
|
||||
std::move(pParentDir),
|
||||
pParentDir,
|
||||
std::move(fileExt)),
|
||||
m_fmt{pFmt} {
|
||||
installTemplate(ox::make_unique<ItemTemplateT<T>>("Default", std::move(pItem)));
|
||||
@@ -223,13 +228,13 @@ class ItemMakerT final: public ItemMaker {
|
||||
|
||||
constexpr ItemMakerT(
|
||||
ox::StringParam pDisplayName,
|
||||
ox::StringParam pParentDir,
|
||||
ox::StringViewCR pParentDir,
|
||||
ox::StringParam fileExt,
|
||||
T &&pItem,
|
||||
ox::ClawFormat const pFmt) noexcept:
|
||||
ItemMaker(
|
||||
std::move(pDisplayName),
|
||||
std::move(pParentDir),
|
||||
pParentDir,
|
||||
std::move(fileExt)),
|
||||
m_fmt{pFmt} {
|
||||
installTemplate(ox::make_unique<ItemTemplateT<T>>("Default", std::move(pItem)));
|
||||
|
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright 2016 - 2025 Gary Talent (gary@drinkingtea.net). All rights reserved.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ox/std/memory.hpp>
|
||||
#include <ox/std/string.hpp>
|
||||
|
||||
#include <turbine/context.hpp>
|
||||
|
||||
#include <studio/filetreemodel.hpp>
|
||||
|
||||
namespace studio {
|
||||
|
||||
}
|
@@ -9,6 +9,7 @@
|
||||
#include <studio/dragdrop.hpp>
|
||||
#include <studio/editor.hpp>
|
||||
#include <studio/filedialog.hpp>
|
||||
#include <studio/filetreemodel.hpp>
|
||||
#include <studio/imguiutil.hpp>
|
||||
#include <studio/module.hpp>
|
||||
#include <studio/itemmaker.hpp>
|
||||
|
Reference in New Issue
Block a user