diff --git a/src/core/Types.h b/src/core/Types.h index 6faf27d..5b21f5d 100644 --- a/src/core/Types.h +++ b/src/core/Types.h @@ -2,6 +2,8 @@ #include #include +#include +#include #include #include #include @@ -85,6 +87,28 @@ inline const char* inputFormatName(InputFormat f) { } } +// ── Formatting helpers ─────────────────────────────────────────────────────── + +// Format frequency into buf with fixed-width numeric field per unit range. +inline int fmtFreq(char* buf, size_t sz, double freq) { + if (std::abs(freq) >= 1e6) + return std::snprintf(buf, sz, "% 10.6f MHz", freq / 1e6); + else if (std::abs(freq) >= 1e3) + return std::snprintf(buf, sz, "% 7.3f kHz", freq / 1e3); + else + return std::snprintf(buf, sz, "% 7.1f Hz", freq); +} + +// Format "label: freq, dB" into buf for sidebar display (fixed-width freq + dB). +inline int fmtFreqDB(char* buf, size_t sz, const char* label, double freq, float dB) { + if (std::abs(freq) >= 1e6) + return std::snprintf(buf, sz, "%s: % 10.6f MHz %6.1f dB", label, freq / 1e6, dB); + else if (std::abs(freq) >= 1e3) + return std::snprintf(buf, sz, "%s: % 7.3f kHz %6.1f dB", label, freq / 1e3, dB); + else + return std::snprintf(buf, sz, "%s: % 7.1f Hz %6.1f dB", label, freq, dB); +} + // ── Spectrum data ──────────────────────────────────────────────────────────── struct SpectrumLine { diff --git a/src/ui/Application.cpp b/src/ui/Application.cpp index f4d6012..b36266d 100644 --- a/src/ui/Application.cpp +++ b/src/ui/Application.cpp @@ -460,13 +460,7 @@ void Application::render() { // Frequency label at top of waterfall char freqLabel[48]; - double hf = cursors_.hover.freq; - if (std::abs(hf) >= 1e6) - std::snprintf(freqLabel, sizeof(freqLabel), "%.6f MHz", hf / 1e6); - else if (std::abs(hf) >= 1e3) - std::snprintf(freqLabel, sizeof(freqLabel), "%.3f kHz", hf / 1e3); - else - std::snprintf(freqLabel, sizeof(freqLabel), "%.1f Hz", hf); + fmtFreq(freqLabel, sizeof(freqLabel), cursors_.hover.freq); ImVec2 tSz = ImGui::CalcTextSize(freqLabel); float lx = std::min(hx + 4, wfPosX_ + wfSizeX_ - tSz.x - 4); @@ -572,7 +566,8 @@ void Application::renderControlPanel() { if (ImGui::CollapsingHeader("FFT", ImGuiTreeNodeFlags_DefaultOpen)) { const char* sizeNames[] = {"256", "512", "1024", "2048", "4096", "8192", "16384", "32768", "65536"}; - ImGui::SetNextItemWidth(-1); + float halfW = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f; + ImGui::SetNextItemWidth(halfW); if (ImGui::Combo("##fftsize", &fftSizeIdx_, sizeNames, kNumFFTSizes)) { settings_.fftSize = kFFTSizes[fftSizeIdx_]; updateAnalyzerSettings(); @@ -580,9 +575,10 @@ void Application::renderControlPanel() { } if (ImGui::IsItemHovered()) ImGui::SetTooltip("FFT Size"); + ImGui::SameLine(); const char* winNames[] = {"Rectangular", "Hann", "Hamming", "Blackman", "Blackman-Harris", "Kaiser", "Flat Top"}; - ImGui::SetNextItemWidth(-1); + ImGui::SetNextItemWidth(halfW); if (ImGui::Combo("##window", &windowIdx_, winNames, static_cast(WindowType::Count))) { settings_.window = static_cast(windowIdx_); @@ -621,7 +617,7 @@ void Application::renderControlPanel() { ImVec2 rMax = ImGui::GetItemRectMax(); float tx = rMin.x + ((rMax.x - rMin.x) - textSize.x) * 0.5f; float ty = rMin.y + ((rMax.y - rMin.y) - textSize.y) * 0.5f; - ImGui::GetForegroundDrawList()->AddText({tx, ty}, IM_COL32(255, 255, 255, 220), overlayText); + ImGui::GetWindowDrawList()->AddText({tx, ty}, IM_COL32(255, 255, 255, 220), overlayText); if (ImGui::IsItemHovered()) ImGui::SetTooltip("Overlap"); } } @@ -635,6 +631,7 @@ void Application::renderControlPanel() { if (ImGui::IsItemHovered()) ImGui::SetTooltip("dB Range (min / max)"); ImGui::Checkbox("Peak Hold", &specDisplay_.peakHoldEnable); + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Draws a \"maximum\" line in the spectrogram"); if (specDisplay_.peakHoldEnable) { ImGui::SameLine(); ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x @@ -669,6 +666,7 @@ void Application::renderControlPanel() { viewLo_ = 0.0f; viewHi_ = 0.5f; } + if (ImGui::IsItemHovered()) ImGui::SetTooltip("Reset to 2x zoom"); } } @@ -829,12 +827,11 @@ void Application::renderControlPanel() { int pkCh2 = std::clamp(waterfallChannel_, 0, analyzer_.numSpectra() - 1); auto [peakBin, peakDB] = analyzer_.findPeak(pkCh2); double peakFreq = analyzer_.binToFreq(peakBin); - if (std::abs(peakFreq) >= 1e6) - ImGui::TextDisabled("Peak: %.6f MHz, %.1f dB", peakFreq / 1e6, peakDB); - else if (std::abs(peakFreq) >= 1e3) - ImGui::TextDisabled("Peak: %.3f kHz, %.1f dB", peakFreq / 1e3, peakDB); - else - ImGui::TextDisabled("Peak: %.1f Hz, %.1f dB", peakFreq, peakDB); + { + char peakBuf[128]; + fmtFreqDB(peakBuf, sizeof(peakBuf), "Peak", peakFreq, peakDB); + ImGui::TextDisabled("%s", peakBuf); + } } void Application::renderSpectrumPanel() { diff --git a/src/ui/Cursors.cpp b/src/ui/Cursors.cpp index 7c3ef1d..e53755a 100644 --- a/src/ui/Cursors.cpp +++ b/src/ui/Cursors.cpp @@ -78,12 +78,7 @@ void Cursors::draw(const SpectrumDisplay& specDisplay, // Format a cursor label string. auto formatLabel = [](char* buf, size_t sz, const char* label, double freq, float dB) { - if (std::abs(freq) >= 1e6) - std::snprintf(buf, sz, "%s: %.6f MHz %.1f dB", label, freq / 1e6, dB); - else if (std::abs(freq) >= 1e3) - std::snprintf(buf, sz, "%s: %.3f kHz %.1f dB", label, freq / 1e3, dB); - else - std::snprintf(buf, sz, "%s: %.1f Hz %.1f dB", label, freq, dB); + fmtFreqDB(buf, sz, label, freq, dB); }; float aDB = avgDBA(), bDB = avgDBB(); @@ -124,12 +119,7 @@ void Cursors::draw(const SpectrumDisplay& specDisplay, double dFreq = cursorB.freq - cursorA.freq; float dDB = bDB - aDB; char val1[48], val2[48]; - if (std::abs(dFreq) >= 1e6) - std::snprintf(val1, sizeof(val1), "%.6f MHz", dFreq / 1e6); - else if (std::abs(dFreq) >= 1e3) - std::snprintf(val1, sizeof(val1), "%.3f kHz", dFreq / 1e3); - else - std::snprintf(val1, sizeof(val1), "%.1f Hz", dFreq); + fmtFreq(val1, sizeof(val1), dFreq); std::snprintf(val2, sizeof(val2), "%.1f dB", dDB); ImVec2 labelSz = ImGui::CalcTextSize("dF = "); @@ -138,7 +128,7 @@ void Cursors::draw(const SpectrumDisplay& specDisplay, float valW = std::max(v1Sz.x, v2Sz.x); float lineH = labelSz.y; float totalW = labelSz.x + valW; - float tx = posX + sizeX - totalW - 8; + float tx = posX + sizeX - totalW - 158; float ty = posY + 4; ImU32 col = IM_COL32(255, 200, 100, 255); float eqX = tx + labelSz.x; // values start here (right of '= ') @@ -158,12 +148,9 @@ void Cursors::drawPanel() { ImGui::TextDisabled("%s: --", label); return; } - if (std::abs(c.freq) >= 1e6) - ImGui::Text("%s: %.6f MHz, %.1f dB", label, c.freq / 1e6, dispDB); - else if (std::abs(c.freq) >= 1e3) - ImGui::Text("%s: %.3f kHz, %.1f dB", label, c.freq / 1e3, dispDB); - else - ImGui::Text("%s: %.1f Hz, %.1f dB", label, c.freq, dispDB); + char buf[128]; + fmtFreqDB(buf, sizeof(buf), label, c.freq, dispDB); + ImGui::Text("%s", buf); }; float aDB = avgDBA(), bDB = avgDBB(); @@ -173,21 +160,9 @@ void Cursors::drawPanel() { if (cursorA.active && cursorB.active) { double dF = cursorB.freq - cursorA.freq; float dA = bDB - aDB; - if (std::abs(dF) >= 1e6) - ImGui::Text("D: %.6f MHz, %.1f dB", dF / 1e6, dA); - else if (std::abs(dF) >= 1e3) - ImGui::Text("D: %.3f kHz, %.1f dB", dF / 1e3, dA); - else - ImGui::Text("D: %.1f Hz, %.1f dB", dF, dA); - } - - if (hover.active) { - if (std::abs(hover.freq) >= 1e6) - ImGui::TextDisabled("%.6f MHz, %.1f dB", hover.freq / 1e6, hover.dB); - else if (std::abs(hover.freq) >= 1e3) - ImGui::TextDisabled("%.3f kHz, %.1f dB", hover.freq / 1e3, hover.dB); - else - ImGui::TextDisabled("%.1f Hz, %.1f dB", hover.freq, hover.dB); + char dbuf[128]; + fmtFreqDB(dbuf, sizeof(dbuf), "D", dF, dA); + ImGui::Text("%s", dbuf); } // Averaging slider (logarithmic scale) diff --git a/src/ui/Measurements.cpp b/src/ui/Measurements.cpp index bdc1f99..1052849 100644 --- a/src/ui/Measurements.cpp +++ b/src/ui/Measurements.cpp @@ -186,12 +186,11 @@ void Measurements::drawPanel() { ImU32 col = (i == 0) ? IM_COL32(255, 80, 80, 255) : IM_COL32(255, 140, 60, 255); ImGui::PushStyleColor(ImGuiCol_Text, col); - if (std::abs(p.freq) >= 1e6) - ImGui::Text("P%d: %.6f MHz, %.1f dB", i + 1, p.freq / 1e6, p.dB); - else if (std::abs(p.freq) >= 1e3) - ImGui::Text("P%d: %.3f kHz, %.1f dB", i + 1, p.freq / 1e3, p.dB); - else - ImGui::Text("P%d: %.1f Hz, %.1f dB", i + 1, p.freq, p.dB); + char plabel[4]; + std::snprintf(plabel, sizeof(plabel), "P%d", i + 1); + char pbuf[128]; + fmtFreqDB(pbuf, sizeof(pbuf), plabel, p.freq, p.dB); + ImGui::Text("%s", pbuf); ImGui::PopStyleColor(); } }