INSTINCT Code Coverage Report


Directory: src/
File: util/Plot/PlotTooltip.cpp
Date: 2025-11-25 23:34:18
Exec Total Coverage
Lines: 0 72 0.0%
Functions: 0 3 0.0%
Branches: 0 146 0.0%

Line Branch Exec Source
1 // This file is part of INSTINCT, the INS Toolkit for Integrated
2 // Navigation Concepts and Training by the Institute of Navigation of
3 // the University of Stuttgart, Germany.
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9 #include "PlotTooltip.hpp"
10
11 #include <cstddef>
12 #include <implot_internal.h>
13
14 #include "Navigation/Time/InsTime.hpp"
15 #include "internal/gui/NodeEditorApplication.hpp"
16
17 ✗ bool NAV::ShowPlotTooltip(std::vector<PlotTooltip>& tooltips,
18 size_t plotItemIdx,
19 const std::string& plotName,
20 ImAxis axis,
21 const ScrollingBuffer<double>& xData,
22 const ScrollingBuffer<double>& yData,
23 bool otherHoverTooltipsShown,
24 const std::function<void(size_t)>& showTooltipCallback)
25 {
26 ✗ bool tooltipShown = false;
27
28 ✗ if (ImPlot::IsPlotHovered() && ImGui::IsKeyDown(ImGuiKey_ModCtrl))
29 {
30 ✗ if (const auto* item = ImPlot::GetCurrentPlot()->Items.GetItem(plotName.c_str());
31 ✗ item && item->Show)
32 {
33 ✗ constexpr double HOVER_PIXEL_SIZE = 5.0;
34 ✗ auto limits = ImPlot::GetPlotLimits(IMPLOT_AUTO, axis);
35
36 ✗ ImVec2 scaling = ImVec2(static_cast<float>(HOVER_PIXEL_SIZE * (limits.X.Max - limits.X.Min) / ImPlot::GetCurrentPlot()->PlotRect.GetWidth()),
37 ✗ static_cast<float>(HOVER_PIXEL_SIZE * (limits.Y.Max - limits.Y.Min) / ImPlot::GetCurrentPlot()->PlotRect.GetHeight()));
38 ✗ ImPlotPoint mouse = ImPlot::GetPlotMousePos();
39
40 ✗ for (size_t i = 0; i < yData.size(); i++)
41 {
42 ✗ if (std::abs(mouse.x - xData.at(i)) < scaling.x
43 ✗ && std::abs(mouse.y - yData.at(i)) < scaling.y)
44 {
45 ✗ ImGui::PushFont(Application::MonoFont());
46 ✗ ImGui::BeginTooltip();
47 ✗ if (otherHoverTooltipsShown)
48 {
49 ✗ ImGui::PushStyleColor(ImGuiCol_Separator, ImGui::GetStyleColorVec4(ImGuiCol_SeparatorActive));
50 ✗ ImGui::Separator();
51 ✗ ImGui::Separator();
52 ✗ ImGui::PopStyleColor();
53 }
54
55 ✗ if (showTooltipCallback) { showTooltipCallback(i); }
56
57 ✗ ImGui::EndTooltip();
58 ✗ ImGui::PopFont();
59 ✗ tooltipShown = true;
60
61 ✗ if (ImGui::IsMouseClicked(ImGuiMouseButton_Left))
62 {
63 ✗ if (std::ranges::find_if(tooltips, [&](const auto& tooltip) {
64 ✗ return tooltip.plotItemIdx == plotItemIdx && tooltip.dataIdx == i;
65 })
66 ✗ == tooltips.end())
67 {
68 ✗ auto mousePos = ImGui::GetMousePos();
69 ✗ mousePos.x += 25.0F;
70 ✗ tooltips.emplace_back(plotItemIdx, i, mousePos);
71 }
72 }
73 ✗ break;
74 }
75 }
76 }
77 }
78 ✗ return tooltipShown;
79 }
80
81 ✗ void NAV::ShowPlotTooltipWindows(std::vector<PlotTooltip>& tooltips,
82 size_t plotItemIdx,
83 const std::string& plotName,
84 const std::string& uid,
85 const std::vector<int*>& parentWindows,
86 const std::function<InsTime(size_t)>& getInsTime,
87 const std::function<void(size_t, const char*)>& showTooltipCallback)
88 {
89 ✗ std::vector<size_t> tooltipsToClose;
90 ✗ for (size_t tipIdx = 0; tipIdx < tooltips.size(); tipIdx++)
91 {
92 ✗ auto& tooltip = tooltips.at(tipIdx);
93 ✗ if (tooltip.plotItemIdx == plotItemIdx)
94 {
95 ✗ auto tooltipTime = getInsTime(tooltip.dataIdx).toYMDHMS(GPST);
96 ✗ auto windowName = fmt::format("{} - {}", plotName, tooltipTime);
97 ✗ auto tooltipUID = fmt::format("{} {}", uid, tooltip.dataIdx);
98
99 ✗ auto windowUniqueTitle = fmt::format("{}##{}", windowName, tooltipUID);
100
101 ✗ for (size_t i = 0; i < tooltips.size(); i++) // Prevent windows with same name/content
102 {
103 ✗ if (i == tipIdx) { continue; }
104 ✗ const auto& tooltip = tooltips.at(i);
105 auto uniqueTitle = fmt::format("{} - {}##{} {}",
106 ✗ plotName, getInsTime(tooltip.dataIdx).toYMDHMS(GPST), uid, tooltip.dataIdx);
107 ✗ if (uniqueTitle == windowUniqueTitle)
108 {
109 ✗ tooltipsToClose.push_back(tipIdx);
110 ✗ break;
111 }
112 ✗ }
113 ✗ if (!tooltipsToClose.empty() && tooltipsToClose.back() == tipIdx) { break; }
114
115 ✗ bool open = true;
116 ✗ if (tooltip.startPos)
117 {
118 ✗ ImGui::SetNextWindowPos(*tooltip.startPos);
119 ✗ tooltip.startPos.reset();
120 }
121 ✗ ImGui::PushFont(Application::MonoFont());
122 ✗ ImGui::Begin(windowUniqueTitle.c_str(), &open,
123 ImGuiWindowFlags_AlwaysAutoResize);
124
125 ✗ for (int* parentWindow : parentWindows) // Do not make tooltips go behind the plot window
126 {
127 ✗ if (ImGuiWindow* tooltipWindow = ImGui::GetCurrentWindow();
128 ✗ ImGui::IsWindowAbove(reinterpret_cast<ImGuiWindow*>(parentWindow),
129 tooltipWindow))
130 {
131 ✗ ImGui::BringWindowToDisplayFront(tooltipWindow);
132 }
133 }
134
135 ✗ if (ImGui::GetWindowSize().x < ImGui::CalcTextSize(windowName.c_str()).x + 50.0F)
136 {
137 ✗ ImGui::TextUnformatted(fmt::format("{}", tooltipTime).c_str());
138 ✗ ImGui::Separator();
139 }
140
141 ✗ if (showTooltipCallback) { showTooltipCallback(tooltip.dataIdx, tooltipUID.c_str()); }
142
143 ✗ ImGui::End();
144 ✗ ImGui::PopFont();
145 ✗ if (!open) { tooltipsToClose.push_back(tipIdx); }
146 ✗ }
147 }
148 ✗ for (const size_t tipIdx : tooltipsToClose)
149 {
150 ✗ tooltips.erase(std::next(tooltips.begin(), static_cast<int64_t>(tipIdx)));
151 }
152 ✗ }
153