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