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::editor {
13
15
16namespace {
17
18std::vector<std::string> RemoveIgnoredFiles(
19 const std::vector<std::string>& files,
20 const std::vector<std::string>& ignored_files) {
21 std::vector<std::string> filtered_files;
22 for (const auto& file : files) {
23 // Remove subdirectory files
24 if (file.contains('/')) {
25 continue;
26 }
27 // Make sure the file has an extension
28 if (!file.contains('.')) {
29 continue;
30 }
31 if (std::ranges::find(ignored_files, file) == ignored_files.end()) {
32 filtered_files.push_back(file);
33 }
34 }
35 return filtered_files;
36}
37
38FolderItem 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 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 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.contains('/')) {
70 continue;
71 }
72 // Make sure the file has an extension
73 if (!files.contains('.')) {
74 continue;
75 }
76 if (std::ranges::find(ignored_files, files) != ignored_files.end()) {
77 continue;
78 }
79 folder_item.files.push_back(files);
80 }
81
82 for (const auto& subdir :
84 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
98 // Set the language definition
99}
100
101absl::Status AssemblyEditor::Load() { return absl::OkStatus(); }
102
103void AssemblyEditor::OpenFolder(const std::string& folder_path) {
104 current_folder_ = LoadFolder(folder_path);
105}
106
107void AssemblyEditor::Update(bool& is_loaded) {
108 ImGui::Begin("Assembly Editor", &is_loaded);
109 if (ImGui::BeginMenuBar()) {
110 DrawFileMenu();
111 DrawEditMenu();
112 ImGui::EndMenuBar();
113 }
114
115 auto cpos = text_editor_.GetCursorPosition();
117 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
118 cpos.mColumn + 1, text_editor_.GetTotalLines(),
119 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
120 text_editor_.CanUndo() ? "*" : " ",
121 text_editor_.GetLanguageDefinition().mName.c_str(),
122 current_file_.c_str());
123
124 text_editor_.Render("##asm_editor");
125 ImGui::End();
126}
127
129 auto cpos = text_editor_.GetCursorPosition();
131 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
132 cpos.mColumn + 1, text_editor_.GetTotalLines(),
133 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
134 text_editor_.CanUndo() ? "*" : " ",
135 text_editor_.GetLanguageDefinition().mName.c_str(),
136 current_file_.c_str());
137
138 text_editor_.Render("##asm_editor", ImVec2(0, 0));
139}
140
142 ImGui::BeginTable("##table_view", 2,
143 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
144 ImGuiTableFlags_Resizable);
145
146 // Table headers
147 ImGui::TableSetupColumn("Files", ImGuiTableColumnFlags_WidthFixed, 256.0f);
148 ImGui::TableSetupColumn("Editor", ImGuiTableColumnFlags_WidthStretch);
149
150 ImGui::TableHeadersRow();
151
152 // Table data
153 ImGui::TableNextRow();
154 ImGui::TableNextColumn();
155 if (current_folder_.name != "") {
157 } else {
158 if (ImGui::Button("Open Folder")) {
160 }
161 }
162
163 ImGui::TableNextColumn();
164
165 auto cpos = text_editor_.GetCursorPosition();
167 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
168 cpos.mColumn + 1, text_editor_.GetTotalLines(),
169 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
170 text_editor_.CanUndo() ? "*" : " ",
171 text_editor_.GetLanguageDefinition().mName.c_str(),
172 current_file_.c_str());
173
174 text_editor_.Render("##asm_editor");
175
176 ImGui::EndTable();
177}
178
180 if (ImGui::BeginChild("##current_folder", ImVec2(0, 0), true,
181 ImGuiWindowFlags_AlwaysVerticalScrollbar)) {
182 if (ImGui::BeginTable("##file_table", 2,
183 ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg |
184 ImGuiTableFlags_Resizable |
185 ImGuiTableFlags_Sortable)) {
186 ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed, 256.0f);
187 ImGui::TableSetupColumn("Type", ImGuiTableColumnFlags_WidthStretch);
188
189 ImGui::TableHeadersRow();
190
191 for (const auto& file : current_folder_.files) {
192 ImGui::TableNextRow();
193 ImGui::TableNextColumn();
194 if (ImGui::Selectable(file.c_str())) {
195 ChangeActiveFile(absl::StrCat(current_folder_.name, "/", file));
196 }
197 ImGui::TableNextColumn();
198 ImGui::Text("File");
199 }
200
201 for (const auto& subfolder : current_folder_.subfolders) {
202 ImGui::TableNextRow();
203 ImGui::TableNextColumn();
204 if (ImGui::TreeNode(subfolder.name.c_str())) {
205 for (const auto& file : subfolder.files) {
206 ImGui::TableNextRow();
207 ImGui::TableNextColumn();
208 if (ImGui::Selectable(file.c_str())) {
209 ChangeActiveFile(absl::StrCat(current_folder_.name, "/",
210 subfolder.name, "/", file));
211 }
212 ImGui::TableNextColumn();
213 ImGui::Text("File");
214 }
215 ImGui::TreePop();
216 } else {
217 ImGui::TableNextColumn();
218 ImGui::Text("Folder");
219 }
220 }
221
222 ImGui::EndTable();
223 }
224
225 ImGui::EndChild();
226 }
227}
228
230 static int next_tab_id = 0;
231
232 if (ImGui::BeginTabBar("AssemblyFileTabBar", ImGuiTabBarFlags_None)) {
233 if (ImGui::TabItemButton(ICON_MD_ADD, ImGuiTabItemFlags_None)) {
234 if (std::ranges::find(active_files_, current_file_id_) !=
235 active_files_.end()) {
236 // Room is already open
237 next_tab_id++;
238 }
239 active_files_.push_back(next_tab_id++); // Add new tab
240 }
241
242 // Submit our regular tabs
243 for (int n = 0; n < active_files_.Size;) {
244 bool open = true;
245
246 if (ImGui::BeginTabItem(files_[active_files_[n]].data(), &open,
247 ImGuiTabItemFlags_None)) {
248 auto cpos = text_editor_.GetCursorPosition();
249 {
250 std::ifstream t(current_file_);
251 if (t.good()) {
252 std::string str((std::istreambuf_iterator<char>(t)),
253 std::istreambuf_iterator<char>());
254 text_editor_.SetText(str);
255 } else {
256 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
257 "Error opening file: %s\n", current_file_.c_str());
258 }
259 }
260 ImGui::Text("%6d/%-6d %6d lines | %s | %s | %s | %s", cpos.mLine + 1,
261 cpos.mColumn + 1, text_editor_.GetTotalLines(),
262 text_editor_.IsOverwrite() ? "Ovr" : "Ins",
263 text_editor_.CanUndo() ? "*" : " ",
264 text_editor_.GetLanguageDefinition().mName.c_str(),
265 current_file_.c_str());
266
267 open_files_[active_files_[n]].Render("##asm_editor");
268 ImGui::EndTabItem();
269 }
270
271 if (!open)
272 active_files_.erase(active_files_.Data + n);
273 else
274 n++;
275 }
276
277 ImGui::EndTabBar();
278 }
279 ImGui::Separator();
280}
281
283 if (ImGui::BeginMenu("File")) {
284 if (ImGui::MenuItem("Open", "Ctrl+O")) {
286 ChangeActiveFile(filename);
287 }
288 if (ImGui::MenuItem("Save", "Ctrl+S")) {
289 // TODO: Implement this
290 }
291 ImGui::EndMenu();
292 }
293}
294
296 if (ImGui::BeginMenu("Edit")) {
297 if (ImGui::MenuItem("Undo", "Ctrl+Z")) {
298 text_editor_.Undo();
299 }
300 if (ImGui::MenuItem("Redo", "Ctrl+Y")) {
301 text_editor_.Redo();
302 }
303 ImGui::Separator();
304 if (ImGui::MenuItem("Cut", "Ctrl+X")) {
305 text_editor_.Cut();
306 }
307 if (ImGui::MenuItem("Copy", "Ctrl+C")) {
308 text_editor_.Copy();
309 }
310 if (ImGui::MenuItem("Paste", "Ctrl+V")) {
311 text_editor_.Paste();
312 }
313 ImGui::Separator();
314 if (ImGui::MenuItem("Find", "Ctrl+F")) {
315 // TODO: Implement this.
316 }
317 ImGui::EndMenu();
318 }
319}
320
322 if (!file_is_loaded_) {
323 std::ifstream t(current_file_);
324 if (t.good()) {
325 std::string str((std::istreambuf_iterator<char>(t)),
326 std::istreambuf_iterator<char>());
327 text_editor_.SetText(str);
328 } else {
329 SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error opening file: %s\n",
330 current_file_.c_str());
331 }
332 file_is_loaded_ = true;
333 }
334}
335
336absl::Status AssemblyEditor::Cut() {
337 text_editor_.Cut();
338 return absl::OkStatus();
339}
340
341absl::Status AssemblyEditor::Copy() {
342 text_editor_.Copy();
343 return absl::OkStatus();
344}
345
346absl::Status AssemblyEditor::Paste() {
347 text_editor_.Paste();
348 return absl::OkStatus();
349}
350
351absl::Status AssemblyEditor::Undo() {
352 text_editor_.Undo();
353 return absl::OkStatus();
354}
355
356absl::Status AssemblyEditor::Redo() {
357 text_editor_.Redo();
358 return absl::OkStatus();
359}
360
361absl::Status AssemblyEditor::Update() { return absl::OkStatus(); }
362
363} // namespace yaze::editor
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.
std::vector< FolderItem > subfolders
std::vector< std::string > files