3#include <ftxui/component/component.hpp>
4#include <ftxui/component/screen_interactive.hpp>
5#include <ftxui/dom/elements.hpp>
6#include <ftxui/screen/terminal.hpp>
10#include "absl/strings/str_format.h"
20 : screen_(ScreenInteractive::TerminalOutput()),
21 rom_context_(rom_context) {
45 text(rom_loaded ?
"✅ Ready" :
"⚠ Awaiting ROM") |
46 color(rom_loaded ? Color::GreenLight : Color::YellowLight),
47 text(absl::StrFormat(
"Focus: %s",
55 return std::vector<std::string>{
56 "agent::chat — conversational ROM inspector",
57 "rom::info — metadata & validation",
58 "dungeon::list — dungeon manifest",
59 "gfx::export — sprite/palette dump",
60 "project::build — apply patches"
65 return std::vector<std::string>{
66 "[pending] Implement dungeon diff visualizer",
67 "[pending] Integrate context panes",
68 "[todo] Hook TODO manager into project manifests"
120 screen_.PostEvent(Event::Custom);
125 screen_.PostEvent(Event::Custom);
130 screen_.PostEvent(Event::Custom);
135 screen_.PostEvent(Event::Custom);
147 rows.push_back(text(
"No TODOs available") | dim | center);
149 for (
const auto& line : items) {
150 rows.push_back(text(line));
154 return dbox({window(text(
"📝 TODO Overlay") | bold,
157 vbox(rows) | frame | size(HEIGHT, LESS_THAN, 15) | size(WIDTH, LESS_THAN, 80),
159 text(
"Ctrl+T to close • Enter to jump via command palette") | dim | center
163 screen_.PostEvent(Event::Custom);
165 screen_.PostEvent(Event::Custom);
186 auto terminal = Terminal::Size();
187 if (terminal.dimx < 120) {
196 std::vector<std::string> items = {
208 auto state = std::make_shared<MenuState>();
211 option.focused_entry = &state->selected;
212 option.on_enter = [
this, state] {
213 switch (state->selected) {
225 auto menu = Menu(&state->items, &state->selected, option);
227 return Renderer(menu, [
this, menu, state] {
238 text(
"↑/↓: Navigate | Enter: Select | q: Quit") | dim | center
239 }) | borderRounded | bgcolor(Color::Black);
246 return Renderer([
this] {
247 std::vector<Element> cards;
248 cards.push_back(vbox({
249 text(
"🤖 Overview") | bold,
250 text(
"AI assistant for ROM editing"),
251 text(
"Press 'f' for fullscreen chat") | dim
255 cards.push_back(vbox({
256 text(
"📦 ROM Context") | bold,
259 }) | borderRounded | color(Color::GreenLight));
261 cards.push_back(vbox({
262 text(
"⚠ No ROM loaded") | color(Color::Yellow),
263 text(
"Use Load ROM from main menu") | dim
267 cards.push_back(vbox({
268 text(
"🛠 Integrations") | bold,
269 text(
"• TODO manager status") | dim,
270 text(
"• Command palette shortcuts") | dim,
271 text(
"• Tool dispatcher metrics") | dim
279 text(
"Shortcuts: f fullscreen | c toggle chat | /help commands") | dim | center
280 }) | borderRounded | bgcolor(Color::Black);
285 auto input_message = std::make_shared<std::string>();
286 auto input_component = Input(input_message.get(),
"Type your message...");
288 auto send_button = Button(
"Send", [
this, input_message] {
289 if (input_message->empty())
return;
292 if (*input_message ==
"/exit") {
297 input_message->clear();
301 input_component = CatchEvent(input_component, [
this, input_message](
const Event& event) {
302 if (event == Event::Return) {
303 if (input_message->empty())
return true;
305 if (*input_message ==
"/exit") {
310 input_message->clear();
316 auto container = Container::Vertical({
321 return Renderer(container, [
this, container, input_component, send_button] {
323 text(
"🤖 AI Chat") | bold | center,
325 text(
"Chat functionality integrated into unified layout") | center | dim,
328 text(
"You: ") | bold,
329 input_component->Render() | flex,
331 send_button->Render()
334 text(
"Commands: /exit, /clear, /help") | dim | center
340 return Renderer([
this] {
342 text(absl::StrFormat(
"ROM: %s",
rom_context_->
title())) | color(Color::GreenLight) :
343 text(
"ROM: none") | color(Color::RedLight);
349 std::vector<Element> sections = {
362 sections.push_back(separatorLight());
366 return vbox(sections) | borderRounded | bgcolor(Color::Black);
373 std::vector<std::string> items = {
374 "🔧 ROM Tools (press t)",
375 "🎨 Graphics Tools (ref gfx::export)",
376 "📝 TODO Manager (ref todo::list)",
382 auto state = std::make_shared<ToolsState>();
384 option.on_change = [
this, state] {
385 if (!state->items.empty()) {
389 auto menu = Menu(&state->items, &state->selected, option);
391 return Renderer(menu, [
this, menu, state] {
397 text(
"Select a tool category") | dim | center,
402 }) | borderRounded | bgcolor(Color::Black);
407 auto offset = std::make_shared<int>(0);
408 const int lines_to_show = 20;
410 return Renderer([
this, offset, lines_to_show] {
413 text(
"🔍 Hex Viewer") | bold | center,
415 text(
"No ROM loaded") | center | color(Color::Red),
417 text(
"Load a ROM to view hex data") | center | dim
421 std::vector<Element> rows;
422 for (
int i = 0; i < lines_to_show; ++i) {
423 int current_offset = *offset + (i * 16);
429 row.push_back(text(absl::StrFormat(
"0x%08X: ", current_offset)) | color(Color::Yellow));
431 for (
int j = 0; j < 16; ++j) {
433 row.push_back(text(absl::StrFormat(
"%02X ",
rom_context_->
vector()[current_offset + j])));
435 row.push_back(text(
" "));
439 row.push_back(separator());
441 for (
int j = 0; j < 16; ++j) {
444 row.push_back(text(std::isprint(c) ? std::string(1, c) :
"."));
446 row.push_back(text(
" "));
450 rows.push_back(hbox(row));
456 text(
"🔍 Hex Viewer") | bold | center,
460 vbox(rows) | frame | flex,
462 text(absl::StrFormat(
"Offset: 0x%08X", *offset)) | color(Color::Cyan),
464 text(
"↑/↓: Scroll | q: Back") | dim | center
465 }) | borderRounded | bgcolor(Color::Black);
470 return Renderer([
this] {
476 text(
"🌈 Overview") | bold,
477 text(
"Preview palette indices and colors"),
478 text(
"Highlight sprite-specific palettes") | dim
479 }) | borderRounded | bgcolor(Color::Black),
481 text(
"🧪 Roadmap") | bold,
482 text(
"• Live recolor with undo stack"),
483 text(
"• Sprite preview viewport"),
484 text(
"• Export to .pal/.act")
485 }) | borderRounded | bgcolor(Color::Black),
487 text(
"🗒 TODO") | bold,
488 text(
"Link to command palette"),
489 text(
"Use animation timeline"),
490 text(
"Add palette history panel") | dim
491 }) | borderRounded | bgcolor(Color::Black)
496 text(
"Press 'q' to go back") | dim | center
502 return Renderer([
this] {
503 std::vector<Element> todo_cards;
506 todo_cards.push_back(text(
"• " + item));
509 if (todo_cards.empty()) {
510 todo_cards.push_back(text(
"No TODOs yet") | dim);
516 vbox(todo_cards) | borderRounded | bgcolor(Color::Black),
518 text(
"Press Ctrl+T anywhere to toggle the popup todo overlay.") | dim,
522 text(
"Press 'q' to go back") | dim | center
530 std::vector<std::string> items = {
531 "Apply Asar Patch — todo#123",
532 "Apply BPS Patch — todo#124",
533 "Extract Symbols — todo#098",
534 "Validate Assembly — todo#087",
535 "Generate Save File — todo#142",
540 auto state = std::make_shared<ToolsState>();
541 auto menu = Menu(&state->items, &state->selected);
543 return Renderer(menu, [
this, menu, state] {
545 text(
"🔧 ROM Tools") | bold | center,
549 text(
"Select a ROM tool") | dim | center
557 std::vector<std::string> items = {
558 "Palette Editor — ref gfx::export",
559 "Hex Viewer — ref rom::hex",
564 auto state = std::make_shared<ToolsState>();
565 auto menu = Menu(&state->items, &state->selected);
567 return Renderer(menu, [
this, menu, state] {
569 text(
"🎨 Graphics Tools") | bold | center,
573 text(
"Select a graphics tool") | dim | center
579 struct SettingsState {
580 int left_width_slider;
581 int right_width_slider;
582 int bottom_height_slider;
585 auto state = std::make_shared<SettingsState>();
590 auto left_width_control = Slider(
"Left Panel Width: ", &state->left_width_slider, 20, 60, 1);
591 auto right_width_control = Slider(
"Right Panel Width: ", &state->right_width_slider, 30, 60, 1);
592 auto bottom_height_control = Slider(
"Bottom Panel Height: ", &state->bottom_height_slider, 10, 30, 1);
594 auto apply_button = Button(
"Apply Changes", [
this, state] {
598 screen_.PostEvent(Event::Custom);
601 auto reset_button = Button(
"Reset to Defaults", [
this, state] {
602 state->left_width_slider = 30;
603 state->right_width_slider = 40;
604 state->bottom_height_slider = 15;
608 screen_.PostEvent(Event::Custom);
611 auto controls = Container::Vertical({
614 bottom_height_control,
615 Container::Horizontal({
621 return Renderer(controls, [
this, controls, state, left_width_control, right_width_control,
622 bottom_height_control, apply_button, reset_button] {
626 text(
"Customize the TUI layout") | center | dim,
629 text(
"Left Panel Width: ") | bold,
630 text(absl::StrFormat(
"%d", state->left_width_slider))
632 left_width_control->Render(),
635 text(
"Right Panel Width: ") | bold,
636 text(absl::StrFormat(
"%d", state->right_width_slider))
638 right_width_control->Render(),
641 text(
"Bottom Panel Height: ") | bold,
642 text(absl::StrFormat(
"%d", state->bottom_height_slider))
644 bottom_height_control->Render(),
647 apply_button->Render(),
649 reset_button->Render()
652 text(
"Panel Visibility:") | bold,
654 text(
"Chat: ") | bold,
658 text(
"Status: ") | bold,
663 text(
"Keyboard Shortcuts:") | bold,
664 text(
" c - Toggle chat panel") | dim,
665 text(
" s - Toggle status panel") | dim,
666 text(
" Esc/b - Back to menu") | dim,
668 text(
"Changes apply immediately") | center | dim
674 return Renderer([
this] {
678 text(
"Unified TUI Layout - ROM Editor & AI Agent") | center | dim,
680 text(
"Global Shortcuts:") | bold | color(Color::Yellow),
681 text(
" q - Quit application"),
682 text(
" h - Show this help"),
683 text(
" m - Main menu"),
684 text(
" Esc/b - Back to previous panel"),
686 text(
"Panel Controls:") | bold | color(Color::Yellow),
687 text(
" c - Toggle chat panel"),
688 text(
" s - Toggle status panel"),
689 text(
" f - Open full chat interface"),
690 text(
" t - ROM tools"),
692 text(
"Navigation:") | bold | color(Color::Yellow),
693 text(
" ↑/↓ - Navigate menus"),
694 text(
" Enter - Select item"),
695 text(
" Tab - Switch focus"),
697 text(
"Chat Commands:") | bold | color(Color::Yellow),
698 text(
" /exit - Exit chat"),
699 text(
" /clear - Clear history"),
700 text(
" /help - Show chat help"),
702 text(
"Available Tools:") | bold | color(Color::Green),
703 text(
" • Hex Viewer - Inspect ROM data"),
704 text(
" • Palette Editor - Edit color palettes"),
705 text(
" • TODO Manager - Track tasks"),
706 text(
" • AI Chat - Natural language ROM queries"),
707 text(
" • Dungeon Tools - Room inspection & editing"),
708 text(
" • Graphics Tools - Sprite & tile editing"),
710 text(
"Press 'Esc' or 'b' to go back") | dim | center
717 auto all_panels = Container::Tab({
732 return Renderer(all_panels, [
this, all_panels] {
734 Component left_panel;
736 case PanelType::kMainMenu:
737 left_panel = main_menu_panel_;
739 case PanelType::kHexViewer:
740 left_panel = hex_viewer_panel_;
742 case PanelType::kPaletteEditor:
743 left_panel = palette_editor_panel_;
745 case PanelType::kTodoManager:
746 left_panel = todo_manager_panel_;
748 case PanelType::kRomTools:
749 left_panel = rom_tools_panel_;
751 case PanelType::kGraphicsTools:
752 left_panel = graphics_tools_panel_;
754 case PanelType::kSettings:
755 left_panel = settings_panel_;
757 case PanelType::kHelp:
758 left_panel = help_panel_;
761 left_panel = main_menu_panel_;
766 Component right_panel;
774 auto top_section = hbox({
775 left_panel->Render() | flex,
782 Element stacked = vbox({
786 }) | bgcolor(Color::Black);
794 Element content = top_section | bgcolor(Color::Black);
805 if (event == Event::Escape || event == Event::Character(
'b')) {
813 if (event == Event::Special({20})) {
818 if (event == Event::Character(
'q') ||
824 if (event == Event::Character(
'h')) {
829 if (event == Event::Character(
'c')) {
834 if (event == Event::Character(
's')) {
839 if (event == Event::Character(
't')) {
844 if (event == Event::Character(
'm')) {
849 if (event == Event::Character(
'f')) {
854 screen_.PostEvent(Event::Custom);
871 title =
"🎮 Main Menu";
883 title =
"🔍 Hex Viewer";
886 title =
"🎨 Palette Editor";
889 title =
"📝 TODO Manager";
892 title =
"🔧 ROM Tools";
895 title =
"🎨 Graphics Tools";
898 title =
"⚙️ Settings";
905 return text(title) | bold | center;
910 text(absl::StrFormat(
"Panel: %s",
913 text(absl::StrFormat(
"ROM: %s",
916 text(
"Shortcuts: Ctrl+T TODO Overlay | f Full Chat | m Main Menu") | dim
921 return text(
"🎮 Z3ED CLI") | bold | center;
925 return text(
"Workflow: Active") | color(Color::Green);
930 text(
"Command Hints:") | bold,
931 text(
" Ctrl+T - Toggle TODO overlay"),
932 text(
" f - Full chat mode"),
933 text(
" m - Main menu")
938 return text(
"TODO Stack: Empty") | dim;
943 return text(
"No items") | center | dim;
The Rom class is used to load, save, and modify Rom data.
ftxui::Component unified_layout_
ftxui::Element RenderTodoStack()
ftxui::Component CreateToolsPanel()
ftxui::Component CreatePaletteEditorPanel()
ftxui::Component graphics_tools_panel_
void SwitchToolPanel(PanelType panel)
ftxui::Component CreateHelpPanel()
void SetStatusProvider(std::function< ftxui::Element()> provider)
bool todo_overlay_visible_
ftxui::Component settings_panel_
void SetLayoutConfig(const LayoutConfig &config)
ftxui::Element RenderCommandHints()
UnifiedLayout(Rom *rom_context=nullptr)
std::function< ftxui::Element()> status_provider_
ftxui::Component rom_tools_panel_
ftxui::Component CreateRomToolsPanel()
ftxui::Element RenderStatusBar()
ftxui::Component hex_viewer_panel_
ftxui::Component CreateChatPanel()
ftxui::ScreenInteractive screen_
bool HandleGlobalEvents(const ftxui::Event &event)
std::unique_ptr< tui::ChatTUI > chat_tui_
ftxui::Element RenderPanelHeader(PanelType panel)
std::function< bool(const ftxui::Event &)> global_event_handler_
ftxui::Element RenderResponsiveGrid(const std::vector< ftxui::Element > &tiles)
void SwitchMainPanel(PanelType panel)
ftxui::Component status_panel_
ftxui::Component palette_editor_panel_
std::function< bool(const ftxui::Event &)> panel_event_handler_
ftxui::Component chat_panel_
ftxui::Component help_panel_
ftxui::Component main_menu_panel_
void SetTodoProvider(std::function< std::vector< std::string >()> provider)
void SetRomContext(Rom *rom_context)
ftxui::Component CreateHexViewerPanel()
std::function< std::vector< std::string >()> todo_provider_
ftxui::Component CreateSettingsPanel()
ftxui::Component todo_manager_panel_
ftxui::Component todo_overlay_component_
ftxui::Element RenderWorkflowLane()
ftxui::Component CreateStatusPanel()
ftxui::Component tools_panel_
void SetCommandSummaryProvider(std::function< std::vector< std::string >()> provider)
bool HandlePanelEvents(const ftxui::Event &event)
ftxui::Component CreateUnifiedLayout()
ftxui::Component CreateGraphicsToolsPanel()
ftxui::Component CreateTodoManagerPanel()
ftxui::Component CreateMainMenuPanel()
ftxui::Element RenderAnimatedBanner()
std::function< std::vector< std::string >()> command_summary_provider_
Main namespace for the application.
PanelType active_tool_panel
std::vector< std::string > active_workflows
std::string current_rom_file
std::string current_error
PanelType active_main_panel
std::string command_palette_hint