46 std::function<void(
const std::string&)>
callback;
79 if (m_impl->messageBox && m_impl->messageBox->open) {
83 if (m_impl->inputDialog && m_impl->inputDialog->open) {
87 if (!m_impl->progressDialogs.empty()) {
88 RenderProgressDialogs();
91 if (m_impl->listDialog && m_impl->listDialog->open) {
98 m_impl->messageBox = std::make_unique<MessageBoxState>();
99 m_impl->messageBox->title = title;
100 m_impl->messageBox->message = message;
101 m_impl->messageBox->buttons = buttons;
102 m_impl->messageBox->icon = icon;
103 m_impl->messageBox->callback = callback;
104 m_impl->messageBox->open =
true;
108 const std::string& defaultValue, std::function<
void(
const std::string&)> callback) {
109 m_impl->inputDialog = std::make_unique<InputDialogState>();
110 m_impl->inputDialog->title = title;
111 m_impl->inputDialog->prompt = prompt;
112 m_impl->inputDialog->callback = callback;
113 m_impl->inputDialog->open =
true;
116 auto& buffer = m_impl->inputDialog->inputBuffer;
117 strncpy(std::data(buffer), defaultValue.c_str(), std::size(buffer) - 1);
119 buffer[std::size(buffer) - 1] =
'\0';
123 const int id = m_impl->nextProgressId++;
130 m_impl->progressDialogs[id] = state;
135 auto it = m_impl->progressDialogs.find(dialogId);
136 if (it != m_impl->progressDialogs.end()) {
137 it->second.progress = std::clamp(progress, 0.0f, 1.0f);
138 if (!message.empty()) {
139 it->second.message = message;
145 m_impl->progressDialogs.erase(dialogId);
149 std::function<
void(
int)> callback) {
150 m_impl->listDialog = std::make_unique<ListDialogState>();
151 m_impl->listDialog->title = title;
152 m_impl->listDialog->items = items;
153 m_impl->listDialog->selectedIndex = -1;
154 m_impl->listDialog->callback = callback;
155 m_impl->listDialog->open =
true;
159 std::function<
void(
bool)> callback) {
169 return (m_impl->messageBox && m_impl->messageBox->open) || (m_impl->inputDialog && m_impl->inputDialog->open) ||
170 !m_impl->progressDialogs.empty() || (m_impl->listDialog && m_impl->listDialog->open);
174 m_impl->messageBox.reset();
175 m_impl->inputDialog.reset();
176 m_impl->listDialog.reset();
177 m_impl->progressDialogs.clear();
182void DialogManager::RenderMessageBox() {
183 auto& mb = m_impl->messageBox;
184 if (!mb || !mb->open) {
188 ImGui::OpenPopup(mb->title.c_str());
189 const ImVec2 center = ImGui::GetMainViewport()->GetCenter();
190 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
194 if (ImGui::BeginPopupModal(mb->title.c_str(), &mb->open,
195 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
197 const char* iconText =
nullptr;
198 ImVec4 iconColor = ImVec4(1, 1, 1, 1);
202 iconColor = ImVec4(0.2f, 0.6f, 1.0f, 1.0f);
206 iconColor = ImVec4(1.0f, 0.8f, 0.0f, 1.0f);
210 iconColor = ImVec4(1.0f, 0.2f, 0.2f, 1.0f);
214 iconColor = ImVec4(0.4f, 0.8f, 0.4f, 1.0f);
218 ImGui::TextColored(iconColor,
"%s", iconText);
220 ImGui::TextWrapped(
"%s", mb->message.c_str());
227 const float buttonWidth = 100.0f;
228 switch (mb->buttons) {
230 if (ImGui::Button(loc.Tr(
"button.ok").c_str(), ImVec2(buttonWidth, 0))) {
237 if (ImGui::Button(loc.Tr(
"button.ok").c_str(), ImVec2(buttonWidth, 0))) {
242 if (ImGui::Button(loc.Tr(
"button.cancel").c_str(), ImVec2(buttonWidth, 0))) {
249 if (ImGui::Button(loc.Tr(
"button.yes").c_str(), ImVec2(buttonWidth, 0))) {
254 if (ImGui::Button(loc.Tr(
"button.no").c_str(), ImVec2(buttonWidth, 0))) {
261 if (ImGui::Button(loc.Tr(
"button.yes").c_str(), ImVec2(buttonWidth, 0))) {
266 if (ImGui::Button(loc.Tr(
"button.no").c_str(), ImVec2(buttonWidth, 0))) {
271 if (ImGui::Button(loc.Tr(
"button.cancel").c_str(), ImVec2(buttonWidth, 0))) {
278 if (ImGui::Button(loc.Tr(
"button.retry").c_str(), ImVec2(buttonWidth, 0))) {
283 if (ImGui::Button(loc.Tr(
"button.cancel").c_str(), ImVec2(buttonWidth, 0))) {
296 mb->callback(result);
298 m_impl->messageBox.reset();
302void DialogManager::RenderInputDialog() {
303 auto&
id = m_impl->inputDialog;
304 if (!
id || !id->open) {
308 ImGui::OpenPopup(id->title.c_str());
309 const ImVec2 center = ImGui::GetMainViewport()->GetCenter();
310 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
313 bool submitted =
false;
315 if (ImGui::BeginPopupModal(id->title.c_str(), &id->open,
316 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
317 ImGui::Text(
"%s", id->prompt.c_str());
320 ImGui::SetNextItemWidth(300.0f);
321 if (ImGui::InputText(
"##input", id->inputBuffer.data(), id->inputBuffer.size(),
322 ImGuiInputTextFlags_EnterReturnsTrue)) {
324 result =
id->inputBuffer.data();
333 if (ImGui::Button(loc.Tr(
"button.ok").c_str(), ImVec2(100, 0))) {
335 result =
id->inputBuffer.data();
339 if (ImGui::Button(loc.Tr(
"button.cancel").c_str(), ImVec2(100, 0))) {
350 id->callback(submitted ? result :
"");
352 m_impl->inputDialog.reset();
356void DialogManager::RenderProgressDialogs() {
357 for (
auto it = m_impl->progressDialogs.begin(); it != m_impl->progressDialogs.end();) {
358 auto& pd = it->second;
361 it = m_impl->progressDialogs.erase(it);
365 const std::string popupId = pd.title +
"##" + std::to_string(pd.id);
366 ImGui::OpenPopup(popupId.c_str());
367 const ImVec2 center = ImGui::GetMainViewport()->GetCenter();
368 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
370 if (ImGui::BeginPopupModal(popupId.c_str(),
nullptr,
371 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
372 if (!pd.message.empty()) {
373 ImGui::Text(
"%s", pd.message.c_str());
377 ImGui::ProgressBar(pd.progress, ImVec2(300, 0));
381 ImGui::Text(
"%.1f%%", pd.progress * 100.0f);
390void DialogManager::RenderListDialog() {
391 auto& ld = m_impl->listDialog;
392 if (!ld || !ld->open) {
396 ImGui::OpenPopup(ld->title.c_str());
397 const ImVec2 center = ImGui::GetMainViewport()->GetCenter();
398 ImGui::SetNextWindowPos(center, ImGuiCond_Appearing, ImVec2(0.5f, 0.5f));
400 int selectedIndex = -1;
401 bool confirmed =
false;
403 if (ImGui::BeginPopupModal(ld->title.c_str(), &ld->open,
404 ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove)) {
405 ImGui::BeginChild(
"ListBox", ImVec2(300, 200), ImGuiChildFlags_Border);
407 const auto itemCount =
static_cast<int>(ld->items.size());
408 for (
int i = 0; i < itemCount; ++i) {
409 const bool isSelected = (i == ld->selectedIndex);
410 if (ImGui::Selectable(ld->items[
static_cast<size_t>(i)].c_str(), isSelected,
411 ImGuiSelectableFlags_AllowDoubleClick)) {
412 ld->selectedIndex = i;
413 if (ImGui::IsMouseDoubleClicked(0)) {
415 selectedIndex = ld->selectedIndex;
428 if (ImGui::Button(loc.Tr(
"button.ok").c_str(), ImVec2(100, 0)) && ld->selectedIndex >= 0) {
430 selectedIndex = ld->selectedIndex;
434 if (ImGui::Button(loc.Tr(
"button.cancel").c_str(), ImVec2(100, 0))) {
444 ld->callback(confirmed ? selectedIndex : -1);
446 m_impl->listDialog.reset();