7#include "absl/strings/match.h"
8#include "absl/strings/str_format.h"
9#include "absl/strings/str_split.h"
13#include "imgui/imgui.h"
32 ImGui::SetNextWindowSize(ImVec2(900, 700), ImGuiCond_FirstUseEver);
33 if (!ImGui::Begin(absl::StrFormat(
"%s Project Editor###ProjectFileEditor",
42 if (ImGui::BeginTable(
"ProjectEditorToolbar", 10,
43 ImGuiTableFlags_SizingFixedFit)) {
44 ImGui::TableNextColumn();
49 ImGui::TableNextColumn();
57 std::string(status.message().data(), status.message().size()),
63 ImGui::TableNextColumn();
66 ImGui::BeginDisabled();
67 if (ImGui::Button(absl::StrFormat(
"%s Save",
ICON_MD_SAVE).c_str())) {
73 std::string(status.message().data(), status.message().size()),
80 ImGui::TableNextColumn();
81 if (ImGui::Button(absl::StrFormat(
"%s Save As",
ICON_MD_SAVE_AS).c_str())) {
90 std::string(status.message().data(), status.message().size()),
96 ImGui::TableNextColumn();
99 ImGui::TableNextColumn();
102 absl::StrFormat(
"%s Import Labels",
ICON_MD_LABEL).c_str())) {
109 std::string(status.message().data(), status.message().size()),
113 if (ImGui::IsItemHovered()) {
114 ImGui::SetTooltip(
"Import labels from ZScream DefaultNames.txt");
117 ImGui::TableNextColumn();
124 ImGui::TableNextColumn();
127 ImGui::TableNextColumn();
129 ImGui::TextDisabled(
"%s",
filepath_.c_str());
131 ImGui::TextDisabled(
"No file loaded");
141 ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.3f, 0.2f, 0.2f, 0.5f));
142 if (ImGui::BeginChild(
"ValidationErrors", ImVec2(0, 100),
true)) {
143 ImGui::TextColored(ImVec4(1.0f, 0.4f, 0.4f, 1.0f),
146 ImGui::BulletText(
"%s", error.c_str());
150 ImGui::PopStyleColor();
154 ImVec2 editor_size = ImGui::GetContentRegionAvail();
162 std::string key = std::filesystem::path(
filepath).stem().string();
166 auto storage_or = platform::WasmStorage::LoadProject(key);
167 if (storage_or.ok()) {
172 return absl::OkStatus();
177 if (!file.is_open()) {
178 return absl::InvalidArgumentError(
179 absl::StrFormat(
"Cannot open file: %s",
filepath));
182 std::stringstream buffer;
183 buffer << file.rdbuf();
192 return absl::OkStatus();
197 return absl::InvalidArgumentError(
"No file path specified");
206 if (!absl::EndsWith(final_path,
".yaze")) {
207 final_path +=
".yaze";
211 std::string key = std::filesystem::path(final_path).stem().string();
215 auto storage_status =
217 if (!storage_status.ok()) {
218 return storage_status;
225 return absl::OkStatus();
227 std::ofstream file(final_path);
228 if (!file.is_open()) {
229 return absl::InvalidArgumentError(
230 absl::StrFormat(
"Cannot create file: %s", final_path));
244 return absl::OkStatus();
250 const char* template_content = R
"(# yaze Project File
269ollama_host=http://localhost:11434
270use_custom_prompt=false
274rom_backup_folder=backups
277patches_folder=patches
278labels_filename=labels.txt
279symbols_filename=symbols.txt
284# REMOVED: kLogInstructions - DisassemblyViewer is always active
286kSaveGraphicsSheet=true
287kLoadCustomOverworld=false
292autosave_interval_secs=300
299asm_entry_point=asm/main.asm
305persist_custom_music=true
325 std::vector<std::string> lines = absl::StrSplit(content,
'\n');
327 std::string current_section;
330 for (
const auto& line : lines) {
332 std::string trimmed = std::string(absl::StripAsciiWhitespace(line));
335 if (trimmed.empty() || trimmed[0] ==
'#')
339 if (trimmed[0] ==
'[' && trimmed[trimmed.size() - 1] ==
']') {
340 current_section = trimmed.substr(1, trimmed.size() - 2);
343 if (current_section !=
"project" && current_section !=
"files" &&
344 current_section !=
"feature_flags" &&
345 current_section !=
"workspace" &&
346 current_section !=
"workspace_settings" &&
347 current_section !=
"build" && current_section !=
"agent_settings" &&
348 current_section !=
"music" && current_section !=
"keybindings" &&
349 current_section !=
"editor_visibility") {
351 "Line %d: Unknown section [%s]", line_num, current_section));
357 size_t equals_pos = trimmed.find(
'=');
358 if (equals_pos == std::string::npos) {
360 "Line %d: Invalid format, expected key=value", line_num));
374 ImGui::TextColored(ImVec4(1.0f, 0.3f, 0.3f, 1.0f),
"Validation Errors:");
376 ImGui::BulletText(
"%s", error.c_str());
382 return absl::UnimplementedError(
383 "File-based label import is not supported in the web build");
386 return absl::FailedPreconditionError(
387 "No project loaded. Open a project first.");
393 return absl::CancelledError(
"No file selected");
397 std::ifstream input_file(file);
398 if (!input_file.is_open()) {
399 return absl::InvalidArgumentError(
400 absl::StrFormat(
"Cannot open file: %s", file));
403 std::stringstream buffer;
404 buffer << input_file.rdbuf();
void SetShowWhitespaces(bool aValue)
std::string GetText() const
void Render(const char *aTitle, const ImVec2 &aSize=ImVec2(), bool aBorder=false)
void SetText(const std::string &aText)
void SetTabSize(int aValue)
void SetLanguageDefinition(const LanguageDefinition &aLanguageDef)
void ApplySyntaxHighlighting()
ToastManager * toast_manager_
absl::Status SaveFileAs(const std::string &filepath)
Save to a new file path.
absl::Status LoadFile(const std::string &filepath)
Load a project file into the editor.
void NewFile()
Create a new empty project file.
bool IsModified() const
Get whether the file has unsaved changes.
std::vector< std::string > validation_errors_
absl::Status SaveFile()
Save the current editor contents to disk.
absl::Status ImportLabelsFromZScream()
Import labels from a ZScream DefaultNames.txt file.
project::YazeProject * project_
void ShowValidationErrors()
const std::string & filepath() const
Get the current filepath.
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
static RecentFilesManager & GetInstance()
static std::string ShowSaveFileDialog(const std::string &default_name="", const std::string &default_extension="")
ShowSaveFileDialog opens a save file dialog and returns the selected filepath. Uses global feature fl...
static std::string ShowOpenFileDialog()
ShowOpenFileDialog opens a file dialog and returns the selected filepath. Uses global feature flag to...
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_CHECK_CIRCLE
#define ICON_MD_DESCRIPTION
static const LanguageDefinition & C()
absl::Status ImportLabelsFromZScreamContent(const std::string &content)
Import labels from ZScream format content directly.