#include "fiko/ui/form.hpp" #include #include #include "fiko/ui/bilesen.hpp" #include "fiko/ui/tema.hpp" #include "imgui_internal.h" namespace fiko::ui { namespace { // Etiket kolonu genişliği: verilmezse içerik genişliğinin %40'ı (70..220 kenetli). float etiketKolonu(float istek) { if (istek > 0.0f) return istek; const float w = ImGui::GetContentRegionAvail().x * 0.40f; return ImClamp(w, 70.0f, 220.0f); } // Bir hap/şerit için tema durum rengi. ImVec4 durumRengi(int tip) { const Tema& t = tema(); switch (tip) { case 1: return t.basari; case 2: return t.uyari; case 3: return t.hata; default: return t.vurgu; } } const char* durumIkon(int tip) { switch (tip) { case 1: return "✔"; case 2: return "⚠"; case 3: return "✕"; default: return "ⓘ"; } } // sliderYazilabilir durumu (aynı anda tek alan yazı kipinde olabilir → global yeterli). ImGuiID g_yaziId = 0; // yazı kipindeki alan (0 = yok) bool g_yaziOdakla = false; // yazı kipine yeni girildi → bu karede odak ver ImGuiID g_aktifId = 0; // slider'ı en son AKTİF eden alan float g_aktifOnceki = 0.0f; // o aktifleşmenin TIK ÖNCESİ değeri (sıçramayı geri almak için) } // namespace void alan(const char* etiket, float etiketGen) { const float lw = etiketKolonu(etiketGen); const float bosluk = ImGui::GetStyle().ItemInnerSpacing.x; const float x0 = ImGui::GetCursorPosX(); ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted(etiket); ImGui::SameLine(0.0f, 0.0f); // Etiket kolondan genişse widget'ı etiketin ARDINA koy (üst üste binmeyi önle); // değilse sabit kolona hizala. const float hedef = x0 + lw + bosluk; const float simdi = ImGui::GetCursorPosX(); // etiket bitişi ImGui::SetCursorPosX(simdi > hedef ? simdi + bosluk : hedef); ImGui::SetNextItemWidth(-FLT_MIN); // kalan tam genişlik } bool sliderYazilabilir(const char* kimlik, float* deger, float min, float max, const char* bicim) { const ImGuiID id = ImGui::GetID(kimlik); if (g_yaziId == id) { // ---- YAZI KİPİ ---- if (g_yaziOdakla) { ImGui::SetKeyboardFocusHere(); // yalnız ilk karede (yoksa imleç oynatılamaz) g_yaziOdakla = false; } const bool enter = ImGui::InputFloat(kimlik, deger, 0.0f, 0.0f, bicim, ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_AutoSelectAll); const bool duzenlendi = ImGui::IsItemDeactivatedAfterEdit(); if (enter || ImGui::IsItemDeactivated()) { // Enter ya da odak kaybı → slider'a dön *deger = ImClamp(*deger, min, max); g_yaziId = 0; } return enter || duzenlendi; } // ---- SLIDER KİPİ ---- const float tikOncesi = *deger; // bu karenin slider çağrısından ÖNCEki değer const bool degisti = ImGui::SliderFloat(kimlik, deger, min, max, bicim); if (ImGui::IsItemActivated()) { // ilk tık: sıçramadan önceki değeri sakla g_aktifId = id; g_aktifOnceki = tikOncesi; } if (ImGui::IsItemHovered() && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { if (g_aktifId == id) *deger = g_aktifOnceki; // ilk tıkın sıçrattığı değeri GERİ AL g_yaziId = id; g_yaziOdakla = true; ImGui::ClearActiveID(); // slider sürükleme yakalamasını bıraksın return true; // geri alınan değer uygulansın } return degisti; } bool anahtarSatiri(const char* etiket, bool* deger) { ImGui::AlignTextToFramePadding(); ImGui::TextUnformatted(etiket); const float sw = ImGui::GetFrameHeight() * 0.85f * 1.9f; // anahtar() genişliği ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - sw); ImGui::PushID(etiket); const bool d = anahtar("", deger); ImGui::PopID(); return d; } void istatistikSatiri(const char* etiket, const char* deger, const char* birim) { const Tema& t = tema(); ImGui::AlignTextToFramePadding(); ImGui::TextColored(t.metinSoluk, "%s", etiket); char buf[96]; if (birim && *birim) std::snprintf(buf, sizeof(buf), "%s %s", deger, birim); else std::snprintf(buf, sizeof(buf), "%s", deger); const float tw = ImGui::CalcTextSize(buf).x; ImGui::SameLine(); ImGui::SetCursorPosX(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - tw); ImGui::TextColored(t.metin, "%s", buf); } void istatistikSatiri(const char* etiket, float deger, const char* birim, const char* fmt) { char buf[48]; std::snprintf(buf, sizeof(buf), fmt, deger); istatistikSatiri(etiket, buf, birim); } void bilgiSeridi(int tip, const char* metin) { const ImVec4 renk = durumRengi(tip); ImDrawList* dl = ImGui::GetWindowDrawList(); const ImGuiStyle& st = ImGui::GetStyle(); const float w = ImGui::GetContentRegionAvail().x; const ImVec2 p0 = ImGui::GetCursorScreenPos(); const char* ik = durumIkon(tip); const float ikW = ImGui::CalcTextSize(ik).x + st.ItemInnerSpacing.x * 2.0f; const float metinW = ImClamp(w - ikW - st.FramePadding.x * 2.0f, 10.0f, w); const ImVec2 ts = ImGui::CalcTextSize(metin, nullptr, false, metinW); const float yuk = ts.y + st.FramePadding.y * 2.0f; const ImVec2 p1{p0.x + w, p0.y + yuk}; dl->AddRectFilled(p0, p1, u32(renk, 0.12f), tema().yuvarlak); dl->AddLine({p0.x, p0.y}, {p0.x, p1.y}, u32(renk, 0.9f), 2.5f); // sol vurgu şeridi ImGui::Dummy({w, yuk}); // İçerik: ikon + sarmalı metin ImGui::SetCursorScreenPos({p0.x + ikW * 0.35f + 3.0f, p0.y + st.FramePadding.y}); ImGui::TextColored(renk, "%s", ik); ImGui::SameLine(0.0f, st.ItemInnerSpacing.x); ImGui::PushTextWrapPos(p0.x + ikW + metinW); ImGui::TextColored(tema().metin, "%s", metin); ImGui::PopTextWrapPos(); } void ikonSeritBasla(const char* kimlik) { const Tema& t = tema(); ImGui::PushID(kimlik); ImGui::PushStyleColor(ImGuiCol_ChildBg, u32(t.panel, 0.6f)); ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, t.yuvarlak); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2{3.0f, 3.0f}); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2{4.0f, 3.0f}); // Yukseklik ikonButon'u TAM sigdirmali: buton (FrameHeight+6) + ust/alt WindowPadding // (2×3). Eskiden FrameHeight+6 idi → butonun alt 6 pikseli kirpiliyordu. ImGui::BeginChild("##serit", ImVec2{0, ImGui::GetFrameHeight() + 12.0f}, true, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse); } void ikonSeritBitir() { ImGui::EndChild(); ImGui::PopStyleVar(3); ImGui::PopStyleColor(); ImGui::PopID(); } } // namespace fiko::ui