allow Node/Ref to accept drag&drop
This commit is contained in:
parent
9ff6339fe4
commit
6eaab065aa
@ -57,6 +57,7 @@ target_sources(nf7
|
|||||||
common/generic_memento.hh
|
common/generic_memento.hh
|
||||||
common/generic_type_info.hh
|
common/generic_type_info.hh
|
||||||
common/generic_watcher.hh
|
common/generic_watcher.hh
|
||||||
|
common/gui_dnd.hh
|
||||||
common/gui_file.hh
|
common/gui_file.hh
|
||||||
common/gui_node.hh
|
common/gui_node.hh
|
||||||
common/gui_resizer.hh
|
common/gui_resizer.hh
|
||||||
|
@ -10,10 +10,11 @@ namespace nf7 {
|
|||||||
class DirItem : public File::Interface {
|
class DirItem : public File::Interface {
|
||||||
public:
|
public:
|
||||||
enum Flag : uint8_t {
|
enum Flag : uint8_t {
|
||||||
kNone = 0,
|
kNone = 0,
|
||||||
kTree = 1 << 0,
|
kTree = 1 << 0,
|
||||||
kMenu = 1 << 1,
|
kMenu = 1 << 1,
|
||||||
kTooltip = 1 << 2,
|
kTooltip = 1 << 2,
|
||||||
|
kDragDropTarget = 1 << 3,
|
||||||
};
|
};
|
||||||
using Flags = uint8_t;
|
using Flags = uint8_t;
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ class DirItem : public File::Interface {
|
|||||||
virtual void UpdateTree() noexcept { }
|
virtual void UpdateTree() noexcept { }
|
||||||
virtual void UpdateMenu() noexcept { }
|
virtual void UpdateMenu() noexcept { }
|
||||||
virtual void UpdateTooltip() noexcept { }
|
virtual void UpdateTooltip() noexcept { }
|
||||||
|
virtual void UpdateDragDropTarget() noexcept { }
|
||||||
|
|
||||||
Flags flags() const noexcept { return flags_; }
|
Flags flags() const noexcept { return flags_; }
|
||||||
|
|
||||||
|
69
common/gui_dnd.hh
Normal file
69
common/gui_dnd.hh
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <optional>
|
||||||
|
#include <string>
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
|
||||||
|
#include "nf7.hh"
|
||||||
|
|
||||||
|
|
||||||
|
namespace nf7::gui::dnd {
|
||||||
|
|
||||||
|
// data entity is char[] of file path
|
||||||
|
constexpr const char* kFilePath = "nf7::File::Path";
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool Send(const char* type, const T&) noexcept;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline bool Send<std::string>(const char* type, const std::string& v) noexcept {
|
||||||
|
return ImGui::SetDragDropPayload(type, v.data(), v.size());
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
inline bool Send<std::string_view>(const char* type, const std::string_view& v) noexcept {
|
||||||
|
return ImGui::SetDragDropPayload(type, v.data(), v.size());
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
inline bool Send<File::Path>(const char* type, const File::Path& p) noexcept {
|
||||||
|
return Send(type, p.Stringify());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T To(const ImGuiPayload&) noexcept;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
inline std::string To<std::string>(const ImGuiPayload& pay) noexcept {
|
||||||
|
std::string ret;
|
||||||
|
ret.resize(static_cast<size_t>(pay.DataSize));
|
||||||
|
std::memcpy(ret.data(), pay.Data, ret.size());
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
inline File::Path To<File::Path>(const ImGuiPayload& pay) noexcept {
|
||||||
|
return File::Path::Parse(To<std::string>(pay));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
std::optional<T> Accept(const char* type, ImGuiDragDropFlags flags = 0) noexcept {
|
||||||
|
if (auto pay = ImGui::AcceptDragDropPayload(type, flags)) {
|
||||||
|
return To<T>(*pay);
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
const ImGuiPayload* Peek(const char* type, auto& v, ImGuiDragDropFlags flags = 0) noexcept {
|
||||||
|
flags |= ImGuiDragDropFlags_AcceptBeforeDelivery;
|
||||||
|
if (auto pay = ImGui::AcceptDragDropPayload(type, flags)) {
|
||||||
|
if (pay->IsDelivery()) v = To<T>(*pay);
|
||||||
|
return pay;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nf7::gui::dnd
|
@ -7,6 +7,8 @@
|
|||||||
|
|
||||||
#include "nf7.hh"
|
#include "nf7.hh"
|
||||||
|
|
||||||
|
#include "common/gui_dnd.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace nf7::gui {
|
namespace nf7::gui {
|
||||||
|
|
||||||
@ -128,4 +130,18 @@ struct FileCreatePopup final {
|
|||||||
std::string type_filter_;
|
std::string type_filter_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace nf7
|
|
||||||
|
inline bool InputFilePath(const char* id, std::string* path) noexcept {
|
||||||
|
bool ret = ImGui::InputText(id, path, ImGuiInputTextFlags_EnterReturnsTrue);
|
||||||
|
|
||||||
|
if (ImGui::BeginDragDropTarget()) {
|
||||||
|
if (auto str = gui::dnd::Accept<std::string>(gui::dnd::kFilePath)) {
|
||||||
|
*path = *str;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nf7::gui
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#include "common/generic_context.hh"
|
#include "common/generic_context.hh"
|
||||||
#include "common/generic_type_info.hh"
|
#include "common/generic_type_info.hh"
|
||||||
#include "common/generic_watcher.hh"
|
#include "common/generic_watcher.hh"
|
||||||
|
#include "common/gui_dnd.hh"
|
||||||
#include "common/lambda.hh"
|
#include "common/lambda.hh"
|
||||||
#include "common/logger_ref.hh"
|
#include "common/logger_ref.hh"
|
||||||
#include "common/luajit_obj.hh"
|
#include "common/luajit_obj.hh"
|
||||||
@ -47,7 +48,8 @@ class Node final : public nf7::File, public nf7::DirItem, public nf7::Node {
|
|||||||
Node(Env& env, File::Path&& path = {}, std::string_view desc = "",
|
Node(Env& env, File::Path&& path = {}, std::string_view desc = "",
|
||||||
std::vector<std::string>&& in = {},
|
std::vector<std::string>&& in = {},
|
||||||
std::vector<std::string>&& out = {}) noexcept :
|
std::vector<std::string>&& out = {}) noexcept :
|
||||||
File(kType, env), DirItem(DirItem::kMenu | DirItem::kTooltip),
|
File(kType, env),
|
||||||
|
DirItem(DirItem::kMenu | DirItem::kTooltip | DirItem::kDragDropTarget),
|
||||||
log_(std::make_shared<nf7::LoggerRef>()),
|
log_(std::make_shared<nf7::LoggerRef>()),
|
||||||
obj_(*this, std::move(path)), desc_(desc) {
|
obj_(*this, std::move(path)), desc_(desc) {
|
||||||
input_ = std::move(in);
|
input_ = std::move(in);
|
||||||
@ -84,6 +86,7 @@ class Node final : public nf7::File, public nf7::DirItem, public nf7::Node {
|
|||||||
static void UpdateList(std::vector<std::string>&) noexcept;
|
static void UpdateList(std::vector<std::string>&) noexcept;
|
||||||
void UpdateMenu() noexcept override;
|
void UpdateMenu() noexcept override;
|
||||||
void UpdateTooltip() noexcept override;
|
void UpdateTooltip() noexcept override;
|
||||||
|
void UpdateDragDropTarget() noexcept override;
|
||||||
void UpdateNode(Node::Editor&) noexcept override;
|
void UpdateNode(Node::Editor&) noexcept override;
|
||||||
|
|
||||||
File::Interface* interface(const std::type_info& t) noexcept override {
|
File::Interface* interface(const std::type_info& t) noexcept override {
|
||||||
@ -404,6 +407,13 @@ void Node::UpdateTooltip() noexcept {
|
|||||||
ImGui::TextUnformatted(desc_.c_str());
|
ImGui::TextUnformatted(desc_.c_str());
|
||||||
}
|
}
|
||||||
ImGui::Unindent();
|
ImGui::Unindent();
|
||||||
|
|
||||||
|
ImGui::TextDisabled("drop a file here to set it as source");
|
||||||
|
}
|
||||||
|
void Node::UpdateDragDropTarget() noexcept {
|
||||||
|
if (auto p = gui::dnd::Accept<Path>(gui::dnd::kFilePath)) {
|
||||||
|
obj_ = std::move(*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void Node::UpdateNode(Node::Editor&) noexcept {
|
void Node::UpdateNode(Node::Editor&) noexcept {
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "common/generic_context.hh"
|
#include "common/generic_context.hh"
|
||||||
#include "common/generic_type_info.hh"
|
#include "common/generic_type_info.hh"
|
||||||
#include "common/generic_watcher.hh"
|
#include "common/generic_watcher.hh"
|
||||||
|
#include "common/gui_dnd.hh"
|
||||||
#include "common/lock.hh"
|
#include "common/lock.hh"
|
||||||
#include "common/luajit.hh"
|
#include "common/luajit.hh"
|
||||||
#include "common/luajit_obj.hh"
|
#include "common/luajit_obj.hh"
|
||||||
@ -46,7 +47,8 @@ class Obj final : public nf7::File,
|
|||||||
class ExecTask;
|
class ExecTask;
|
||||||
|
|
||||||
Obj(Env& env, Path&& path = {}) noexcept :
|
Obj(Env& env, Path&& path = {}) noexcept :
|
||||||
File(kType, env), DirItem(DirItem::kTooltip | DirItem::kMenu),
|
File(kType, env),
|
||||||
|
DirItem(DirItem::kTooltip | DirItem::kMenu | DirItem::kDragDropTarget),
|
||||||
log_(std::make_shared<nf7::LoggerRef>()),
|
log_(std::make_shared<nf7::LoggerRef>()),
|
||||||
src_(*this, std::move(path)) {
|
src_(*this, std::move(path)) {
|
||||||
}
|
}
|
||||||
@ -65,6 +67,7 @@ class Obj final : public nf7::File,
|
|||||||
void Update() noexcept override;
|
void Update() noexcept override;
|
||||||
void UpdateMenu() noexcept override;
|
void UpdateMenu() noexcept override;
|
||||||
void UpdateTooltip() noexcept override;
|
void UpdateTooltip() noexcept override;
|
||||||
|
void UpdateDragDropTarget() noexcept override;
|
||||||
|
|
||||||
nf7::Future<std::shared_ptr<nf7::luajit::Ref>> Build() noexcept override;
|
nf7::Future<std::shared_ptr<nf7::luajit::Ref>> Build() noexcept override;
|
||||||
|
|
||||||
@ -314,6 +317,12 @@ void Obj::UpdateMenu() noexcept {
|
|||||||
void Obj::UpdateTooltip() noexcept {
|
void Obj::UpdateTooltip() noexcept {
|
||||||
ImGui::Text("source: %s", src_.path().Stringify().c_str());
|
ImGui::Text("source: %s", src_.path().Stringify().c_str());
|
||||||
ImGui::Text("cache : %d", cache_? cache_->index(): -1);
|
ImGui::Text("cache : %d", cache_? cache_->index(): -1);
|
||||||
|
ImGui::TextDisabled("drop a file here to set it as source");
|
||||||
|
}
|
||||||
|
void Obj::UpdateDragDropTarget() noexcept {
|
||||||
|
if (auto p = gui::dnd::Accept<Path>(gui::dnd::kFilePath)) {
|
||||||
|
src_ = std::move(*p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "common/generic_context.hh"
|
#include "common/generic_context.hh"
|
||||||
#include "common/generic_memento.hh"
|
#include "common/generic_memento.hh"
|
||||||
#include "common/generic_type_info.hh"
|
#include "common/generic_type_info.hh"
|
||||||
|
#include "common/gui_dnd.hh"
|
||||||
#include "common/gui_node.hh"
|
#include "common/gui_node.hh"
|
||||||
#include "common/lambda.hh"
|
#include "common/lambda.hh"
|
||||||
#include "common/logger_ref.hh"
|
#include "common/logger_ref.hh"
|
||||||
@ -41,16 +42,11 @@ class Ref final : public nf7::File, public nf7::Node {
|
|||||||
std::vector<std::string>&& out = {}) noexcept :
|
std::vector<std::string>&& out = {}) noexcept :
|
||||||
File(kType, env),
|
File(kType, env),
|
||||||
mem_(*this, {*this, std::move(path), std::move(in), std::move(out)}) {
|
mem_(*this, {*this, std::move(path), std::move(in), std::move(out)}) {
|
||||||
auto& d = mem_.data();
|
|
||||||
d.input = std::move(in);
|
|
||||||
d.output = std::move(out);
|
|
||||||
CopySock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref(Env& env, Deserializer& ar) : Ref(env) {
|
Ref(Env& env, Deserializer& ar) : Ref(env) {
|
||||||
auto& d = mem_.data();
|
auto& d = mem_.data();
|
||||||
ar(d.target, d.input, d.output);
|
ar(d.target, d.input, d.output);
|
||||||
CopySock();
|
|
||||||
}
|
}
|
||||||
void Serialize(Serializer& ar) const noexcept override {
|
void Serialize(Serializer& ar) const noexcept override {
|
||||||
const auto& d = mem_.data();
|
const auto& d = mem_.data();
|
||||||
@ -60,15 +56,21 @@ class Ref final : public nf7::File, public nf7::Node {
|
|||||||
const auto& d = mem_.data();
|
const auto& d = mem_.data();
|
||||||
return std::make_unique<Ref>(
|
return std::make_unique<Ref>(
|
||||||
env, Path{d.target.path()},
|
env, Path{d.target.path()},
|
||||||
std::vector<std::string>{d.input}, std::vector<std::string>{d.output});
|
std::vector<std::string>{input_}, std::vector<std::string>{output_});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<nf7::Lambda> CreateLambda() noexcept override;
|
std::shared_ptr<nf7::Lambda> CreateLambda() noexcept override;
|
||||||
|
|
||||||
void Handle(const Event& ev) noexcept {
|
void Handle(const Event& ev) noexcept {
|
||||||
|
const auto& d = mem_.data();
|
||||||
|
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
case Event::kAdd:
|
case Event::kAdd:
|
||||||
log_.SetUp(*this);
|
log_.SetUp(*this);
|
||||||
|
/* fallthrough */
|
||||||
|
case Event::kUpdate:
|
||||||
|
input_ = d.input;
|
||||||
|
output_ = d.output;
|
||||||
return;
|
return;
|
||||||
case Event::kRemove:
|
case Event::kRemove:
|
||||||
log_.TearDown();
|
log_.TearDown();
|
||||||
@ -106,35 +108,42 @@ class Ref final : public nf7::File, public nf7::Node {
|
|||||||
nf7::GenericMemento<Data> mem_;
|
nf7::GenericMemento<Data> mem_;
|
||||||
|
|
||||||
|
|
||||||
void Sync(bool quiet = true) noexcept
|
void SyncQuiet() noexcept {
|
||||||
try {
|
|
||||||
auto& n = target();
|
|
||||||
auto& d = mem_.data();
|
auto& d = mem_.data();
|
||||||
|
try {
|
||||||
|
auto& n = target();
|
||||||
|
|
||||||
const auto i = n.input();
|
const auto i = n.input();
|
||||||
d.input = std::vector<std::string>{i.begin(), i.end()};
|
d.input = std::vector<std::string>{i.begin(), i.end()};
|
||||||
|
|
||||||
const auto o = n.output();
|
const auto o = n.output();
|
||||||
d.output = std::vector<std::string>{o.begin(), o.end()};
|
d.output = std::vector<std::string>{o.begin(), o.end()};
|
||||||
|
} catch (nf7::Exception& e) {
|
||||||
CopySock(quiet);
|
d.input = {};
|
||||||
} catch (nf7::Exception& e) {
|
d.output = {};
|
||||||
log_.Error("failed to sync: "+e.msg());
|
log_.Error("failed to sync: "+e.msg());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void CopySock(bool quiet = true) noexcept {
|
void Sync() noexcept {
|
||||||
std::vector<std::string> in, out;
|
SyncQuiet();
|
||||||
if (!quiet) {
|
|
||||||
in = std::move(input_);
|
|
||||||
out = std::move(output_);
|
|
||||||
}
|
|
||||||
const auto& d = mem_.data();
|
const auto& d = mem_.data();
|
||||||
input_ = d.input;
|
if (input_ != d.input || output_ != d.output) {
|
||||||
output_ = d.output;
|
mem_.Commit();
|
||||||
if (!quiet) {
|
|
||||||
if (in != input_ || out != output_) Touch();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExecChangePath(Path&& p) noexcept {
|
||||||
|
auto& target = mem_.data().target;
|
||||||
|
if (p == target.path()) return;
|
||||||
|
env().ExecMain(
|
||||||
|
std::make_shared<nf7::GenericContext>(*this, "change path"),
|
||||||
|
[this, &target, p = std::move(p)]() mutable {
|
||||||
|
target = std::move(p);
|
||||||
|
SyncQuiet();
|
||||||
|
mem_.Commit();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
nf7::Node& target() const {
|
nf7::Node& target() const {
|
||||||
auto& f = *mem_.data().target;
|
auto& f = *mem_.data().target;
|
||||||
if (&f == this) throw nf7::Exception("self reference");
|
if (&f == this) throw nf7::Exception("self reference");
|
||||||
@ -242,15 +251,7 @@ void Ref::Update() noexcept {
|
|||||||
|
|
||||||
if (!err && (ImGui::Button("ok") || submit)) {
|
if (!err && (ImGui::Button("ok") || submit)) {
|
||||||
ImGui::CloseCurrentPopup();
|
ImGui::CloseCurrentPopup();
|
||||||
if (path != d.target.path()) {
|
ExecChangePath(std::move(path));
|
||||||
env().ExecMain(
|
|
||||||
std::make_shared<nf7::GenericContext>(*this, "change path"),
|
|
||||||
[this, path = std::move(path)]() {
|
|
||||||
mem_.data().target = std::move(path);
|
|
||||||
Sync(true /* = quiet */);
|
|
||||||
mem_.Commit();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
@ -264,7 +265,7 @@ void Ref::UpdateNode(Node::Editor&) noexcept {
|
|||||||
if (ImGui::SmallButton("sync")) {
|
if (ImGui::SmallButton("sync")) {
|
||||||
env().ExecMain(
|
env().ExecMain(
|
||||||
std::make_shared<nf7::GenericContext>(*this, "synchornizing with target node"),
|
std::make_shared<nf7::GenericContext>(*this, "synchornizing with target node"),
|
||||||
[this]() { Sync(false /* = quiet */); });
|
[this]() { Sync(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto pathstr = mem_.data().target.path().Stringify();
|
const auto pathstr = mem_.data().target.path().Stringify();
|
||||||
@ -288,6 +289,12 @@ void Ref::UpdateNode(Node::Editor&) noexcept {
|
|||||||
if (ImGui::Button(pathstr.c_str(), {w, 0})) {
|
if (ImGui::Button(pathstr.c_str(), {w, 0})) {
|
||||||
popup_ = "ConfigPopup";
|
popup_ = "ConfigPopup";
|
||||||
}
|
}
|
||||||
|
if (ImGui::BeginDragDropTarget()) {
|
||||||
|
if (auto p = gui::dnd::Accept<Path>(gui::dnd::kFilePath)) {
|
||||||
|
ExecChangePath(std::move(*p));
|
||||||
|
}
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
|
||||||
const auto right = ImGui::GetCursorPosX() + w;
|
const auto right = ImGui::GetCursorPosX() + w;
|
||||||
ImGui::BeginGroup();
|
ImGui::BeginGroup();
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "common/dir_item.hh"
|
#include "common/dir_item.hh"
|
||||||
#include "common/generic_context.hh"
|
#include "common/generic_context.hh"
|
||||||
#include "common/generic_type_info.hh"
|
#include "common/generic_type_info.hh"
|
||||||
|
#include "common/gui_dnd.hh"
|
||||||
#include "common/gui_file.hh"
|
#include "common/gui_file.hh"
|
||||||
#include "common/gui_window.hh"
|
#include "common/gui_window.hh"
|
||||||
#include "common/ptr_selector.hh"
|
#include "common/ptr_selector.hh"
|
||||||
@ -236,8 +237,7 @@ void Dir::UpdateTree() noexcept {
|
|||||||
flags |= ImGuiTreeNodeFlags_Leaf;
|
flags |= ImGuiTreeNodeFlags_Leaf;
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool open = ImGui::TreeNodeEx(
|
const bool open = ImGui::TreeNodeEx(item.second.get(), flags, "%s", name.c_str());
|
||||||
item.second.get(), flags, "%s", name.c_str());
|
|
||||||
|
|
||||||
// tooltip
|
// tooltip
|
||||||
if (ImGui::IsItemHovered()) {
|
if (ImGui::IsItemHovered()) {
|
||||||
@ -274,6 +274,23 @@ void Dir::UpdateTree() noexcept {
|
|||||||
ImGui::EndPopup();
|
ImGui::EndPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dnd source
|
||||||
|
if (ImGui::BeginDragDropSource()) {
|
||||||
|
gui::dnd::Send(gui::dnd::kFilePath, item.second->abspath());
|
||||||
|
ImGui::TextUnformatted(file.type().name().c_str());
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextDisabled(file.abspath().Stringify().c_str());
|
||||||
|
ImGui::EndDragDropSource();
|
||||||
|
}
|
||||||
|
|
||||||
|
// dnd target
|
||||||
|
if (ditem && (ditem->flags() & DirItem::kDragDropTarget)) {
|
||||||
|
if (ImGui::BeginDragDropTarget()) {
|
||||||
|
ditem->UpdateDragDropTarget();
|
||||||
|
ImGui::EndDragDropTarget();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// displayed contents
|
// displayed contents
|
||||||
if (open) {
|
if (open) {
|
||||||
ImGui::TreePush(&file);
|
ImGui::TreePush(&file);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user