INSTINCT Code Coverage Report


Directory: src/
File: util/Plot/PlotTooltip.cpp
Date: 2025-02-07 16:54:41
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