/** * @file TriggerPanel.cpp * @brief Trigger configuration bar — hub-side trigger semantics. * * The trigger runs in the C++ StreamHub: this panel only edits the config * (signal/edge/threshold/window/pre%/mode), sends setTrigger + arm/disarm/ * rearm/trigStop commands, and reflects the hub triggerState broadcasts. */ #include "TriggerPanel.h" #include "App.h" #include "Protocol.h" #include "imgui.h" #include "Icons.h" #include #include #include namespace StreamHubClient { /* Window presets (mirrors the web UI: 100 µs .. 10 s) */ static const double kWinVals[] = {1e-4, 1e-3, 1e-2, 1e-1, 1.0, 10.0}; static const char* kWinLabels[] = {"100 µs", "1 ms", "10 ms", "100 ms", "1 s", "10 s"}; static const int kNumWins = 6; static const char* kEdgeLabels[] = {ICON_FA_ARROW_TREND_UP " Rising", ICON_FA_ARROW_TREND_DOWN " Falling", ICON_FA_ARROWS_UP_DOWN " Both"}; static const char* kEdgeWire[] = {"rising", "falling", "both"}; /* Send the current config to the hub. */ static void sendTrigConfig(App& app) { auto& trig = app.trigger(); if (trig.signalKey.empty()) { return; } app.ws().sendText(BuildSetTrigger( trig.signalKey, kEdgeWire[trig.edge], trig.threshold, trig.windowSec, trig.prePercent, trig.single ? "single" : "normal")); } void RenderTriggerPanel(App& app) { auto& trig = app.trigger(); auto& sources = app.sources(); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.15f, 0.15f, 0.20f, 1.f)); ImGui::BeginChild("##trigbar", ImVec2(0.f, 90.f), true); ImGui::PopStyleColor(); ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(6.f, 4.f)); bool cfgChanged = false; /* ── Signal selector (full keys "src:sig") ─────────────────────────── * * Vector signals are flattened time-series on the hub: one key per * signal; the trigger engine checks every decoded sample of it. */ ImGui::SetNextItemWidth(180.f); if (ImGui::BeginCombo("Signal##trig", trig.signalKey.empty() ? "