Files
nostalgia/src/olympic/studio/modlib/src/imguiutil.cpp

198 lines
4.9 KiB
C++

/*
* Copyright 2016 - 2024 Gary Talent (gary@drinkingtea.net). All rights reserved.
*/
#include <imgui.h>
#include <turbine/gfx.hpp>
#include <studio/imguiutil.hpp>
namespace studio::ig {
ChildStackItem::ChildStackItem(ox::CStringViewCR id, ImVec2 const&sz) noexcept {
ImGui::BeginChild(id.c_str(), sz);
}
ChildStackItem::~ChildStackItem() noexcept {
ImGui::EndChild();
}
IDStackItem::IDStackItem(int id) noexcept {
ImGui::PushID(id);
}
IDStackItem::IDStackItem(const char *id) noexcept {
ImGui::PushID(id);
}
IDStackItem::IDStackItem(ox::CStringViewCR id) noexcept: IDStackItem(id.c_str()) {}
IDStackItem::~IDStackItem() noexcept {
ImGui::PopID();
}
IndentStackItem::IndentStackItem(float indent) noexcept: m_indent(indent) {
ImGui::Indent(m_indent);
}
IndentStackItem::~IndentStackItem() noexcept {
ImGui::Indent(-m_indent);
}
void centerNextWindow(turbine::Context &ctx) noexcept {
auto const sz = turbine::getScreenSize(ctx);
auto const screenW = static_cast<float>(sz.width);
auto const screenH = static_cast<float>(sz.height);
auto const mod = ImGui::GetWindowDpiScale() * 2;
ImGui::SetNextWindowPos(ImVec2(screenW / mod, screenH / mod), ImGuiCond_Always, ImVec2(0.5f, 0.5f));
}
bool PushButton(ox::CStringViewCR lbl, ImVec2 const&btnSz) noexcept {
return ImGui::Button(lbl.c_str(), btnSz);
}
PopupResponse PopupControlsOkCancel(float popupWidth, bool &popupOpen) {
auto out = PopupResponse::None;
constexpr auto btnSz = ImVec2{50, BtnSz.y};
ImGui::Separator();
ImGui::SetCursorPosX(popupWidth - 118);
if (ImGui::Button("OK", btnSz)) {
ImGui::CloseCurrentPopup();
popupOpen = false;
out = PopupResponse::OK;
}
ImGui::SameLine();
if (ImGui::IsKeyDown(ImGuiKey_Escape) || ImGui::Button("Cancel", btnSz)) {
ImGui::CloseCurrentPopup();
popupOpen = false;
out = PopupResponse::Cancel;
}
return out;
}
PopupResponse PopupControlsOkCancel(bool &popupOpen) {
return PopupControlsOkCancel(ImGui::GetContentRegionAvail().x + 17, popupOpen);
}
bool BeginPopup(turbine::Context &ctx, ox::CStringViewCR popupName, bool &show, ImVec2 const&sz) {
constexpr auto modalFlags = ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize;
centerNextWindow(ctx);
ImGui::OpenPopup(popupName.c_str());
ImGui::SetNextWindowSize(sz);
return ImGui::BeginPopupModal(popupName.c_str(), &show, modalFlags);
}
bool ComboBox(
ox::CStringView lbl,
ox::Span<const ox::String> list,
size_t &selectedIdx) noexcept {
bool out{};
auto const first = selectedIdx < list.size() ? list[selectedIdx].c_str() : "";
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
for (auto i = 0u; i < list.size(); ++i) {
const auto selected = (selectedIdx == i);
if (ImGui::Selectable(list[i].c_str(), selected) && selectedIdx != i) {
selectedIdx = i;
out = true;
}
}
ImGui::EndCombo();
}
return out;
}
bool ComboBox(
ox::CStringViewCR lbl,
std::function<ox::CStringView(size_t)> const&f,
size_t strCnt,
size_t &selectedIdx) noexcept {
bool out{};
auto const first = selectedIdx < strCnt ? f(selectedIdx).c_str() : "";
if (ImGui::BeginCombo(lbl.c_str(), first, 0)) {
for (auto i = 0u; i < strCnt; ++i) {
const auto selected = (selectedIdx == i);
if (ImGui::Selectable(f(i).c_str(), selected) && selectedIdx != i) {
selectedIdx = i;
out = true;
}
}
ImGui::EndCombo();
}
return out;
}
bool FileComboBox(
ox::CStringViewCR lbl,
StudioContext &sctx,
ox::StringViewCR fileExt,
size_t &selectedIdx) noexcept {
auto const&list = sctx.project->fileList(fileExt);
return ComboBox(lbl, list, selectedIdx);
}
bool ListBox(
ox::CStringViewCR name,
std::function<ox::CStringView(size_t)> const&f,
size_t strCnt,
size_t &selIdx) noexcept {
auto out = false;
if (ImGui::BeginListBox(name.c_str())) {
for (auto i = 0u; i < strCnt; ++i) {
auto str = f(i);
ig::IDStackItem const idStackItem2(static_cast<int>(i));
if (ImGui::Selectable(str.c_str(), selIdx == i)) {
if (i != selIdx) {
selIdx = i;
out = true;
}
}
}
ImGui::EndListBox();
}
return out;
}
bool ListBox(ox::CStringViewCR name, ox::SpanView<ox::String> const&list, size_t &selIdx) noexcept {
return ListBox(name, [list](size_t i) -> ox::CStringView {
return list[i];
}, list.size(), selIdx);
}
FilePicker::FilePicker(
StudioContext &sctx,
ox::StringParam title,
ox::StringParam fileExt,
ImVec2 const&size) noexcept:
m_sctx(sctx),
m_title(std::move(title)),
m_fileExt(std::move(fileExt)),
m_size(size) {
}
void FilePicker::draw() noexcept {
if (!m_show) {
return;
}
auto constexpr popupSz = ImVec2{450.f, 0};
IDStackItem const idStackItem(m_title);
if (BeginPopup(m_sctx.tctx, m_title, m_show, popupSz)) {
auto const&list = m_sctx.project->fileList(m_fileExt);
size_t selIdx{};
ComboBox(m_title, list, selIdx);
if (PopupControlsOkCancel(popupSz.x, m_show) == ig::PopupResponse::OK) {
filePicked.emit(list[selIdx]);
}
ImGui::EndPopup();
}
}
void FilePicker::show() noexcept {
m_show = true;
}
}