INSTINCT Code Coverage Report


Directory: src/
File: internal/gui/widgets/TimeEdit.cpp
Date: 2025-02-07 16:54:41
Exec Total Coverage
Lines: 4 77 5.2%
Functions: 1 5 20.0%
Branches: 0 124 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 "TimeEdit.hpp"
10
11 #include <imgui.h>
12 #include <fmt/core.h>
13
14 #include "internal/gui/widgets/imgui_ex.hpp"
15 #include "internal/gui/widgets/EnumCombo.hpp"
16
17 namespace NAV
18 {
19
20 const char* to_string(gui::widgets::TimeEditFormat::Format timeEditFormat)
21 {
22 switch (timeEditFormat)
23 {
24 case gui::widgets::TimeEditFormat::Format::YMDHMS:
25 return "YMDHMS";
26 case gui::widgets::TimeEditFormat::Format::GPSWeekToW:
27 return "GPS Week/ToW";
28 case gui::widgets::TimeEditFormat::Format::COUNT:
29 break;
30 }
31 return "";
32 }
33
34 namespace gui::widgets
35 {
36 namespace
37 {
38
39 /// @brief Shows a ComboBox to select the time edit format
40 /// @param[in] label Label to show beside the combo box. This has to be a unique id for ImGui.
41 /// @param[in] format Reference to the format to select
42 bool ComboTimeEditFormat(const char* label, TimeEditFormat::Format& format)
43 {
44 return gui::widgets::EnumCombo(label, format);
45 }
46
47 } // namespace
48 } // namespace gui::widgets
49
50 } // namespace NAV
51
52 bool NAV::gui::widgets::TimeEdit(const char* str_id, InsTime& insTime, TimeEditFormat& timeEditFormat, float itemWidth)
53 {
54 bool changes = false;
55 bool edited = false;
56
57 ImGui::BeginGroup();
58
59 ImGui::SetNextItemWidth(140.0F);
60 if (ComboTimeEditFormat(fmt::format("##ComboTimeEditFormat {}", str_id).c_str(), timeEditFormat.format))
61 {
62 changes = true;
63 }
64 ImGui::SameLine();
65 ImGui::SetNextItemWidth(80.0F);
66 if (ComboTimeSystem(fmt::format("##ComboTimeSystem {}", str_id).c_str(), timeEditFormat.system))
67 {
68 changes = true;
69 }
70
71 if (timeEditFormat.format == TimeEditFormat::Format::YMDHMS)
72 {
73 auto ymdhms = insTime.toYMDHMS(timeEditFormat.system);
74
75 int year = ymdhms.year;
76 int month = ymdhms.month;
77 int day = ymdhms.day;
78 int hour = ymdhms.hour;
79 int min = ymdhms.min;
80 auto sec = static_cast<double>(ymdhms.sec);
81
82 ImGui::SetNextItemWidth(itemWidth);
83 if (ImGui::InputInt(fmt::format("Year##{}", str_id).c_str(), &year, 0, 0)) { edited = true; }
84 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
85
86 ImGui::SetNextItemWidth(itemWidth);
87 if (ImGui::InputIntL(fmt::format("Month##{}", str_id).c_str(), &month, 1, InsTimeUtil::MONTHS_PER_YEAR, 0, 0)) { edited = true; }
88 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
89
90 ImGui::SetNextItemWidth(itemWidth);
91 if (ImGui::InputIntL(fmt::format("Day##{}", str_id).c_str(), &day, 1, InsTimeUtil::daysInMonth(month, year), 0, 0)) { edited = true; }
92 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
93
94 ImGui::SetNextItemWidth(itemWidth);
95 if (ImGui::InputIntL(fmt::format("Hour##{}", str_id).c_str(), &hour, 0, InsTimeUtil::HOURS_PER_DAY - 1, 0, 0)) { edited = true; }
96 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
97
98 ImGui::SetNextItemWidth(itemWidth);
99 if (ImGui::InputIntL(fmt::format("Min##{}", str_id).c_str(), &min, 0, InsTimeUtil::MINUTES_PER_HOUR - 1, 0, 0)) { edited = true; }
100 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
101
102 ImGui::SetNextItemWidth(itemWidth);
103 if (ImGui::InputDoubleL(fmt::format("Sec##{}", str_id).c_str(), &sec, 0, InsTimeUtil::SECONDS_PER_MINUTE - 1e-5, 0, 0, "%.6f")) { edited = true; }
104 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
105
106 if (changes || edited)
107 {
108 insTime = InsTime{ static_cast<uint16_t>(year), static_cast<uint16_t>(month), static_cast<uint16_t>(day),
109 static_cast<uint16_t>(hour), static_cast<uint16_t>(min), sec, timeEditFormat.system };
110 }
111 }
112 else // if (timeEditFormat == TimeEditFormat::Format::GPSWeekToW)
113 {
114 auto gpsWeekTow = insTime.toGPSweekTow(timeEditFormat.system);
115
116 int cycle = gpsWeekTow.gpsCycle;
117 int week = gpsWeekTow.gpsWeek;
118 auto tow = static_cast<double>(gpsWeekTow.tow);
119
120 ImGui::SetNextItemWidth(itemWidth);
121 if (ImGui::InputIntL(fmt::format("Cycle##{}", str_id).c_str(), &cycle, 0, std::numeric_limits<int>::max(), 0, 0)) { edited = true; }
122 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
123
124 ImGui::SetNextItemWidth(itemWidth);
125 if (ImGui::InputIntL(fmt::format("Week##{}", str_id).c_str(), &week, 0, InsTimeUtil::WEEKS_PER_GPS_CYCLE - 1, 0, 0)) { edited = true; }
126 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
127
128 ImGui::SetNextItemWidth(itemWidth);
129 if (ImGui::InputDoubleL(fmt::format("ToW [s]##{}", str_id).c_str(), &tow, 0, std::numeric_limits<double>::max(), 0, 0, "%.6f")) { edited = true; }
130 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
131
132 if (changes || edited)
133 {
134 insTime = InsTime{ cycle, week, tow, timeEditFormat.system };
135 }
136 }
137
138 ImGui::EndGroup();
139
140 return changes;
141 }
142
143 void NAV::gui::widgets::to_json(json& j, const TimeEditFormat& timeEditFormat)
144 {
145 j = json{
146 { "format", timeEditFormat.format },
147 { "system", timeEditFormat.system },
148 };
149 }
150
151 12 void NAV::gui::widgets::from_json(const json& j, TimeEditFormat& timeEditFormat)
152 {
153 12 j.at("format").get_to(timeEditFormat.format);
154 12 j.at("system").get_to(timeEditFormat.system);
155 12 }
156