EchoMap 2026-07-25 6d3977c
An experimental cross-platform digital signal processing application for sound-source localisation.
Loading...
Searching...
No Matches
MapSourcesModal.cpp
Go to the documentation of this file.
1
9
10#include "MapSourcesModal.hpp"
11
12#include "../../EchoMap.hpp"
17
18namespace echomap
19{
20
21MapSourcesModal::MapSourcesModal(
22 EchoMap* const app,
23 const PartialProject* const project
24) :
25 panel_name(std::string("Upload External Files") + get_imgui_stable_name()),
26 app(app),
27 project(project)
28{
29}
30
31void MapSourcesModal::draw() noexcept // TODO remove noexcepts where necessary.
32{
33 if (project->observe_unloaded_signals().empty())
34 return;
35
36 if (std::exchange(should_open, false))
37 ImGui::OpenPopup(get_imgui_name());
38
39 ImGui::SetNextWindowSize(default_modal_size, ImGuiCond_Appearing);
40
41 if (ImGui::BeginPopupModal(
42 get_imgui_name(), nullptr,
43 ImGuiWindowFlags_AlwaysAutoResize
44 )) {
45 ImGui::PushID("UploadExternalModal");
46
47 draw_preamble();
48
49 // The remaining number of signals for which there is no given path in VFS, decremented as we enumerate.
50 auto unmapped_count = project->observe_unloaded_signals().size();
51
52 if (ImGui::BeginTable("##UploadTable", 5, table_flags)) {
53 ImGui::TableSetupColumn("##UploadButton", ImGuiTableColumnFlags_WidthFixed, button_size.x);
54 ImGui::TableSetupColumn("Indicated Path", ImGuiTableColumnFlags_WidthStretch);
55 ImGui::TableSetupColumn("Signal Name", ImGuiTableColumnFlags_WidthStretch);
56 ImGui::TableSetupColumn("Channel Number", ImGuiTableColumnFlags_WidthStretch);
57 ImGui::TableSetupColumn("Given Path", ImGuiTableColumnFlags_WidthStretch);
58 ImGui::TableHeadersRow();
59
60 for (const auto& [external_path, mapping_info] : project->observe_unloaded_signals())
61 if (draw_table_entry(
62 external_path,
63 mapping_info.first,
64 std::views::transform(mapping_info.second, [](const std::unique_ptr<SignalFactory>& ptr) {
65 return ptr.get();
66 })
67 ))
68
69 --unmapped_count;
70
71 ImGui::EndTable();
72 }
73
74 draw_buttons(unmapped_count == 0);
75
76 ImGui::PopID();
77 ImGui::EndPopup();
78 }
79}
80
81const char* MapSourcesModal::get_imgui_name() const noexcept
82{
83 return panel_name.c_str();
84}
85
86void MapSourcesModal::reshow() noexcept
87{
88 should_open = true;
89}
90
92 const PartialProject* new_project
93)
94{
95 std::ignore = new_project;
96}
97
98const char* MapSourcesModal::get_imgui_stable_name() noexcept
99{
100 return "###IndividualUploadModal";
101}
102
103void MapSourcesModal::draw_preamble() const noexcept
104{
105 ImGui::TextWrapped(
106 "%s contains references to externally sourced signals. Browser security requires that each externally "
107 "sourced file is uploaded separately.",
108 project->get_imgui_name()
109 );
110
111 ImGui::Spacing();
112 ImGui::Separator();
113
114 ImGui::TextWrapped(
115 "Upload all missing files to complete the mapping, and press Continue.\n\nCancelling the operation "
116 "will abort the load and revert back to the previously loaded project, if applicable."
117 );
118
119 ImGui::Spacing();
120 ImGui::Separator();
121 ImGui::Spacing();
122}
123
124void MapSourcesModal::draw_buttons(
125 const bool are_all_mapped
126)
127{
128 ImGui::Spacing();
129 ImGui::Separator();
130 ImGui::Spacing();
131
132 if (ImGui::Button("Cancel", button_size)) {
133 app->notify(CancelProjectLoadNotification(project->get_id()));
134 ImGui::CloseCurrentPopup();
135 should_open = false;
136 }
137
138 ImGui::SameLine();
139
140 if (are_all_mapped) {
141 if (ImGui::Button("Continue", button_size)) {
142 app->notify(CompleteProjectLoadNotification(project->get_id()));
143 ImGui::CloseCurrentPopup();
144 }
145 } else {
146 ImGui::BeginDisabled();
147 ImGui::Button("Continue", button_size);
148 ImGui::SetItemTooltip("To continue, provide mappings for all unloaded externally sourced signals.");
149 ImGui::EndDisabled();
150 }
151}
152
153bool MapSourcesModal::draw_table_entry(
154 const std::filesystem::path& external_path,
156 SignalFactoryRange auto&& factories
157) const noexcept
158{
159 ImGui::PushID(external_path.c_str());
160 ImGui::TableNextRow();
161 ImGui::TableNextColumn();
162
163 const auto& padding = ImGui::GetStyle().CellPadding;
164 ImGui::SetCursorPos({ImGui::GetCursorPosX() - padding.x, ImGui::GetCursorPosY() - padding.y});
165 ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, upload_button_frame_padding);
166
167 if (ImGui::Button("Upload", ImVec2(button_size.x + 2 * padding.x, button_size.y)))
168 ActionController::register_vfs_mapping(project->get_id(), external_path);
169
170 ImGui::PopStyleVar();
171
172 ImGui::TableNextColumn();
173 ImGui::TextUnformatted(external_path.c_str());
174
175 bool is_first = true;
176 bool is_mapped = false;
177
178 for (const auto signal_factory : factories | std::views::filter([](auto&& ptr) {
179 return ptr;
180 })) {
181 if (!is_first)
182 ImGui::TableNextRow();
183
184 ImGui::TableSetColumnIndex(2);
185
186 const auto& signal = signal_factory->observe_signal();
187 ImGui::PushID(signal.get_imgui_name());
188
189 ImGui::TextUnformatted(signal.get_imgui_name());
190 ImGui::TableNextColumn();
191 const auto formatted_channel_num = std::to_string(signal.observe_source()->channel);
192 ImGui::TextUnformatted(formatted_channel_num.c_str());
193 ImGui::TableNextColumn();
194
195 if (is_first) {
196 const auto& given_path = vfs_path;
197 if (given_path.has_value()) {
198 ImGui::TextUnformatted(given_path->c_str());
199 is_mapped = true;
200 } else
201 ImGui::TextUnformatted("Not provided");
202
203 is_first = false;
204 }
205
206 ImGui::PopID();
207 }
208
209 ImGui::PopID();
210 return is_mapped;
211}
212
213} // namespace echomap
ActionController specification.
AllNotifications specification.
EchoMap class specification.
IndividualUploadModal specification.
PartialProject specification.
Wave file specification.
The EchoMap maintains state for the application including WebGPU and Dear ImGui context,...
Definition EchoMap.hpp:35
void draw() noexcept override
Draw the panel to the active rendering context.
void change_active_project(const PartialProject *new_project) override
Do nothing.
const char * get_imgui_name() const noexcept override
Retrieves the name of the IPanel for Dear ImGui API functions.
A Project with semantics for expressing an incomplete set of owned Signal objects.
T exchange(T... args)
The main EchoMap outermost namespace for all non-exported symbols.
T signal(T... args)
T to_string(T... args)