INSTINCT Code Coverage Report


Directory: src/
File: internal/gui/windows/ImPlotStyleEditor.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 0 339 0.0%
Functions: 0 3 0.0%
Branches: 0 687 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 "ImPlotStyleEditor.hpp"
10
11 #include <vector>
12 #include <string>
13 #include <filesystem>
14 #include <fstream>
15
16 #include <fmt/core.h>
17 #include <imgui.h>
18 #include <imgui_stdlib.h>
19 #include <implot.h>
20 #include <implot_internal.h>
21 #include <imgui_extra_math.h>
22
23 #include "internal/gui/widgets/HelpMarker.hpp"
24 #include "internal/gui/widgets/FileDialog.hpp"
25 #include "internal/gui/widgets/imgui_ex.hpp"
26 #include "internal/gui/NodeEditorApplication.hpp"
27 #include "internal/ConfigManager.hpp"
28 #include "internal/FlowManager.hpp"
29
30 #include "util/ImPlot.hpp"
31 #include "util/Logger.hpp"
32 #include "util/Json.hpp"
33
34 namespace NAV::gui::windows
35 {
36
37 bool saveConfigInFlow = false;
38 bool prefereFlowOverGlobal = true;
39
40 } // namespace NAV::gui::windows
41
42 void NAV::gui::windows::ShowImPlotStyleEditor(bool* show /* = nullptr*/)
43 {
44 if (!ImGui::Begin("ImPlot Style", show))
45 {
46 ImGui::End();
47 return;
48 }
49
50 static std::string path = ConfigManager::Get<std::string>("implot-config");
51
52 ImGui::TextUnformatted("Plot style: ");
53 ImGui::SameLine();
54 if (widgets::FileDialogLoad(path, "ImPlot config file", ".json", { ".json" }, flow::GetConfigPath(), 0, "ImPlotStyleEditor"))
55 {
56 LOG_DEBUG("ImPlot config file changed to: {}", path);
57 loadImPlotStyleFromConfigFile(path.c_str(), ImPlot::GetStyle());
58 }
59 ImGui::SameLine();
60 if (ImGui::Button("Save##ImPlotStyleToFile"))
61 {
62 std::filesystem::path filepath = flow::GetConfigPath();
63 if (std::filesystem::path inputPath{ path };
64 inputPath.is_relative())
65 {
66 filepath /= inputPath;
67 }
68 else
69 {
70 filepath = inputPath;
71 }
72 std::ofstream filestream(filepath);
73
74 if (!filestream.good())
75 {
76 LOG_ERROR("Could not save the ImPlot config file: {}", filepath.string());
77 }
78 else
79 {
80 json j;
81 j["implot"]["style"] = ImPlot::GetStyle();
82
83 filestream << std::setw(4) << j << std::endl; // NOLINT(performance-avoid-endl)
84 }
85 }
86
87 if (ImGui::Checkbox("Save into flow file", &saveConfigInFlow))
88 {
89 flow::ApplyChanges();
90 }
91 ImGui::SameLine();
92 if (ImGui::Checkbox("Prefere flow file over global settings", &prefereFlowOverGlobal))
93 {
94 loadImPlotStyleFromConfigFile(prefereFlowOverGlobal ? flow::GetCurrentFilename().c_str() : path.c_str(), ImPlot::GetStyle());
95 flow::ApplyChanges();
96 }
97
98 ImPlotStyle& style = ImPlot::GetStyle();
99
100 if (ImGui::BeginTabBar("##StyleEditor"))
101 {
102 if (ImGui::BeginTabItem("Variables"))
103 {
104 if (ImGui::BeginTable("ImPlotStyleEditorColors", 2, ImGuiTableFlags_SizingFixedFit, ImVec2(0.0F, 0.0F)))
105 {
106 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
107 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed, 55.0F);
108
109 auto revertButton = [](auto& value, auto refVal, const char* id) {
110 if (value != refVal)
111 {
112 ImGui::TableNextColumn();
113 if (ImGui::Button(fmt::format("Revert##ImPlotStyle.{}", id).c_str()))
114 {
115 value = refVal;
116 if (saveConfigInFlow)
117 {
118 flow::ApplyChanges();
119 }
120 }
121 }
122 };
123
124 ImGui::TableNextRow();
125 ImGui::TableNextColumn();
126 ImGui::Text("Item Styling");
127 ImGui::TableNextRow();
128 ImGui::TableNextColumn();
129 if (ImGui::SliderFloat("LineWeight", &style.LineWeight, 0.0F, 5.0F, "%.1F"))
130 {
131 if (saveConfigInFlow)
132 {
133 flow::ApplyChanges();
134 }
135 }
136 revertButton(style.LineWeight, NodeEditorApplication::imPlotReferenceStyle.LineWeight, "LineWeight");
137 ImGui::TableNextRow();
138 ImGui::TableNextColumn();
139 if (ImGui::SliderFloat("MarkerSize", &style.MarkerSize, 2.0F, 10.0F, "%.1F"))
140 {
141 if (saveConfigInFlow)
142 {
143 flow::ApplyChanges();
144 }
145 }
146 revertButton(style.MarkerSize, NodeEditorApplication::imPlotReferenceStyle.MarkerSize, "MarkerSize");
147 ImGui::TableNextRow();
148 ImGui::TableNextColumn();
149 if (ImGui::SliderFloat("MarkerWeight", &style.MarkerWeight, 0.0F, 5.0F, "%.1F"))
150 {
151 if (saveConfigInFlow)
152 {
153 flow::ApplyChanges();
154 }
155 }
156 revertButton(style.MarkerWeight, NodeEditorApplication::imPlotReferenceStyle.MarkerWeight, "MarkerWeight");
157 ImGui::TableNextRow();
158 ImGui::TableNextColumn();
159 if (ImGui::SliderFloat("FillAlpha", &style.FillAlpha, 0.0F, 1.0F, "%.2F"))
160 {
161 if (saveConfigInFlow)
162 {
163 flow::ApplyChanges();
164 }
165 }
166 revertButton(style.FillAlpha, NodeEditorApplication::imPlotReferenceStyle.FillAlpha, "FillAlpha");
167 ImGui::TableNextRow();
168 ImGui::TableNextColumn();
169 if (ImGui::SliderFloat("ErrorBarSize", &style.ErrorBarSize, 0.0F, 10.0F, "%.1F"))
170 {
171 if (saveConfigInFlow)
172 {
173 flow::ApplyChanges();
174 }
175 }
176 revertButton(style.ErrorBarSize, NodeEditorApplication::imPlotReferenceStyle.ErrorBarSize, "ErrorBarSize");
177 ImGui::TableNextRow();
178 ImGui::TableNextColumn();
179 if (ImGui::SliderFloat("ErrorBarWeight", &style.ErrorBarWeight, 0.0F, 5.0F, "%.1F"))
180 {
181 if (saveConfigInFlow)
182 {
183 flow::ApplyChanges();
184 }
185 }
186 revertButton(style.ErrorBarWeight, NodeEditorApplication::imPlotReferenceStyle.ErrorBarWeight, "ErrorBarWeight");
187 ImGui::TableNextRow();
188 ImGui::TableNextColumn();
189 if (ImGui::SliderFloat("DigitalBitHeight", &style.DigitalBitHeight, 0.0F, 20.0F, "%.1F"))
190 {
191 if (saveConfigInFlow)
192 {
193 flow::ApplyChanges();
194 }
195 }
196 revertButton(style.DigitalBitHeight, NodeEditorApplication::imPlotReferenceStyle.DigitalBitHeight, "DigitalBitHeight");
197 ImGui::TableNextRow();
198 ImGui::TableNextColumn();
199 if (ImGui::SliderFloat("DigitalBitGap", &style.DigitalBitGap, 0.0F, 20.0F, "%.1F"))
200 {
201 if (saveConfigInFlow)
202 {
203 flow::ApplyChanges();
204 }
205 }
206 revertButton(style.DigitalBitGap, NodeEditorApplication::imPlotReferenceStyle.DigitalBitGap, "DigitalBitGap");
207 ImGui::TableNextRow();
208 ImGui::TableNextColumn();
209 ImGui::Text("Plot Styling");
210 ImGui::TableNextRow();
211 ImGui::TableNextColumn();
212 if (ImGui::SliderFloat("PlotBorderSize", &style.PlotBorderSize, 0.0F, 2.0F, "%.0F"))
213 {
214 if (saveConfigInFlow)
215 {
216 flow::ApplyChanges();
217 }
218 }
219 revertButton(style.PlotBorderSize, NodeEditorApplication::imPlotReferenceStyle.PlotBorderSize, "PlotBorderSize");
220 ImGui::TableNextRow();
221 ImGui::TableNextColumn();
222 if (ImGui::SliderFloat("MinorAlpha", &style.MinorAlpha, 0.0F, 1.0F, "%.2F"))
223 {
224 if (saveConfigInFlow)
225 {
226 flow::ApplyChanges();
227 }
228 }
229 revertButton(style.MinorAlpha, NodeEditorApplication::imPlotReferenceStyle.MinorAlpha, "MinorAlpha");
230 ImGui::TableNextRow();
231 ImGui::TableNextColumn();
232 if (ImGui::SliderFloat2("MajorTickLen", reinterpret_cast<float*>(&style.MajorTickLen), 0.0F, 20.0F, "%.0F"))
233 {
234 if (saveConfigInFlow)
235 {
236 flow::ApplyChanges();
237 }
238 }
239 revertButton(style.MajorTickLen, NodeEditorApplication::imPlotReferenceStyle.MajorTickLen, "MajorTickLen");
240 ImGui::TableNextRow();
241 ImGui::TableNextColumn();
242 if (ImGui::SliderFloat2("MinorTickLen", reinterpret_cast<float*>(&style.MinorTickLen), 0.0F, 20.0F, "%.0F"))
243 {
244 if (saveConfigInFlow)
245 {
246 flow::ApplyChanges();
247 }
248 }
249 revertButton(style.MinorTickLen, NodeEditorApplication::imPlotReferenceStyle.MinorTickLen, "MinorTickLen");
250 ImGui::TableNextRow();
251 ImGui::TableNextColumn();
252 if (ImGui::SliderFloat2("MajorTickSize", reinterpret_cast<float*>(&style.MajorTickSize), 0.0F, 2.0F, "%.1F"))
253 {
254 if (saveConfigInFlow)
255 {
256 flow::ApplyChanges();
257 }
258 }
259 revertButton(style.MajorTickSize, NodeEditorApplication::imPlotReferenceStyle.MajorTickSize, "MajorTickSize");
260 ImGui::TableNextRow();
261 ImGui::TableNextColumn();
262 if (ImGui::SliderFloat2("MinorTickSize", reinterpret_cast<float*>(&style.MinorTickSize), 0.0F, 2.0F, "%.1F"))
263 {
264 if (saveConfigInFlow)
265 {
266 flow::ApplyChanges();
267 }
268 }
269 revertButton(style.MinorTickSize, NodeEditorApplication::imPlotReferenceStyle.MinorTickSize, "MinorTickSize");
270 ImGui::TableNextRow();
271 ImGui::TableNextColumn();
272 if (ImGui::SliderFloat2("MajorGridSize", reinterpret_cast<float*>(&style.MajorGridSize), 0.0F, 2.0F, "%.1F"))
273 {
274 if (saveConfigInFlow)
275 {
276 flow::ApplyChanges();
277 }
278 }
279 revertButton(style.MajorGridSize, NodeEditorApplication::imPlotReferenceStyle.MajorGridSize, "MajorGridSize");
280 ImGui::TableNextRow();
281 ImGui::TableNextColumn();
282 if (ImGui::SliderFloat2("MinorGridSize", reinterpret_cast<float*>(&style.MinorGridSize), 0.0F, 2.0F, "%.1F"))
283 {
284 if (saveConfigInFlow)
285 {
286 flow::ApplyChanges();
287 }
288 }
289 revertButton(style.MinorGridSize, NodeEditorApplication::imPlotReferenceStyle.MinorGridSize, "MinorGridSize");
290 ImGui::TableNextRow();
291 ImGui::TableNextColumn();
292 if (ImGui::SliderFloat2("PlotDefaultSize", reinterpret_cast<float*>(&style.PlotDefaultSize), 0.0F, 1000, "%.0F"))
293 {
294 if (saveConfigInFlow)
295 {
296 flow::ApplyChanges();
297 }
298 }
299 revertButton(style.PlotDefaultSize, NodeEditorApplication::imPlotReferenceStyle.PlotDefaultSize, "PlotDefaultSize");
300 ImGui::TableNextRow();
301 ImGui::TableNextColumn();
302 if (ImGui::SliderFloat2("PlotMinSize", reinterpret_cast<float*>(&style.PlotMinSize), 0.0F, 300, "%.0F"))
303 {
304 if (saveConfigInFlow)
305 {
306 flow::ApplyChanges();
307 }
308 }
309 revertButton(style.PlotMinSize, NodeEditorApplication::imPlotReferenceStyle.PlotMinSize, "PlotMinSize");
310
311 ImGui::TableNextRow();
312 ImGui::TableNextColumn();
313 ImGui::Text("Plot Padding");
314 ImGui::TableNextRow();
315 ImGui::TableNextColumn();
316 if (ImGui::SliderFloat2("PlotPadding", reinterpret_cast<float*>(&style.PlotPadding), 0.0F, 30.0F, "%.0F"))
317 {
318 if (saveConfigInFlow)
319 {
320 flow::ApplyChanges();
321 }
322 }
323 revertButton(style.PlotPadding, NodeEditorApplication::imPlotReferenceStyle.PlotPadding, "PlotPadding");
324 ImGui::TableNextRow();
325 ImGui::TableNextColumn();
326 if (ImGui::SliderFloat2("LabelPadding", reinterpret_cast<float*>(&style.LabelPadding), 0.0F, 20.0F, "%.0F"))
327 {
328 if (saveConfigInFlow)
329 {
330 flow::ApplyChanges();
331 }
332 }
333 revertButton(style.LabelPadding, NodeEditorApplication::imPlotReferenceStyle.LabelPadding, "LabelPadding");
334 ImGui::TableNextRow();
335 ImGui::TableNextColumn();
336 if (ImGui::SliderFloat2("LegendPadding", reinterpret_cast<float*>(&style.LegendPadding), 0.0F, 20.0F, "%.0F"))
337 {
338 if (saveConfigInFlow)
339 {
340 flow::ApplyChanges();
341 }
342 }
343 revertButton(style.LegendPadding, NodeEditorApplication::imPlotReferenceStyle.LegendPadding, "LegendPadding");
344 ImGui::TableNextRow();
345 ImGui::TableNextColumn();
346 if (ImGui::SliderFloat2("LegendInnerPadding", reinterpret_cast<float*>(&style.LegendInnerPadding), 0.0F, 10.0F, "%.0F"))
347 {
348 if (saveConfigInFlow)
349 {
350 flow::ApplyChanges();
351 }
352 }
353 revertButton(style.LegendInnerPadding, NodeEditorApplication::imPlotReferenceStyle.LegendInnerPadding, "LegendInnerPadding");
354 ImGui::TableNextRow();
355 ImGui::TableNextColumn();
356 if (ImGui::SliderFloat2("LegendSpacing", reinterpret_cast<float*>(&style.LegendSpacing), 0.0F, 5.0F, "%.0F"))
357 {
358 if (saveConfigInFlow)
359 {
360 flow::ApplyChanges();
361 }
362 }
363 revertButton(style.LegendSpacing, NodeEditorApplication::imPlotReferenceStyle.LegendSpacing, "LegendSpacing");
364 ImGui::TableNextRow();
365 ImGui::TableNextColumn();
366 if (ImGui::SliderFloat2("MousePosPadding", reinterpret_cast<float*>(&style.MousePosPadding), 0.0F, 20.0F, "%.0F"))
367 {
368 if (saveConfigInFlow)
369 {
370 flow::ApplyChanges();
371 }
372 }
373 revertButton(style.MousePosPadding, NodeEditorApplication::imPlotReferenceStyle.MousePosPadding, "MousePosPadding");
374 ImGui::TableNextRow();
375 ImGui::TableNextColumn();
376 if (ImGui::SliderFloat2("AnnotationPadding", reinterpret_cast<float*>(&style.AnnotationPadding), 0.0F, 5.0F, "%.0F"))
377 {
378 if (saveConfigInFlow)
379 {
380 flow::ApplyChanges();
381 }
382 }
383 revertButton(style.AnnotationPadding, NodeEditorApplication::imPlotReferenceStyle.AnnotationPadding, "AnnotationPadding");
384 ImGui::TableNextRow();
385 ImGui::TableNextColumn();
386 if (ImGui::SliderFloat2("FitPadding", reinterpret_cast<float*>(&style.FitPadding), 0, 0.2F, "%.2F"))
387 {
388 if (saveConfigInFlow)
389 {
390 flow::ApplyChanges();
391 }
392 }
393 revertButton(style.FitPadding, NodeEditorApplication::imPlotReferenceStyle.FitPadding, "FitPadding");
394
395 ImGui::EndTable();
396 }
397
398 ImGui::EndTabItem();
399 }
400 if (ImGui::BeginTabItem("Colors"))
401 {
402 static ImGuiTextFilter filter;
403 filter.Draw("Filter colors", ImGui::GetFontSize() * 16);
404
405 static ImGuiColorEditFlags alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
406 if (ImGui::RadioButton("Opaque", alpha_flags == ImGuiColorEditFlags_None))
407 {
408 alpha_flags = ImGuiColorEditFlags_None;
409 }
410 ImGui::SameLine();
411 if (ImGui::RadioButton("Alpha", alpha_flags == ImGuiColorEditFlags_AlphaPreview))
412 {
413 alpha_flags = ImGuiColorEditFlags_AlphaPreview;
414 }
415 ImGui::SameLine();
416 if (ImGui::RadioButton("Both", alpha_flags == ImGuiColorEditFlags_AlphaPreviewHalf))
417 {
418 alpha_flags = ImGuiColorEditFlags_AlphaPreviewHalf;
419 }
420 ImGui::SameLine();
421 gui::widgets::HelpMarker("In the color list:\n"
422 "Left-click on colored square to open color picker,\n"
423 "Right-click to open edit options menu.");
424 ImGui::Separator();
425
426 if (ImGui::BeginTable("ImPlotStyleEditorColors", 3, ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_NoHostExtendX, ImVec2(0.0F, 0.0F)))
427 {
428 for (int i = 0; i < ImPlotCol_COUNT; i++)
429 {
430 const char* name = ImPlot::GetStyleColorName(i);
431 if (!filter.PassFilter(name))
432 {
433 continue;
434 }
435
436 ImGui::TableNextRow();
437 ImGui::TableNextColumn();
438 ImGui::PushID(i);
439 ImVec4 temp = ImPlot::GetStyleColorVec4(i);
440 const bool isColorAuto = ImPlot::IsColorAuto(i);
441 if (!isColorAuto)
442 {
443 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.25F);
444 }
445 if (ImGui::Button("Auto"))
446 {
447 if (isColorAuto)
448 {
449 style.Colors[i] = temp; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
450 }
451 else
452 {
453 style.Colors[i] = IMPLOT_AUTO_COL; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
454 }
455 ImPlot::BustItemCache();
456 if (saveConfigInFlow)
457 {
458 flow::ApplyChanges();
459 }
460 }
461 if (!isColorAuto)
462 {
463 ImGui::PopStyleVar();
464 }
465 ImGui::TableNextColumn();
466 if (ImGui::ColorEdit4(name, &temp.x, ImGuiColorEditFlags_NoInputs | alpha_flags))
467 {
468 style.Colors[i] = temp; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
469 ImPlot::BustItemCache();
470 if (saveConfigInFlow)
471 {
472 flow::ApplyChanges();
473 }
474 }
475 if (style.Colors[i] != NodeEditorApplication::imPlotReferenceStyle.Colors[i]) // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
476 {
477 ImGui::TableNextColumn();
478 if (ImGui::Button(fmt::format("Revert##ImPlotStyleColor{}", i).c_str()))
479 {
480 style.Colors[i] = NodeEditorApplication::imPlotReferenceStyle.Colors[i]; // NOLINT(cppcoreguidelines-pro-bounds-constant-array-index)
481 ImPlot::BustItemCache();
482 if (saveConfigInFlow)
483 {
484 flow::ApplyChanges();
485 }
486 }
487 }
488 ImGui::PopID();
489 }
490
491 ImGui::EndTable();
492 }
493
494 ImGui::EndTabItem();
495 }
496 if (ImGui::BeginTabItem("Colormaps"))
497 {
498 ImPlotContext& gp = *ImPlot::GetCurrentContext();
499
500 static std::vector<bool> showEditColormap(static_cast<size_t>(gp.ColormapData.Count));
501
502 if (ImGui::BeginTable("ImPlotStyleEditorColormaps", 2, ImGuiTableFlags_SizingFixedFit))
503 {
504 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthFixed);
505 ImGui::TableSetupColumn("", ImGuiTableColumnFlags_WidthStretch);
506
507 // built-in/added
508 for (int i = 0; i < gp.ColormapData.Count; ++i)
509 {
510 ImGui::TableNextRow();
511 ImGui::TableNextColumn();
512 ImGui::PushID(i);
513 int size = gp.ColormapData.GetKeyCount(i);
514 bool selected = i == gp.Style.Colormap;
515
516 const char* name = ImPlot::GetColormapName(i);
517 if (!selected)
518 {
519 ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.25F);
520 }
521 if (ImGui::Button(name, ImVec2(100 * gui::NodeEditorApplication::windowFontRatio(), 0)))
522 {
523 gp.Style.Colormap = i;
524 ImPlot::BustItemCache();
525 }
526 if (!selected)
527 {
528 ImGui::PopStyleVar();
529 }
530 ImGui::TableNextColumn();
531 if (showEditColormap.at(static_cast<size_t>(i)))
532 {
533 for (int c = 0; c < size; ++c)
534 {
535 ImGui::PushID(c);
536 ImVec4 col4 = ImGui::ColorConvertU32ToFloat4(gp.ColormapData.GetKeyColor(i, c));
537 if (ImGui::ColorEdit4("", &col4.x, ImGuiColorEditFlags_NoInputs))
538 {
539 ImU32 col32 = ImGui::ColorConvertFloat4ToU32(col4);
540 gp.ColormapData.SetKeyColor(i, c, col32);
541 ImPlot::BustItemCache();
542 }
543 if ((c + 1) % 12 != 0 && c != size - 1)
544 {
545 ImGui::SameLine();
546 }
547 ImGui::PopID();
548 }
549 ImGui::SameLine();
550 ImGui::Dummy(ImVec2(10.0F, -1.0F));
551 ImGui::SameLine();
552 if (ImGui::Button("x##ImPlotStyleEditorColormap close edit"))
553 {
554 showEditColormap.at(static_cast<size_t>(i)) = false;
555 }
556 }
557 else
558 {
559 if (ImPlot::ColormapButton("##", ImVec2(-1, 0), i))
560 {
561 showEditColormap.at(static_cast<size_t>(i)) = true;
562 }
563 }
564
565 ImGui::PopID();
566 }
567
568 ImGui::EndTable();
569 }
570
571 static ImVector<ImVec4> custom;
572 if (custom.Size == 0)
573 {
574 custom.push_back(ImVec4(1, 0, 0, 1));
575 custom.push_back(ImVec4(0, 1, 0, 1));
576 custom.push_back(ImVec4(0, 0, 1, 1));
577 }
578 ImGui::Separator();
579
580 ImGui::BeginGroup();
581 static std::string name = "Custom";
582
583 if (ImGui::Button("+", ImVec2((100 - ImGui::GetStyle().ItemSpacing.x) / 2, 0)))
584 {
585 custom.push_back(ImVec4(0, 0, 0, 1));
586 }
587 ImGui::SameLine();
588 if (ImGui::Button("-", ImVec2((100 - ImGui::GetStyle().ItemSpacing.x) / 2, 0)) && custom.Size > 2)
589 {
590 custom.pop_back();
591 }
592 ImGui::SetNextItemWidth(100 * gui::NodeEditorApplication::windowFontRatio());
593 ImGui::InputText("##Name", &name, ImGuiInputTextFlags_CharsNoBlank);
594 static bool qual = true;
595 ImGui::Checkbox("Qualitative", &qual);
596 if (ImGui::IsItemHovered())
597 {
598 ImGui::SetTooltip("Means, that the colors are separated into distinct levels.\n"
599 "If unchecked, a color gradient will be applied.");
600 }
601
602 if (ImGui::Button("Add", ImVec2(100, 0)) && gp.ColormapData.GetIndex(name.c_str()) == -1)
603 {
604 ImPlot::AddColormap(name.c_str(), custom.Data, custom.Size, qual);
605 showEditColormap.push_back(false);
606 }
607
608 ImGui::EndGroup();
609 ImGui::SameLine();
610 ImGui::BeginGroup();
611 for (int c = 0; c < custom.Size; ++c)
612 {
613 ImGui::PushID(c);
614 if (ImGui::ColorEdit4("##Col1", &custom[c].x, ImGuiColorEditFlags_NoInputs))
615 {
616 }
617 if ((c + 1) % 12 != 0)
618 {
619 ImGui::SameLine();
620 }
621 ImGui::PopID();
622 }
623 ImGui::EndGroup();
624
625 ImGui::EndTabItem();
626 }
627 ImGui::EndTabBar();
628 }
629
630 ImGui::End();
631 }
632