EchoMap 2026-07-25 6d3977c
An experimental cross-platform digital signal processing application for sound-source localisation.
Loading...
Searching...
No Matches
echomap::MapSourcesModal Class Referencefinal

Provides a modal IPanel to map externally sourced Signal objects to separately uploaded files. More...

#include <MapSourcesModal.hpp>

Inheritance diagram for echomap::MapSourcesModal:
[legend]

Public Member Functions

 MapSourcesModal (EchoMap *app, const PartialProject *project)
void draw () noexcept override
 Draw the panel to the active rendering context.
const char * get_imgui_name () const noexcept override
 Retrieves the name of the IPanel for Dear ImGui API functions.
void reshow () noexcept
void change_active_project (const PartialProject *new_project) override
 Do nothing.
Public Member Functions inherited from echomap::IPanel
virtual void update_gpu (const wgpu::CommandEncoder &command_encoder)
 Delegate work to the GPU via the WebGPU platform.

Static Public Member Functions

static const char * get_imgui_stable_name () noexcept

Private Member Functions

void draw_preamble () const noexcept
bool draw_table_entry (const std::filesystem::path &external_path, const std::optional< std::filesystem::path > &vfs_path, SignalFactoryRange auto &&factories) const noexcept
void draw_buttons (bool are_all_mapped)

Private Attributes

std::string panel_name
EchoMapapp
const PartialProjectproject
bool should_open = true

Static Private Attributes

static constexpr ImVec2 upload_button_frame_padding {0.0f, 0.0f}
static constexpr ImVec2 default_modal_size {500.0f, 300.0f}

Additional Inherited Members

Static Protected Attributes inherited from echomap::IPanel
static constexpr ImVec2 button_size {80.0f, 20.0f}
static constexpr auto table_flags

Detailed Description

Provides a modal IPanel to map externally sourced Signal objects to separately uploaded files.

This is most useful in browser (WebAssembly VFS) contexts where the application cannot interrogate the file system directly.

Definition at line 34 of file MapSourcesModal.hpp.

Constructor & Destructor Documentation

◆ MapSourcesModal()

echomap::MapSourcesModal::MapSourcesModal ( EchoMap * app,
const PartialProject * project )
explicit

Definition at line 21 of file MapSourcesModal.cpp.

24 :
25 panel_name(std::string("Upload External Files") + get_imgui_stable_name()),
26 app(app),
27 project(project)
28{
29}

Member Function Documentation

◆ change_active_project()

void echomap::MapSourcesModal::change_active_project ( const PartialProject * new_project)
overridevirtual

Do nothing.

THe active Project may be changed in the background, but that shouldn't interfere with an active modal. This modal will also typically relate to an unloaded (or partially loaded) Project, not the active one.

Parameters
new_projectIgnored.

Implements echomap::IWebPanel.

Definition at line 91 of file MapSourcesModal.cpp.

94{
95 std::ignore = new_project;
96}

◆ draw()

void echomap::MapSourcesModal::draw ( )
overridevirtualnoexcept

Draw the panel to the active rendering context.

Implements echomap::IPanel.

Definition at line 31 of file MapSourcesModal.cpp.

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}
const char * get_imgui_name() const noexcept override
Retrieves the name of the IPanel for Dear ImGui API functions.
T exchange(T... args)

◆ draw_buttons()

void echomap::MapSourcesModal::draw_buttons ( bool are_all_mapped)
private

Definition at line 124 of file MapSourcesModal.cpp.

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}

◆ draw_preamble()

void echomap::MapSourcesModal::draw_preamble ( ) const
privatenoexcept

Definition at line 103 of file MapSourcesModal.cpp.

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}

◆ draw_table_entry()

bool echomap::MapSourcesModal::draw_table_entry ( const std::filesystem::path & external_path,
const std::optional< std::filesystem::path > & vfs_path,
SignalFactoryRange auto && factories ) const
privatenoexcept

Definition at line 153 of file MapSourcesModal.cpp.

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}
static void register_vfs_mapping(const std::size_t project_id, const std::filesystem::path &external)
T signal(T... args)
T to_string(T... args)

◆ get_imgui_name()

const char * echomap::MapSourcesModal::get_imgui_name ( ) const
nodiscardoverridevirtualnoexcept

Retrieves the name of the IPanel for Dear ImGui API functions.

Returns
The human-readable name of the window as a NULL-terminated C string.

Implements echomap::IPanel.

Definition at line 81 of file MapSourcesModal.cpp.

82{
83 return panel_name.c_str();
84}

◆ get_imgui_stable_name()

const char * echomap::MapSourcesModal::get_imgui_stable_name ( )
staticnoexcept

Definition at line 98 of file MapSourcesModal.cpp.

99{
100 return "###IndividualUploadModal";
101}

◆ reshow()

void echomap::MapSourcesModal::reshow ( )
noexcept

Definition at line 86 of file MapSourcesModal.cpp.

87{
88 should_open = true;
89}

Member Data Documentation

◆ app

EchoMap* echomap::MapSourcesModal::app
private

Definition at line 75 of file MapSourcesModal.hpp.

◆ default_modal_size

ImVec2 echomap::MapSourcesModal::default_modal_size {500.0f, 300.0f}
staticconstexprprivate

Definition at line 62 of file MapSourcesModal.hpp.

62{500.0f, 300.0f};

◆ panel_name

std::string echomap::MapSourcesModal::panel_name
private

Definition at line 74 of file MapSourcesModal.hpp.

◆ project

const PartialProject* echomap::MapSourcesModal::project
private

Definition at line 76 of file MapSourcesModal.hpp.

◆ should_open

bool echomap::MapSourcesModal::should_open = true
private

Definition at line 77 of file MapSourcesModal.hpp.

◆ upload_button_frame_padding

ImVec2 echomap::MapSourcesModal::upload_button_frame_padding {0.0f, 0.0f}
staticconstexprprivate

Definition at line 61 of file MapSourcesModal.hpp.

61{0.0f, 0.0f};

The documentation for this class was generated from the following files: