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