tidy GUI codes

This commit is contained in:
falsycat 2022-11-06 11:30:17 +09:00
parent b463e112aa
commit 7ee26d431e
18 changed files with 115 additions and 799 deletions

View File

@ -71,8 +71,6 @@ target_sources(nf7
common/dir_item.hh
common/factory.hh
common/file_base.hh
common/file_holder.hh
common/file_holder.cc
common/font_queue.hh
common/future.hh
common/generic_context.hh
@ -88,10 +86,7 @@ target_sources(nf7
common/gui.hh
common/gui.cc
common/gui_config.hh
common/gui_context.hh
common/gui_dnd.hh
common/gui_file.hh
common/gui_file.cc
common/gui_node.hh
common/gui_timeline.hh
common/gui_timeline.cc

View File

@ -1,134 +0,0 @@
#include "common/file_holder.hh"
#include <imgui.h>
using namespace std::literals;
namespace nf7 {
nf7::File* FileHolder::Find(std::string_view name) const noexcept {
return name == id_? file_: nullptr;
}
void FileHolder::Handle(const nf7::File::Event& ev) noexcept {
switch (ev.type) {
case nf7::File::Event::kAdd:
SetUp();
break;
case nf7::File::Event::kRemove:
TearDown();
break;
default:
break;
}
}
void FileHolder::Update() noexcept {
if (own()) {
ImGui::PushID(this);
file_->Update();
ImGui::PopID();
}
}
void FileHolder::SetUp() noexcept {
const bool first_setup = !file_;
if (own()) {
file_ = std::get<std::shared_ptr<nf7::File>>(entity_).get();
if (owner_->id() && file_->id() == 0) {
file_->MoveUnder(*owner_, id_);
}
} else if (ref()) {
if (owner_->id()) {
try {
file_ = &owner_->ResolveOrThrow(path());
} catch (nf7::File::NotFoundException&) {
file_ = nullptr;
}
}
}
if (file_) {
auto mem = own()? file_->interface<nf7::Memento>(): nullptr;
// init watcher
if (file_->id() && !watcher_) {
watcher_.emplace(file_->env());
watcher_->Watch(file_->id());
watcher_->AddHandler(nf7::File::Event::kUpdate, [this, mem](auto&) {
if (mem) {
auto ptag = std::exchange(tag_, mem->Save());
if (ptag != tag_) {
onChildMementoChange();
if (mem_) mem_->Commit(); // commit owner's memento
}
}
onChildUpdate();
owner_->Touch();
});
}
// memento setup
if (first_setup && mem) {
if (!tag_) {
tag_ = mem->Save();
} else {
mem->Restore(tag_);
}
}
}
}
void FileHolder::TearDown() noexcept {
if (!owner_->id()) return;
if (own()) {
file_->Isolate();
}
file_ = nullptr;
watcher_ = std::nullopt;
}
FileHolder::Tag::Tag(const Tag& src) noexcept {
if (src.target_) {
entity_ = src.target_->entity_;
tag_ = src.target_->tag_;
} else {
entity_ = src.entity_;
tag_ = src.tag_;
}
}
FileHolder::Tag& FileHolder::Tag::operator=(const Tag& src) noexcept {
if (!src.target_ && target_) {
// restore
target_->TearDown();
target_->entity_ = src.entity_;
target_->tag_ = src.tag_;
target_->SetUp();
} else if (!src.target_ && !target_) {
// shallow copy
entity_ = src.entity_;
tag_ = src.tag_;
} else {
assert(false);
}
return *this;
}
void FileHolder::Tag::SetTarget(nf7::FileHolder& h) noexcept {
assert(!target_);
target_ = &h;
h.TearDown();
if (std::holds_alternative<nf7::File::Path>(entity_)) {
h.Emplace(std::move(std::get<nf7::File::Path>(entity_)));
} else if (std::holds_alternative<std::shared_ptr<nf7::File>>(entity_)) {
h.Emplace(std::get<std::shared_ptr<nf7::File>>(entity_)->Clone(h.env()));
}
entity_ = std::monostate {};
tag_ = nullptr;
h.SetUp();
}
} // namespace nf7

View File

@ -1,189 +0,0 @@
#pragma once
#include <cassert>
#include <functional>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <variant>
#include <yas/serialize.hpp>
#include <yas/types/std/variant.hpp>
#include "nf7.hh"
#include "common/file_base.hh"
#include "common/generic_watcher.hh"
#include "common/memento.hh"
#include "common/mutable_memento.hh"
#include "common/yas_nf7.hh"
#include "common/yas_std_variant.hh"
namespace nf7 {
class FileHolder : public nf7::FileBase::Feature {
public:
class Tag;
class EmptyException final : public nf7::Exception {
public:
using nf7::Exception::Exception;
};
using Entity = std::variant<
std::monostate, nf7::File::Path, std::shared_ptr<nf7::File>>;
FileHolder(nf7::FileBase& owner, std::string_view id,
nf7::MutableMemento* mem = nullptr) noexcept :
nf7::FileBase::Feature(owner),
owner_(&owner), mem_(mem), id_(id) {
}
FileHolder(nf7::FileBase& owner, std::string_view id,
nf7::MutableMemento& mem) noexcept :
FileHolder(owner, id, &mem) {
}
FileHolder(const FileHolder&) = delete;
FileHolder(FileHolder&&) = delete;
FileHolder& operator=(const FileHolder&) = delete;
FileHolder& operator=(FileHolder&&) = delete;
void Serialize(nf7::Serializer& ar) const {
ar(entity_);
}
void Deserialize(nf7::Deserializer& ar) {
try {
ar(entity_);
} catch (nf7::Exception&) {
entity_ = std::monostate {};
ar.env().Throw(std::current_exception());
}
SetUp();
}
void Emplace(nf7::File::Path&& path) noexcept {
TearDown();
tag_ = nullptr;
entity_ = std::move(path);
SetUp();
onEmplace();
if (mem_) mem_->Commit();
}
void Emplace(std::unique_ptr<nf7::File>&& f) noexcept {
TearDown();
tag_ = nullptr;
entity_ = std::move(f);
SetUp();
onEmplace();
if (mem_) mem_->Commit();
}
nf7::File& GetFileOrThrow() {
if (auto f = GetFile()) {
return *f;
}
throw EmptyException {"holder is empty"};
}
nf7::File* GetFile() noexcept {
SetUp();
return file_;
}
// nf7::FileBase::Feature methods
nf7::File* Find(std::string_view name) const noexcept override;
void Handle(const nf7::File::Event&) noexcept override;
void Update() noexcept override;
bool own() const noexcept {
return std::holds_alternative<std::shared_ptr<nf7::File>>(entity_);
}
bool ref() const noexcept {
return std::holds_alternative<nf7::File::Path>(entity_);
}
bool empty() const noexcept {
return std::holds_alternative<std::monostate>(entity_);
}
nf7::File& owner() const noexcept { return *owner_; }
nf7::Env& env() const noexcept { return owner_->env(); }
const std::string& id() const noexcept { return id_; }
nf7::File* file() const noexcept { return file_; }
nf7::File::Path path() const noexcept {
assert(!empty());
return own()? nf7::File::Path {{id_}}: std::get<nf7::File::Path>(entity_);
}
// called when kUpdate event is happened on the child
std::function<void(void)> onChildUpdate = [](){};
// called when the child's memento tag id is changed
std::function<void(void)> onChildMementoChange = [](){};
// called right before returning from Emplace()
std::function<void(void)> onEmplace = [](){};
private:
nf7::File* const owner_;
nf7::MutableMemento* const mem_;
const std::string id_;
Entity entity_;
std::shared_ptr<nf7::Memento::Tag> tag_;
nf7::File* file_ = nullptr;
std::optional<nf7::GenericWatcher> watcher_;
void SetUp() noexcept;
void TearDown() noexcept;
};
// to save/restore FileHolder's changes through GenericMemento
class FileHolder::Tag final {
public:
Tag() = default;
Tag(const Tag&) noexcept;
Tag& operator=(const Tag&) noexcept;
Tag(Tag&&) = default;
Tag& operator=(Tag&&) = default;
void SetTarget(nf7::FileHolder& h) noexcept;
private:
nf7::FileHolder* target_ = nullptr;
Entity entity_;
std::shared_ptr<nf7::Memento::Tag> tag_;
};
} // namespace nf7
namespace yas::detail {
template <size_t F>
struct serializer<
type_prop::not_a_fundamental,
ser_case::use_internal_serializer,
F,
nf7::FileHolder> {
public:
template <typename Archive>
static Archive& save(Archive& ar, const nf7::FileHolder& h) {
h.Serialize(ar);
return ar;
}
template <typename Archive>
static Archive& load(Archive& ar, nf7::FileHolder& h) {
h.Deserialize(ar);
return ar;
}
};
} // namespace yas::detail

View File

@ -6,6 +6,8 @@
#include <imgui.h>
#include <imgui_stdlib.h>
#include <ImNodes.h>
#include "nf7.hh"
#include "common/gui_dnd.hh"
@ -69,4 +71,66 @@ bool PathButton(const char* id, nf7::File::Path& p, nf7::File&) noexcept {
return ret;
}
void ContextStack(const nf7::Context& ctx) noexcept {
for (auto p = ctx.parent(); p; p = p->parent()) {
auto f = ctx.env().GetFile(p->initiator());
const auto path = f? f->abspath().Stringify(): "[missing file]";
ImGui::TextUnformatted(path.c_str());
ImGui::TextDisabled("%s", p->GetDescription().c_str());
}
}
void NodeSocket() noexcept {
auto win = ImGui::GetCurrentWindow();
const auto em = ImGui::GetFontSize();
const auto lh = std::max(win->DC.CurrLineSize.y, em);
const auto rad = em/2 / ImNodes::CanvasState().Zoom;
const auto sz = ImVec2(rad*2, lh);
const auto pos = ImGui::GetCursorScreenPos() + sz/2;
auto dlist = ImGui::GetWindowDrawList();
dlist->AddCircleFilled(
pos, rad, IM_COL32(100, 100, 100, 100));
dlist->AddCircleFilled(
pos, rad*.8f, IM_COL32(200, 200, 200, 200));
ImGui::Dummy(sz);
}
void NodeInputSockets(std::span<const std::string> names) noexcept {
ImGui::BeginGroup();
for (auto& name : names) {
if (ImNodes::BeginInputSlot(name.c_str(), 1)) {
ImGui::AlignTextToFramePadding();
nf7::gui::NodeSocket();
ImGui::SameLine();
ImGui::TextUnformatted(name.c_str());
ImNodes::EndSlot();
}
}
ImGui::EndGroup();
}
void NodeOutputSockets(std::span<const std::string> names) noexcept {
float maxw = 0;
for (auto& name : names) {
maxw = std::max(maxw, ImGui::CalcTextSize(name.c_str()).x);
}
ImGui::BeginGroup();
for (auto& name : names) {
const auto w = ImGui::CalcTextSize(name.c_str()).x;
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+maxw-w);
if (ImNodes::BeginOutputSlot(name.c_str(), 1)) {
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted(name.c_str());
ImGui::SameLine();
nf7::gui::NodeSocket();
ImNodes::EndSlot();
}
}
ImGui::EndGroup();
}
} // namespace nf7::gui

