3#include "absl/strings/str_format.h"
9#include "imgui/imgui.h"
12#include "yaze_config.h"
22 return ImVec4(0.45f, 0.70f, 0.95f, 1.0f);
24 return ImVec4(0.35f, 0.80f, 0.45f, 1.0f);
26 return ImVec4(0.90f, 0.35f, 0.35f, 1.0f);
48 const char* fallback_icon) {
49 if (!status.visible) {
56 status.summary.empty() ? status.label.c_str() : status.summary.c_str());
57 if (!status.detail.empty()) {
58 ImGui::TextWrapped(
"%s", status.detail.c_str());
60 if (!status.output_tail.empty()) {
61 ImGui::TextWrapped(
"%s", status.output_tail.c_str());
69 ImGui::TextDisabled(
"No project loaded");
72 "Open a .yaze project file or create a new project to access "
73 "project management features.");
103 if (project_version.empty()) {
109 project_version.c_str());
110 if (ImGui::IsItemHovered()) {
111 ImGui::SetTooltip(
"Project saved with v%s; running v%s",
115 ImGui::Text(
"%s", project_version.c_str());
126 ImGuiSelectableFlags_None,
127 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
133 if (ImGui::IsItemHovered()) {
134 ImGui::SetTooltip(
"Click to copy path");
141 static char name_buffer[256] = {};
142 if (name_buffer[0] ==
'\0' && !
project_->
name.empty()) {
143 strncpy(name_buffer,
project_->
name.c_str(),
sizeof(name_buffer) - 1);
145 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
146 if (ImGui::InputText(
"##project_name", name_buffer,
sizeof(name_buffer))) {
153 static char author_buffer[256] = {};
156 sizeof(author_buffer) - 1);
158 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
159 if (ImGui::InputText(
"##author", author_buffer,
sizeof(author_buffer))) {
166 static char desc_buffer[1024] = {};
169 sizeof(desc_buffer) - 1);
171 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
172 if (ImGui::InputTextMultiline(
"##description", desc_buffer,
173 sizeof(desc_buffer), ImVec2(0, 60))) {
186 "Primary data lives under the .yaze root. Click any path to copy it.");
190 if (!app_root.ok()) {
193 "Storage unavailable: %s",
194 std::string(app_root.status().message()).c_str());
198 std::vector<std::pair<const char*, std::filesystem::path>> locations = {
200 {
"Projects", *app_root /
"projects"},
201 {
"Layouts", *app_root /
"layouts"},
202 {
"Workspaces", *app_root /
"workspaces"},
203 {
"Logs", *app_root /
"logs"},
204 {
"Agent", *app_root /
"agent"}};
207 if (temp_root.ok()) {
208 locations.emplace_back(
"Temp", *temp_root);
211 if (ImGui::BeginTable(
"##storage_locations", 2,
212 ImGuiTableFlags_RowBg | ImGuiTableFlags_BordersInnerV |
213 ImGuiTableFlags_SizingStretchProp)) {
214 ImGui::TableSetupColumn(
"Location", ImGuiTableColumnFlags_WidthFixed,
216 ImGui::TableSetupColumn(
"Path", ImGuiTableColumnFlags_WidthStretch);
217 for (
const auto& entry : locations) {
218 ImGui::TableNextRow();
219 ImGui::TableNextColumn();
221 ImGui::TableNextColumn();
222 const std::string display_path =
224 ImGui::PushID(entry.first);
225 if (ImGui::Selectable(display_path.c_str(),
false,
226 ImGuiSelectableFlags_SpanAllColumns)) {
227 ImGui::SetClipboardText(display_path.c_str());
232 if (ImGui::IsItemHovered()) {
233 ImGui::SetTooltip(
"Click to copy");
256 size_t pos = filename.find_last_of(
"/\\");
257 if (pos != std::string::npos) {
258 filename = filename.substr(pos + 1);
260 ImGui::Text(
"%s", filename.c_str());
261 if (ImGui::IsItemHovered()) {
270 ImGui::Text(
"%s",
rom_->
title().c_str());
274 ImGui::Text(
"%.2f MB",
static_cast<float>(
rom_->
size()) / (1024 * 1024));
286 float button_width = (ImGui::GetContentRegionAvail().x - 8) / 2;
293 if (ImGui::IsItemHovered()) {
294 ImGui::SetTooltip(
"Replace the ROM file for this project");
299 if (ImGui::Button(
ICON_MD_REFRESH " Reload", ImVec2(button_width, 0))) {
304 if (ImGui::IsItemHovered()) {
305 ImGui::SetTooltip(
"Reload ROM from disk");
317 ImGui::TextDisabled(
"Version manager not available");
323 if (!git_initialized) {
325 "Git is not initialized for this project. Initialize Git to enable "
326 "version control and snapshots.");
330 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
340 absl::StrFormat(
"Failed to initialize Git: %s", status.message()),
350 if (!current_hash.empty()) {
353 ImGui::Text(
"%s", current_hash.substr(0, 7).c_str());
359 ImGui::Text(
"Create Snapshot:");
360 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
361 ImGui::InputTextWithHint(
"##snapshot_msg",
"Snapshot message...",
365 ImVec2(ImGui::GetContentRegionAvail().x, 0))) {
372 absl::StrFormat(
"Snapshot created: %s", result->commit_hash),
380 absl::StrFormat(
"Snapshot failed: %s", result.status().message()),
385 if (ImGui::IsItemHovered()) {
387 "Create a snapshot of your project (Git commit + ROM backup)");
400 if (ImGui::CollapsingHeader(
ICON_MD_LIST " Recent Snapshots",
401 ImGuiTreeNodeFlags_DefaultOpen)) {
409 ImGui::TextDisabled(
"No snapshots yet");
413 size_t space_pos = entry.find(
' ');
415 space_pos != std::string::npos ? entry.substr(0, 7) : entry;
416 std::string message =
417 space_pos != std::string::npos ? entry.substr(space_pos + 1) :
"";
421 ImGui::TextWrapped(
"%s", message.c_str());
431 float button_width = ImGui::GetContentRegionAvail().x;
441 if (ImGui::Button(
ICON_MD_SAVE " Save Project", ImVec2(button_width, 0))) {
448 if (ImGui::Button(
ICON_MD_BUILD " Build Project", ImVec2(button_width, 0))) {
457 ImVec2(button_width, 0))) {
463 ImVec2(button_width, 0))) {
478 ImGui::BeginChild(
"##build_output_log", ImVec2(0, 140),
true,
479 ImGuiWindowFlags_HorizontalScrollbar);
481 if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
482 ImGui::SetScrollHereY(1.0f);
496 static char code_buffer[512] = {};
499 sizeof(code_buffer) - 1);
501 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 32);
502 if (ImGui::InputText(
"##code_folder", code_buffer,
sizeof(code_buffer))) {
512 if (ImGui::IsItemHovered()) {
513 ImGui::SetTooltip(
"Browse for code folder");
518 static char assets_buffer[512] = {};
521 sizeof(assets_buffer) - 1);
523 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 32);
524 if (ImGui::InputText(
"##assets_folder", assets_buffer,
525 sizeof(assets_buffer))) {
535 if (ImGui::IsItemHovered()) {
536 ImGui::SetTooltip(
"Browse for assets folder");
541 static char build_buffer[256] = {};
544 sizeof(build_buffer) - 1);
546 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
547 if (ImGui::InputText(
"##build_target", build_buffer,
sizeof(build_buffer))) {
554 static char script_buffer[512] = {};
557 sizeof(script_buffer) - 1);
559 ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
560 if (ImGui::InputText(
"##build_script", script_buffer,
561 sizeof(script_buffer))) {
std::vector< std::string > GetHistory(int limit=10) const
absl::Status InitializeGit()
std::string GetCurrentHash() const
absl::StatusOr< SnapshotResult > CreateSnapshot(const std::string &message)
bool IsGitInitialized() const
BuildProjectCallback build_project_callback_
std::string build_log_output_
char snapshot_message_[256]
SwapRomCallback swap_rom_callback_
void DrawProjectOverview()
SaveProjectCallback save_project_callback_
core::VersionManager * version_manager_
void DrawVersionControl()
RunProjectCallback run_project_callback_
ToastManager * toast_manager_
project::YazeProject * project_
ReloadRomCallback reload_rom_callback_
CancelBuildCallback cancel_build_callback_
ProjectWorkflowStatus build_status_
void DrawStorageLocations()
ProjectWorkflowStatus run_status_
void DrawSnapshotHistory()
std::vector< std::string > history_cache_
BrowseFolderCallback browse_folder_callback_
void Show(const std::string &message, ToastType type=ToastType::kInfo, float ttl_seconds=3.0f)
const Theme & GetCurrentTheme() const
static ThemeManager & Get()
#define YAZE_VERSION_STRING
#define ICON_MD_FOLDER_OPEN
#define ICON_MD_FOLDER_SPECIAL
#define ICON_MD_CAMERA_ALT
#define ICON_MD_PLAY_ARROW
#define ICON_MD_SWAP_HORIZ
#define ICON_MD_CHECK_CIRCLE
void DrawWorkflowCard(const ProjectWorkflowStatus &status, const char *fallback_icon)
const char * WorkflowIcon(const ProjectWorkflowStatus &status, const char *fallback_icon)
ImVec4 WorkflowColor(ProjectWorkflowState state)
ImVec4 ConvertColorToImVec4(const Color &color)
void ColoredText(const char *text, const ImVec4 &color)
ImVec4 GetTextSecondaryVec4()
void ColoredTextF(const ImVec4 &color, const char *fmt,...)
ProjectWorkflowState state
std::string assets_folder