INSTINCT Code Coverage Report


Directory: src/
File: internal/gui/widgets/PinIcon.cpp
Date: 2025-11-25 23:34:18
Exec Total Coverage
Lines: 0 145 0.0%
Functions: 0 2 0.0%
Branches: 0 120 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 "PinIcon.hpp"
10 #include <imgui_internal.h>
11
12 namespace NAV::gui::widgets::PinIcon
13 {
14 namespace
15 {
16
17 ✗ void DrawIcon(ImDrawList* drawList, const ImVec2& a, const ImVec2& b, PinIcon::Type type, bool filled, ImU32 color, ImU32 innerColor)
18 {
19 ✗ auto rect = ImRect(a, b);
20 ✗ auto rect_y = rect.Min.y;
21 ✗ auto rect_w = rect.Max.x - rect.Min.x;
22 ✗ auto rect_h = rect.Max.y - rect.Min.y;
23 ✗ auto rect_center_x = (rect.Min.x + rect.Max.x) * 0.5F;
24 ✗ auto rect_center_y = (rect.Min.y + rect.Max.y) * 0.5F;
25 ✗ auto rect_center = ImVec2(rect_center_x, rect_center_y);
26 ✗ const auto outline_scale = rect_w / 24.0F;
27 ✗ const auto extra_segments = static_cast<int>(2 * outline_scale); // for full circle
28
29 ✗ if (type == PinIcon::Type::Flow)
30 {
31 ✗ const auto origin_scale = rect_w / 24.0F;
32
33 ✗ const auto offset_x = 1.0F * origin_scale;
34 ✗ const auto offset_y = 0.0F * origin_scale;
35 ✗ const auto margin = 2.0F * origin_scale;
36 ✗ const auto rounding = 0.1F * origin_scale;
37 ✗ const auto tip_round = 0.7F; // percentage of triangle edge (for tip)
38 // const auto edge_round = 0.7F; // percentage of triangle edge (for corner)
39 const auto canvas = ImRect(
40 ✗ rect.Min.x + margin + offset_x,
41 ✗ rect.Min.y + margin + offset_y,
42 ✗ rect.Max.x - margin + offset_x,
43 ✗ rect.Max.y - margin + offset_y);
44 ✗ const auto canvas_x = canvas.Min.x;
45 ✗ const auto canvas_y = canvas.Min.y;
46 ✗ const auto canvas_w = canvas.Max.x - canvas.Min.x;
47 ✗ const auto canvas_h = canvas.Max.y - canvas.Min.y;
48
49 ✗ const auto left = canvas_x + canvas_w * 0.5F * 0.3F;
50 ✗ const auto right = canvas_x + canvas_w - canvas_w * 0.5F * 0.3F;
51 ✗ const auto top = canvas_y + canvas_h * 0.5F * 0.2F;
52 ✗ const auto bottom = canvas_y + canvas_h - canvas_h * 0.5F * 0.2F;
53 ✗ const auto center_y = (top + bottom) * 0.5F;
54 // const auto angle = AX_PI * 0.5F * 0.5F * 0.5F;
55
56 ✗ const auto tip_top = ImVec2(canvas_x + canvas_w * 0.5F, top);
57 ✗ const auto tip_right = ImVec2(right, center_y);
58 ✗ const auto tip_bottom = ImVec2(canvas_x + canvas_w * 0.5F, bottom);
59
60 ✗ drawList->PathLineTo(ImVec2(left, top) + ImVec2(0, rounding));
61 ✗ drawList->PathBezierCurveTo(
62 ✗ ImVec2(left, top),
63 ✗ ImVec2(left, top),
64 ✗ ImVec2(left, top) + ImVec2(rounding, 0));
65 ✗ drawList->PathLineTo(tip_top);
66 ✗ drawList->PathLineTo(tip_top + (tip_right - tip_top) * tip_round);
67 ✗ drawList->PathBezierCurveTo(
68 tip_right,
69 tip_right,
70 ✗ tip_bottom + (tip_right - tip_bottom) * tip_round);
71 ✗ drawList->PathLineTo(tip_bottom);
72 ✗ drawList->PathLineTo(ImVec2(left, bottom) + ImVec2(rounding, 0));
73 ✗ drawList->PathBezierCurveTo(
74 ✗ ImVec2(left, bottom),
75 ✗ ImVec2(left, bottom),
76 ✗ ImVec2(left, bottom) - ImVec2(0, rounding));
77
78 ✗ if (!filled)
79 {
80 ✗ if (innerColor & 0xFF000000)
81 {
82 ✗ drawList->AddConvexPolyFilled(drawList->_Path.Data, drawList->_Path.Size, innerColor);
83 }
84
85 ✗ drawList->PathStroke(color, true, 2.0F * outline_scale);
86 }
87 else
88 {
89 ✗ drawList->PathFillConvex(color);
90 }
91 }
92 else
93 {
94 ✗ auto triangleStart = rect_center_x + 0.32F * rect_w;
95
96 ✗ auto rect_offset = -static_cast<int>(rect_w * 0.25F * 0.25F);
97
98 ✗ rect.Min.x += static_cast<float>(rect_offset);
99 ✗ rect.Max.x += static_cast<float>(rect_offset);
100 ✗ rect_center_x += static_cast<float>(rect_offset) * 0.5F;
101 ✗ rect_center.x += static_cast<float>(rect_offset) * 0.5F;
102
103 ✗ if (type == PinIcon::Type::Circle)
104 {
105 ✗ const auto c = rect_center;
106
107 ✗ if (!filled)
108 {
109 ✗ const auto r = 0.5F * rect_w / 2.0F - 0.5F;
110
111 ✗ if (innerColor & 0xFF000000)
112 {
113 ✗ drawList->AddCircleFilled(c, r, innerColor, 12 + extra_segments);
114 }
115 ✗ drawList->AddCircle(c, r, color, 12 + extra_segments, 2.0F * outline_scale);
116 }
117 else
118 {
119 ✗ drawList->AddCircleFilled(c, 0.5F * rect_w / 2.0F, color, 12 + extra_segments);
120 }
121 }
122
123 ✗ if (type == PinIcon::Type::Square)
124 {
125 ✗ if (filled)
126 {
127 ✗ const auto r = 0.5F * rect_w / 2.0F;
128 ✗ const auto p0 = rect_center - ImVec2(r, r);
129 ✗ const auto p1 = rect_center + ImVec2(r, r);
130
131 ✗ drawList->AddRectFilled(p0, p1, color, 0, ImDrawFlags_RoundCornersAll);
132 }
133 else
134 {
135 ✗ const auto r = 0.5F * rect_w / 2.0F - 0.5F;
136 ✗ const auto p0 = rect_center - ImVec2(r, r);
137 ✗ const auto p1 = rect_center + ImVec2(r, r);
138
139 ✗ if (innerColor & 0xFF000000)
140 {
141 ✗ drawList->AddRectFilled(p0, p1, innerColor, 0, ImDrawFlags_RoundCornersAll);
142 }
143
144 ✗ drawList->AddRect(p0, p1, color, 0, ImDrawFlags_RoundCornersAll, 2.0F * outline_scale);
145 }
146 }
147
148 ✗ if (type == PinIcon::Type::Grid)
149 {
150 ✗ const auto r = 0.5F * rect_w / 2.0F;
151 ✗ const auto w = ceilf(r / 3.0F);
152
153 ✗ const auto baseTl = ImVec2(floorf(rect_center_x - w * 2.5F), floorf(rect_center_y - w * 2.5F));
154 ✗ const auto baseBr = ImVec2(floorf(baseTl.x + w), floorf(baseTl.y + w));
155
156 ✗ auto tl = baseTl;
157 ✗ auto br = baseBr;
158 ✗ for (int i = 0; i < 3; ++i)
159 {
160 ✗ tl.x = baseTl.x;
161 ✗ br.x = baseBr.x;
162 ✗ drawList->AddRectFilled(tl, br, color);
163 ✗ tl.x += w * 2;
164 ✗ br.x += w * 2;
165 ✗ if (i != 1 || filled)
166 {
167 ✗ drawList->AddRectFilled(tl, br, color);
168 }
169 ✗ tl.x += w * 2;
170 ✗ br.x += w * 2;
171 ✗ drawList->AddRectFilled(tl, br, color);
172
173 ✗ tl.y += w * 2;
174 ✗ br.y += w * 2;
175 }
176
177 ✗ triangleStart = br.x + w + 1.0F / 24.0F * rect_w;
178 }
179
180 ✗ if (type == PinIcon::Type::RoundSquare)
181 {
182 ✗ if (filled)
183 {
184 ✗ const auto r = 0.5F * rect_w / 2.0F;
185 ✗ const auto cr = r * 0.5F;
186 ✗ const auto p0 = rect_center - ImVec2(r, r);
187 ✗ const auto p1 = rect_center + ImVec2(r, r);
188
189 ✗ drawList->AddRectFilled(p0, p1, color, cr, ImDrawFlags_RoundCornersAll);
190 }
191 else
192 {
193 ✗ const auto r = 0.5F * rect_w / 2.0F - 0.5F;
194 ✗ const auto cr = r * 0.5F;
195 ✗ const auto p0 = rect_center - ImVec2(r, r);
196 ✗ const auto p1 = rect_center + ImVec2(r, r);
197
198 ✗ if (innerColor & 0xFF000000)
199 {
200 ✗ drawList->AddRectFilled(p0, p1, innerColor, cr, ImDrawFlags_RoundCornersAll);
201 }
202
203 ✗ drawList->AddRect(p0, p1, color, cr, ImDrawFlags_RoundCornersAll, 2.0F * outline_scale);
204 }
205 }
206 ✗ else if (type == PinIcon::Type::Diamond)
207 {
208 ✗ if (filled)
209 {
210 ✗ const auto r = 0.607F * rect_w / 2.0F;
211 ✗ const auto c = rect_center;
212
213 ✗ drawList->PathLineTo(c + ImVec2(0, -r));
214 ✗ drawList->PathLineTo(c + ImVec2(r, 0));
215 ✗ drawList->PathLineTo(c + ImVec2(0, r));
216 ✗ drawList->PathLineTo(c + ImVec2(-r, 0));
217 ✗ drawList->PathFillConvex(color);
218 }
219 else
220 {
221 ✗ const auto r = 0.607F * rect_w / 2.0F - 0.5F;
222 ✗ const auto c = rect_center;
223
224 ✗ drawList->PathLineTo(c + ImVec2(0, -r));
225 ✗ drawList->PathLineTo(c + ImVec2(r, 0));
226 ✗ drawList->PathLineTo(c + ImVec2(0, r));
227 ✗ drawList->PathLineTo(c + ImVec2(-r, 0));
228
229 ✗ if (innerColor & 0xFF000000)
230 {
231 ✗ drawList->AddConvexPolyFilled(drawList->_Path.Data, drawList->_Path.Size, innerColor);
232 }
233
234 ✗ drawList->PathStroke(color, true, 2.0F * outline_scale);
235 }
236 }
237 else
238 {
239 ✗ const auto triangleTip = triangleStart + rect_w * (0.45F - 0.32F);
240
241 ✗ drawList->AddTriangleFilled(
242 ✗ ImVec2(ceilf(triangleTip), rect_y + rect_h * 0.5F),
243 ✗ ImVec2(triangleStart, rect_center_y + 0.15F * rect_h),
244 ✗ ImVec2(triangleStart, rect_center_y - 0.15F * rect_h),
245 color);
246 }
247 }
248 ✗ }
249
250 } // namespace
251 } // namespace NAV::gui::widgets::PinIcon
252
253 ✗ void NAV::gui::widgets::PinIcon::Draw(const ImVec2& size, Type type, bool filled, const ImVec4& color /* = ImVec4(1, 1, 1, 1)*/, const ImVec4& innerColor /* = ImVec4(0, 0, 0, 0)*/)
254 {
255 ✗ if (ImGui::IsRectVisible(size))
256 {
257 ✗ auto cursorPos = ImGui::GetCursorScreenPos();
258 ✗ auto* drawList = ImGui::GetWindowDrawList();
259 ✗ DrawIcon(drawList, cursorPos, cursorPos + size, type, filled, ImColor(color), ImColor(innerColor));
260 }
261
262 ✗ ImGui::Dummy(size);
263 ✗ }
264