View File

@ -1,10 +1,44 @@
#pragma once
#include <cinttypes>
#include <cstdint>
#include <cstring>
#include <string>
#include "nf7.hh"
namespace nf7::gui {
// widgets
bool PathButton(const char* id, nf7::File::Path&, nf7::File&) noexcept;
void ContextStack(const nf7::Context&) noexcept;
void NodeSocket() noexcept;
void NodeInputSockets(std::span<const std::string>) noexcept;
void NodeOutputSockets(std::span<const std::string>) noexcept;
// stringify utility
inline std::string GetContextDisplayName(const nf7::Context& ctx) noexcept {
auto f = ctx.env().GetFile(ctx.initiator());
const auto initiator =
f? f->abspath().Stringify(): std::string {"<owner missing>"};
char buf[32];
std::snprintf(buf, sizeof(buf), "(0x%0" PRIXPTR ")", reinterpret_cast<uintptr_t>(&ctx));
return initiator + " " + buf;
}
inline std::string GetParentContextDisplayName(const nf7::Context& ctx) noexcept {
if (auto parent = ctx.parent()) {
return nf7::gui::GetContextDisplayName(*parent);
} else if (ctx.depth() == 0) {
return "(isolated)";
} else {
return "<owner disappeared> MEMORY LEAK? ;(";
}
}
} // namespace nf7::gui

