198 lines
4.9 KiB
C++
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;
|
|
}
|
|
|
|
}
|