#include "ui.hpp" #include "imgui.h" #include "locales.hpp" #include "strops.hpp" static float toast_timer = 0.0f; static const char* toast_msg = nullptr; void ui_helper_show_toast(const char* msg) { toast_msg = msg; toast_timer = 3.0f; } void ui_helper_draw_toasts() { if (toast_timer > 0.0f && toast_msg) { toast_timer -= ImGui::GetIO().DeltaTime; const float pad = 10.0f; const ImVec2 window_pos = ImVec2( ImGui::GetIO().DisplaySize.x - pad, ImGui::GetIO().DisplaySize.y - pad ); const ImVec2 window_pos_pivot = ImVec2(1.0f, 1.0f); ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot); ImGui::SetNextWindowBgAlpha(0.85f); // semi-transparent ImGuiWindowFlags flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav; if (ImGui::Begin("##Toast", nullptr, flags)) { ImGui::TextUnformatted(toast_msg); } ImGui::End(); } } void ui_helper_draw_required_tag() { ImDrawList* draw_list = ImGui::GetWindowDrawList(); const char* text = localize("form.required"); ImVec2 text_pos = ImGui::GetCursorScreenPos(); ImVec2 text_size = ImGui::CalcTextSize(text); text_pos.y += text_size.y/4.0f; ImVec4 bg_color = ImVec4(0.9f, 0.235f, 0.235f, 0.4f); // Red background ImVec4 text_color = ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White text float rounding = 2.0f; float padding = 2.0f; // Background rectangle ImVec2 bg_min = ImVec2(text_pos.x - padding, text_pos.y - padding); ImVec2 bg_max = ImVec2(text_pos.x + text_size.x + padding, text_pos.y + text_size.y + padding); draw_list->AddRectFilled(bg_min, bg_max, ImColor(bg_color), rounding); // Foreground text ImGui::PushStyleColor(ImGuiCol_Text, text_color); ImGui::TextUnformatted(text); ImGui::PopStyleColor(); } int ui_helper_TextInputWithAutocomplete(const char* label, const char* hint, char* buffer, size_t buf_size, char* suggestions[], int suggestion_count) { int result = -1; static bool is_open = false; ImGui::InputTextWithHint(label, hint, buffer, buf_size); if (buffer[0] == '\0' && is_open) is_open = false; if (suggestion_count == 0 && is_open) is_open = false; bool is_active = ImGui::IsItemActive(); if (is_active && buffer[0] != '\0' && suggestion_count > 0) { is_open = true; } if (is_open) { ImGui::BeginChild("autocomplete_popup", ImVec2(0, 10.0f + suggestion_count*23.0f), true); { ImVec2 win_pos = ImGui::GetWindowPos(); ImVec2 win_size = ImGui::GetWindowSize(); ImVec2 mouse_pos = ImGui::GetMousePos(); bool mouse_clicked_outside = !is_active && ImGui::IsMouseClicked(0) && (mouse_pos.x < win_pos.x || mouse_pos.x > win_pos.x + win_size.x || mouse_pos.y < win_pos.y || mouse_pos.y > win_pos.y + win_size.y); if (mouse_clicked_outside) is_open = false; for (int i = 0; i < suggestion_count; ++i) { if (ImGui::Selectable(suggestions[i])) { // Copy selected suggestion to buffer strops_copy(buffer, suggestions[i], buf_size); buffer[buf_size - 1] = '\0'; result = i; is_open = false; } } ImGui::EndChild(); } } return result; }