View File

@ -1,46 +0,0 @@
#pragma once
#include <cinttypes>
#include <string>
#include <imgui.h>
#include "nf7.hh"
namespace nf7::gui {
inline std::string GetContextDisplayName(const nf7::Context& ctx) noexcept {
auto f = ctx.env().GetFile(ctx.initiator());
const auto initiator =
f? f->abspath().Stringify(): std::string {"<owner missing>"};
char buf[32];
std::snprintf(buf, sizeof(buf), "(0x%0" PRIXPTR ")", reinterpret_cast<uintptr_t>(&ctx));
return initiator + " " + buf;
}
inline std::string GetParentContextDisplayName(const nf7::Context& ctx) noexcept {
if (auto parent = ctx.parent()) {
return nf7::gui::GetContextDisplayName(*parent);
} else if (ctx.depth() == 0) {
return "(isolated)";
} else {
return "<owner disappeared> MEMORY LEAK? ;(";
}
}
inline void ContextStack(const nf7::Context& ctx) noexcept {
for (auto p = ctx.parent(); p; p = p->parent()) {
auto f = ctx.env().GetFile(p->initiator());
const auto path = f? f->abspath().Stringify(): "[missing file]";
ImGui::TextUnformatted(path.c_str());
ImGui::TextDisabled("%s", p->GetDescription().c_str());
}
}
} // namespace nf7::gui

