yaze 0.2.0
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
assembly_editor.cc
Go to the documentation of this file.
1#include "assembly_editor.h"
2
3#include "ImGuiColorTextEdit/TextEditor.h"
4#include "ImGuiFileDialog/ImGuiFileDialog.h"
5#include "absl/strings/str_cat.h"
7#include "app/gui/icons.h"
8
9namespace yaze {
10namespace app {
11namespace editor {
12
14
15namespace {
16
17std::vector<std::string> RemoveIgnoredFiles(
18 const std::vector<std::string>& files,
19 const std::vector<std::string>& ignored_files) {
20 std::vector<std::string> filtered_files;
21 for (const auto& file : files) {
22 // Remove subdirectory files
23 if (file.find('/') != std::string::npos) {
24 continue;
25 }
26 // Make sure the file has an extension
27 if (file.find('.') == std::string::npos) {
28 continue;
29 }
30 if (std::find(ignored_files.begin(), ignored_files.end(), file) ==
31 ignored_files.end()) {
32 filtered_files.push_back(file);
33 }
34 }
35 return filtered_files;
36}
37
38core::FolderItem LoadFolder(const std::string& folder) {
39 // Check if .gitignore exists in the folder
40 std::ifstream gitignore(folder + "/.gitignore");
41 std::vector<std::string> ignored_files;
42 if (gitignore.good()) {
43 std::string line;
44 while (std::getline(gitignore, line)) {
45 if (line[0] == '#') {
46 continue;
47 }
48 if (line[0] == '!') {
49 // Ignore the file
50 continue;
51 }
52 ignored_files.push_back(line);
53 }
54 }
55
56 core::FolderItem current_folder;
57 current_folder.name = folder;
58 auto root_files = FileDialogWrapper::GetFilesInFolder(current_folder.name);
59 current_folder.files = RemoveIgnoredFiles(root_files, ignored_files);
60
61 for (const auto& subfolder :
63 core::FolderItem folder_item;
64 folder_item.name = subfolder;
65 std::string full_folder = current_folder.name + "/" + subfolder;
66 auto folder_files = FileDialogWrapper::GetFilesInFolder(full_folder);
67 for (const auto& files : folder_files) {
68 // Remove subdirectory files
69 if (files.find('/') != std::string::npos) {
70 continue;
71 }
72 // Make sure the file has an extension
73 if (files.find('.') == std::string::npos) {
74 continue;
75 }
76 if (std::find(ignored_files.begin(), ignored_files.end(), files) !=
77 ignored_files.end()) {
78 continue;
79 }
80 folder_item.files.push_back(files);
81 }
82
83 for (const auto& subdir :
85 core::FolderItem subfolder_item;
86 subfolder_item.name = subdir;
87 subfolder_item.files = FileDialogWrapper::GetFilesInFolder(subdir);
88 folder_item.subfolders.push_back(subfolder_item);
89 }
90 current_folder.subfolders.push_back(folder_item);
91 }
92
93 return current_folder;
94}
95
96} // namespace
97
98void AssemblyEditor::OpenFolder(const std::string& folder_path) {
99 current_folder_ = LoadFolder(folder_path);
100}
101
102void AssemblyEditor::Update(bool& is_loaded) {
103 ImGui::Begin("Assembly Editor", &is_loaded);
104 if (ImGui::BeginMenuBar()) {
105 DrawFileMenu();
106 DrawEditMenu();
107 ImGui::EndMenuBar();
108 }
109
110 auto cpos = text_editor_.GetCursorPosition();
112 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
113 cpos.mColumn + 1, text_editor_.GetTotalLines(),
114 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
115 text_editor_.CanUndo() ? "*" : " ",
116 text_editor_.GetLanguageDefinition().mName.c_str(),
117 current_file_.c_str());
118
119 text_editor_.Render("##asm_editor");
120 ImGui::End();
121}
122
124 ChangeActiveFile("assets/asm/template_song.asm");
125 auto cpos = text_editor_.GetCursorPosition();
127 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
128 cpos.mColumn + 1, text_editor_.GetTotalLines(),
129 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
130 text_editor_.CanUndo() ? "*" : " ",
131 text_editor_.GetLanguageDefinition().mName.c_str(),
132 current_file_.c_str());
133
134 text_editor_.Render("##asm_editor", ImVec2(0, 0));
135}
136
138 ImGui::BeginTable("##table_view", 2,
139 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
140 ImGuiTableFlags_Resizable);
141
142 // Table headers
143 ImGui::TableSetupColumn("Files", ImGuiTableColumnFlags_WidthFixed, 256.0f);
144 ImGui::TableSetupColumn("Editor", ImGuiTableColumnFlags_WidthStretch);
145
146 ImGui::TableHeadersRow();
147
148 // Table data
149 ImGui::TableNextRow();
150 ImGui::TableNextColumn();
151 if (current_folder_.name != "") {
153 } else {
154 if (ImGui::Button("Open Folder")) {
156 }
157 }
158
159 ImGui::TableNextColumn();
160
161 auto cpos = text_editor_.GetCursorPosition();
163 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
164 cpos.mColumn + 1, text_editor_.GetTotalLines(),
165 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
166 text_editor_.CanUndo() ? "*" : " ",
167 text_editor_.GetLanguageDefinition().mName.c_str(),
168 current_file_.c_str());
169
170 text_editor_.Render("##asm_editor");
171
172 ImGui::EndTable();
173}
174
176 if (ImGui::BeginChild("##current_folder", ImVec2(0, 0), true,
177 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
178 if (ImGui::BeginTable("##file_table", 2,
179 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
180 ImGuiTableFlags_Resizable |
181 ImGuiTableFlags_Sortable)) {
182 ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 256.0f);
183 ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthStretch);
184
185 ImGui::TableHeadersRow();
186
187 for (const auto& file : current_folder_.files) {
188 ImGui::TableNextRow();
189 ImGui::TableNextColumn();
190 if (ImGui::Selectable(file.c_str())) {
191 ChangeActiveFile(absl::StrCat(current_folder_.name, "/", file));
192 }
193 ImGui::TableNextColumn();
194 ImGui::Text("File");
195 }
196
197 for (const auto& subfolder : current_folder_.subfolders) {
198 ImGui::TableNextRow();
199 ImGui::TableNextColumn();
200 if (ImGui::TreeNode(subfolder.name.c_str())) {
201 for (const auto& file : subfolder.files) {
202 ImGui::TableNextRow();
203 ImGui::TableNextColumn();
204 if (ImGui::Selectable(file.c_str())) {
205 ChangeActiveFile(absl::StrCat(current_folder_.name, "/",
206 subfolder.name, "/", file));
207 }
208 ImGui::TableNextColumn();
209 ImGui::Text("File");
210 }
211 ImGui::TreePop();
212 } else {
213 ImGui::TableNextColumn();
214 ImGui::Text("Folder");
215 }
216 }
217
218 ImGui::EndTable();
219 }
220
221 ImGui::EndChild();
222 }
223}
224
226 static int next_tab_id = 0;
227
228 if (ImGui::BeginTabBar("AssemblyFileTabBar", ImGuiTabBarFlags_None)) {
229 if (ImGui::TabItemButton(ICON_MD_ADD, ImGuiTabItemFlags_None)) {
230 if (std::find(active_files_.begin(), active_files_.end(),
232 // Room is already open
233 next_tab_id++;
234 }
235 active_files_.push_back(next_tab_id++); // Add new tab
236 }
237
238 // Submit our regular tabs
239 for (int n = 0; n < active_files_.Size;) {
240 bool open = true;
241
242 if (ImGui::BeginTabItem(files_[active_files_[n]].data(), &open,
243 ImGuiTabItemFlags_None)) {
244 auto cpos = text_editor_.GetCursorPosition();
245 {
246 std::ifstream t(current_file_);
247 if (t.good()) {
248 std::string str((std::istreambuf_iterator<char>(t)),
249 std::istreambuf_iterator<char>());
250 text_editor_.SetText(str);
251 } else {
252 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
253 "Error opening file: %s\n", current_file_.c_str());
254 }
255 }
256 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
257 cpos.mColumn + 1, text_editor_.GetTotalLines(),
258 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
259 text_editor_.CanUndo() ? "*" : " ",
260 text_editor_.GetLanguageDefinition().mName.c_str(),
261 current_file_.c_str());
262
263 open_files_[active_files_[n]].Render("##asm_editor");
264 ImGui::EndTabItem();
265 }
266
267 if (!open)
268 active_files_.erase(active_files_.Data + n);
269 else
270 n++;
271 }
272
273 ImGui::EndTabBar();
274 }
275 ImGui::Separator();
276}
277
279 if (ImGui::BeginMenu("File")) {
280 if (ImGui::MenuItem("Open", "Ctrl+O")) {
281 ImGuiFileDialog::Instance()->OpenDialog(
282 "ChooseASMFileDlg", "Open ASM file", ".asm,.txt", ".");
283 }
284 if (ImGui::MenuItem("Save", "Ctrl+S")) {
285 // TODO: Implement this
286 }
287 ImGui::EndMenu();
288 }
289
290 if (ImGuiFileDialog::Instance()->Display("ChooseASMFileDlg")) {
291 if (ImGuiFileDialog::Instance()->IsOk()) {
292 ChangeActiveFile(ImGuiFileDialog::Instance()->GetFilePathName());
293 }
294 ImGuiFileDialog::Instance()->Close();
295 }
296}
297
299 if (ImGui::BeginMenu("Edit")) {
300 if (ImGui::MenuItem("Undo", "Ctrl+Z")) {
301 text_editor_.Undo();
302 }
303 if (ImGui::MenuItem("Redo", "Ctrl+Y")) {
304 text_editor_.Redo();
305 }
306 ImGui::Separator();
307 if (ImGui::MenuItem("Cut", "Ctrl+X")) {
308 text_editor_.Cut();
309 }
310 if (ImGui::MenuItem("Copy", "Ctrl+C")) {
311 text_editor_.Copy();
312 }
313 if (ImGui::MenuItem("Paste", "Ctrl+V")) {
314 text_editor_.Paste();
315 }
316 ImGui::Separator();
317 if (ImGui::MenuItem("Find", "Ctrl+F")) {
318 // TODO: Implement this.
319 }
320 ImGui::EndMenu();
321 }
322}
323
325 if (!file_is_loaded_) {
326 std::ifstream t(current_file_);
327 if (t.good()) {
328 std::string str((std::istreambuf_iterator<char>(t)),
329 std::istreambuf_iterator<char>());
330 text_editor_.SetText(str);
331 } else {
332 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error opening file: %s\n",
333 current_file_.c_str());
334 }
335 file_is_loaded_ = true;
336 }
337}
338
339absl::Status AssemblyEditor::Cut() {
340 text_editor_.Cut();
341 return absl::OkStatus();
342}
343
344absl::Status AssemblyEditor::Copy() {
345 text_editor_.Copy();
346 return absl::OkStatus();
347}
348
349absl::Status AssemblyEditor::Paste() {
350 text_editor_.Paste();
351 return absl::OkStatus();
352}
353
354absl::Status AssemblyEditor::Undo() {
355 text_editor_.Undo();
356 return absl::OkStatus();
357}
358
359absl::Status AssemblyEditor::Redo() {
360 text_editor_.Redo();
361 return absl::OkStatus();
362}
363
364absl::Status AssemblyEditor::Update() { return absl::OkStatus(); }
365
366} // namespace editor
367} // namespace app
368} // namespace yaze
static std::vector< std::string > GetSubdirectoriesInFolder(const std::string &folder_path)
static std::string ShowOpenFolderDialog()
ShowOpenFolderDialog opens a file dialog and returns the selected folder path.
static std::vector< std::string > GetFilesInFolder(const std::string &folder_path)
void ChangeActiveFile(const std::string_view &filename)
std::vector< TextEditor > open_files_
void OpenFolder(const std::string &folder_path)
std::vector< std::string > files_
#define ICON_MD_ADD
Definition icons.h:84
std::vector< std::string > RemoveIgnoredFiles(const std::vector< std::string > &files, const std::vector< std::string > &ignored_files)
core::FolderItem LoadFolder(const std::string &folder)
Definition common.cc:22
std::vector< FolderItem > subfolders
Definition common.h:280
std::vector< std::string > files
Definition common.h:281