View File

@ -1,252 +0,0 @@
#include "common/gui_file.hh"
#include <cassert>
#include <imgui.h>
#include <imgui_stdlib.h>
#include "common/dir_item.hh"
#include "common/generic_context.hh"
using namespace std::literals;
namespace nf7::gui {
static nf7::DirItem* GetDirItem(nf7::FileHolder& h, nf7::DirItem::Flags f) noexcept
try {
auto& d = h.GetFileOrThrow().interfaceOrThrow<nf7::DirItem>();
return d.flags() & f? &d: nullptr;
} catch (nf7::Exception&) {
return nullptr;
}
bool FileFactory::Update() noexcept {
const auto em = ImGui::GetFontSize();
ImGui::PushItemWidth(16*em);
if (ImGui::IsWindowAppearing()) {
name_ = "new_file";
type_filter_ = "";
}
bool submit = false;
ImGui::InputTextWithHint("##type_filter", "search...", &type_filter_);
if (ImGui::BeginListBox("type", {16*em, 8*em})) {
for (const auto& reg : nf7::File::registry()) {
const auto& t = *reg.second;
const bool match =
t.flags().contains("nf7::File::TypeInfo::Factory") &&
(type_filter_.empty() ||
t.name().find(type_filter_) != std::string::npos) &&
filter_(t);
const bool sel = (type_ == &t);
if (!match) {
if (sel) type_ = nullptr;
continue;
}
constexpr auto kSelectableFlags =
ImGuiSelectableFlags_SpanAllColumns |
ImGuiSelectableFlags_AllowItemOverlap;
if (ImGui::Selectable(t.name().c_str(), sel, kSelectableFlags)) {
type_ = &t;
}
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
t.UpdateTooltip();
ImGui::EndTooltip();
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) {
submit = true;
}
}
}
ImGui::EndListBox();
}
ImGui::PopItemWidth();
ImGui::Spacing();
if (flags_ & kNameInput) {
if (ImGui::IsWindowAppearing()) ImGui::SetKeyboardFocusHere();
ImGui::InputText("name", &name_);
ImGui::Spacing();
}
// input validation
bool err = false;
if (type_ == nullptr) {
ImGui::Bullet(); ImGui::TextUnformatted("type is not selected");
err = true;
}
if (flags_ & kNameInput) {
try {
nf7::File::Path::ValidateTerm(name_);
} catch (Exception& e) {
ImGui::Bullet(); ImGui::Text("invalid name: %s", e.msg().c_str());
err = true;
}
if (flags_ & kNameDupCheck) {
if (owner_->Find(name_)) {
ImGui::Bullet(); ImGui::Text("name duplicated");
err = true;
}
}
}
if (!err) {
if (ImGui::Button("ok")) {
submit = true;
}
if (ImGui::IsItemHovered()) {
const auto path = owner_->abspath().Stringify();
if (flags_ & kNameInput) {
ImGui::SetTooltip(
"create %s as '%s' on '%s'", type_->name().c_str(), name_.c_str(), path.c_str());
} else {
ImGui::SetTooltip("create %s on '%s'", type_->name().c_str(), path.c_str());
}
}
}
return submit && !err;
}
std::string FileHolderEditor::GetDisplayText() const noexcept {
std::string text;
if (holder_->own()) {
text = "[OWN] " + holder_->GetFile()->type().name();
} else if (holder_->ref()) {
text = "[REF] "s + holder_->path().Stringify();
} else if (holder_->empty()) {
text = "(empty)";
} else {
assert(false);
}
return text;
}
void FileHolderEditor::Button(float w, bool small) noexcept {
ImGui::PushID(this);
ImGui::BeginGroup();
const auto text = GetDisplayText();
const bool open = small?
ImGui::SmallButton(text.c_str()):
ImGui::Button(text.c_str(), {w, 0});
if (open) {
ImGui::OpenPopup("FileHolderEmplacePopup_FromButton");
}
if (ImGui::IsItemHovered()) {
ImGui::BeginTooltip();
Tooltip();
ImGui::EndTooltip();
}
ImGui::EndGroup();
UpdateEmplacePopup("FileHolderEmplacePopup_FromButton");
ImGui::PopID();
}
void FileHolderEditor::ButtonWithLabel(const char* name) noexcept {
ImGui::PushID(this);
ImGui::BeginGroup();
Button(ImGui::CalcItemWidth());
ImGui::SameLine(0, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::TextUnformatted(name);
ImGui::EndGroup();
ImGui::PopID();
}
void FileHolderEditor::Tooltip() noexcept {
ImGui::TextUnformatted(GetDisplayText().c_str());
ImGui::Indent();
if (auto a = GetDirItem(*holder_, nf7::DirItem::kTooltip)) {
a->UpdateTooltip();
}
ImGui::Unindent();
}
void FileHolderEditor::ItemWidget(const char* title) noexcept {
if (auto d = GetDirItem(*holder_, nf7::DirItem::kWidget)) {
if (ImGui::CollapsingHeader(title, ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::PushID(d);
ImGui::Indent();
d->UpdateWidget();
ImGui::Unindent();
ImGui::PopID();
}
}
}
void FileHolderEditor::Update() noexcept {
ImGui::PushID(this);
if (std::exchange(open_emplace_, false)) {
ImGui::OpenPopup("FileHolderEmplacePopup_FromMenu");
}
UpdateEmplacePopup("FileHolderEmplacePopup_FromMenu");
ImGui::PopID();
}
void FileHolderEditor::UpdateEmplacePopup(const char* id) noexcept {
if (ImGui::BeginPopup(id)) {
if (ImGui::IsWindowAppearing()) {
if (holder_->ref()) {
type_ = kRef;
path_ = holder_->path().Stringify();
} else {
type_ = kOwn;
path_ = {};
}
}
if (ImGui::RadioButton("own", type_ == kOwn)) { type_ = kOwn; }
ImGui::SameLine();
if (ImGui::RadioButton("ref", type_ == kRef)) { type_ = kRef; }
switch (type_) {
case kOwn:
if (factory_.Update()) {
ImGui::CloseCurrentPopup();
auto& f = holder_->owner();
f.env().ExecMain(
std::make_shared<nf7::GenericContext>(f),
[this]() {
holder_->Emplace(factory_.Create(holder_->owner().env()));
});
}
break;
case kRef:
ImGui::InputText("path", &path_);
bool missing = false;
try {
auto path = nf7::File::Path::Parse(path_);
try {
holder_->owner().ResolveOrThrow(path);
} catch (nf7::File::NotFoundException&) {
missing = true;
}
if (ImGui::Button("apply")) {
ImGui::CloseCurrentPopup();
auto& f = holder_->owner();
f.env().ExecMain(
std::make_shared<nf7::GenericContext>(f),
[this, p = std::move(path)]() mutable {
holder_->Emplace(std::move(p));
});
}
} catch (nf7::Exception& e) {
ImGui::Bullet(); ImGui::TextUnformatted(e.msg().c_str());
}
if (missing) {
ImGui::Bullet(); ImGui::TextUnformatted("the file is missing :(");
}
break;
}
ImGui::EndPopup();
}
}
} // namespace nf7::gui

View File

@ -1,89 +0,0 @@
#pragma once
#include <functional>
#include <memory>
#include <string>
#include <utility>
#include "nf7.hh"
#include "common/file_base.hh"
#include "common/file_holder.hh"
namespace nf7::gui {
class FileFactory final {
public:
enum Flag : uint8_t {
kNameInput = 1 << 0,
kNameDupCheck = 1 << 1,
};
using Flags = uint8_t;
using Filter = std::function<bool(const nf7::File::TypeInfo&)>;
FileFactory(nf7::File& owner, Filter&& filter, Flags flags = 0) noexcept :
owner_(&owner), filter_(std::move(filter)), flags_(flags) {
}
FileFactory(const FileFactory&) = delete;
FileFactory(FileFactory&&) = default;
FileFactory& operator=(const FileFactory&) = delete;
FileFactory& operator=(FileFactory&&) = delete;
bool Update() noexcept;
std::unique_ptr<nf7::File> Create(nf7::Env& env) noexcept {
return type_? type_->Create(env): nullptr;
}
const std::string& name() const noexcept { return name_; }
const nf7::File::TypeInfo& type() const noexcept { return *type_; }
private:
nf7::File* const owner_;
const Filter filter_;
const Flags flags_;
std::string name_;
const nf7::File::TypeInfo* type_ = nullptr;
std::string type_filter_;
};
class FileHolderEditor final : public nf7::FileBase::Feature {
public:
enum Type {
kOwn,
kRef,
};
FileHolderEditor(nf7::FileBase& f, nf7::FileHolder& h, FileFactory::Filter&& filter) noexcept :
nf7::FileBase::Feature(f),
holder_(&h), factory_(h.owner(), std::move(filter)) {
}
FileHolderEditor(const FileHolderEditor&) = delete;
FileHolderEditor(FileHolderEditor&&) = default;
FileHolderEditor& operator=(const FileHolderEditor&) = delete;
FileHolderEditor& operator=(FileHolderEditor&&) = delete;
std::string GetDisplayText() const noexcept;
void Button(float w = 0, bool = false) noexcept;
void SmallButton() noexcept { Button(0, true); }
void ButtonWithLabel(const char* id) noexcept;
void Tooltip() noexcept;
void ItemWidget(const char*) noexcept;
void Update() noexcept override;
private:
nf7::FileHolder* const holder_;
bool open_emplace_ = false;
Type type_;
FileFactory factory_;
std::string path_;
void UpdateEmplacePopup(const char*) noexcept;
};
} // namespace nf7::gui

View File

@ -1,66 +0,0 @@
#pragma once
#include <algorithm>
#include <imgui.h>
#include <imgui_internal.h>
#include <ImNodes.h>
namespace nf7::gui {
inline void NodeSocket() noexcept {
auto win = ImGui::GetCurrentWindow();
const auto em = ImGui::GetFontSize();
const auto lh = std::max(win->DC.CurrLineSize.y, em);
const auto rad = em/2 / ImNodes::CanvasState().Zoom;
const auto sz = ImVec2(rad*2, lh);
const auto pos = ImGui::GetCursorScreenPos() + sz/2;
auto dlist = ImGui::GetWindowDrawList();
dlist->AddCircleFilled(
pos, rad, IM_COL32(100, 100, 100, 100));
dlist->AddCircleFilled(
pos, rad*.8f, IM_COL32(200, 200, 200, 200));
ImGui::Dummy(sz);
}
inline void NodeInputSockets(std::span<const std::string> names) noexcept {
ImGui::BeginGroup();
for (auto& name : names) {
if (ImNodes::BeginInputSlot(name.c_str(), 1)) {
ImGui::AlignTextToFramePadding();
nf7::gui::NodeSocket();
ImGui::SameLine();
ImGui::TextUnformatted(name.c_str());
ImNodes::EndSlot();
}
}
ImGui::EndGroup();
}
inline void NodeOutputSockets(std::span<const std::string> names) noexcept {
float maxw = 0;
for (auto& name : names) {
maxw = std::max(maxw, ImGui::CalcTextSize(name.c_str()).x);
}
ImGui::BeginGroup();
for (auto& name : names) {
const auto w = ImGui::CalcTextSize(name.c_str()).x;
ImGui::SetCursorPosX(ImGui::GetCursorPosX()+maxw-w);
if (ImNodes::BeginOutputSlot(name.c_str(), 1)) {
ImGui::AlignTextToFramePadding();
ImGui::TextUnformatted(name.c_str());
ImGui::SameLine();
nf7::gui::NodeSocket();
ImNodes::EndSlot();
}
}
ImGui::EndGroup();
}
} // namespacce nf7::gui

View File

@ -21,9 +21,8 @@
#include "common/file_base.hh"
#include "common/generic_type_info.hh"
#include "common/generic_memento.hh"
#include "common/gui.hh"
#include "common/gui_config.hh"
#include "common/gui_file.hh"
#include "common/gui_node.hh"
#include "common/life.hh"
#include "common/logger_ref.hh"
#include "common/luajit_nfile_importer.hh"

View File

@ -19,7 +19,7 @@
#include "common/dir_item.hh"
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gui_node.hh"
#include "common/gui.hh"
#include "common/gui_value.hh"
#include "common/life.hh"
#include "common/node.hh"

View File

@ -10,6 +10,7 @@
#include <vector>
#include <imgui.h>
#include <imgui_internal.h>
#include <imgui_stdlib.h>
#include <ImNodes.h>
@ -28,10 +29,8 @@
#include "common/generic_context.hh"
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gui.hh"
#include "common/gui_config.hh"
#include "common/gui_context.hh"
#include "common/gui_file.hh"
#include "common/gui_node.hh"
#include "common/gui_window.hh"
#include "common/life.hh"
#include "common/memento.hh"
@ -1095,6 +1094,11 @@ void Network::NetworkEditor() noexcept {
ItemAdder(pos);
ImGui::EndMenu();
}
if (ImGui::MenuItem("add terminal")) {
ExecAddItem(
std::make_unique<Item>(next_++, std::make_unique<Terminal>(env())),
pos);
}
ImGui::Separator();
if (ImGui::MenuItem("undo", nullptr, false, !!history_.prev())) {
UnDo();

View File

@ -21,8 +21,8 @@
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/generic_watcher.hh"
#include "common/gui.hh"
#include "common/gui_dnd.hh"
#include "common/gui_node.hh"
#include "common/life.hh"
#include "common/logger_ref.hh"
#include "common/memento.hh"

View File

@ -16,7 +16,6 @@
#include "common/generic_context.hh"
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gui_file.hh"
#include "common/life.hh"
#include "common/node.hh"
#include "common/ptr_selector.hh"
@ -191,11 +190,7 @@ try {
ssla_ = nullptr;
la_ = nullptr;
}
} catch (nf7::ExpiredException&) {
ss->Finish();
} catch (nf7::FileHolder::EmptyException&) {
ss->Finish();
} catch (nf7::File::NotImplementedException&) {
} catch (nf7::Exception&) {
ss->Finish();
}
void Call::Lambda::Abort() noexcept {

View File

@ -25,8 +25,7 @@
#include "common/file_base.hh"
#include "common/generic_context.hh"
#include "common/generic_type_info.hh"
#include "common/gui_context.hh"
#include "common/gui_file.hh"
#include "common/gui.hh"
#include "common/gui_timeline.hh"
#include "common/gui_window.hh"
#include "common/life.hh"

View File

@ -14,7 +14,7 @@
#include "common/generic_context.hh"
#include "common/generic_type_info.hh"
#include "common/gui_node.hh"
#include "common/gui.hh"
#include "common/node.hh"
#include "common/ptr_selector.hh"
#include "common/yas_std_atomic.hh"

View File

@ -7,6 +7,8 @@
#include <imgui.h>
#include <imgui_internal.h>
#include <ImNodes.h>
#include <yas/serialize.hpp>
#include <yas/types/utility/usertype.hpp>
@ -15,7 +17,7 @@
#include "common/dir_item.hh"
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gui_node.hh"
#include "common/gui.hh"
#include "common/life.hh"
#include "common/node.hh"
#include "common/ptr_selector.hh"

View File

@ -24,7 +24,7 @@
#include "common/generic_memento.hh"
#include "common/generic_type_info.hh"
#include "common/gui_config.hh"
#include "common/gui_node.hh"
#include "common/gui.hh"
#include "common/gui_window.hh"
#include "common/life.hh"
#include "common/logger_ref.hh"