feat: Introduce Unified Layout with Enhanced Chat and Status Panels
- Added a new unified layout system that integrates chat and status panels for improved user experience. - Implemented EnhancedChatComponent and EnhancedStatusPanel to manage chat interactions and display system information. - Updated CMake configuration to include new source files for the unified layout, ensuring proper build setup. - Refactored existing TUI components to support the new layout structure, enhancing modularity and maintainability.
This commit is contained in:
263
src/cli/tui/enhanced_chat_component.cc
Normal file
263
src/cli/tui/enhanced_chat_component.cc
Normal file
@@ -0,0 +1,263 @@
|
|||||||
|
#include "cli/tui/enhanced_chat_component.h"
|
||||||
|
|
||||||
|
#include <ftxui/component/component.hpp>
|
||||||
|
#include <ftxui/component/screen_interactive.hpp>
|
||||||
|
#include <ftxui/dom/elements.hpp>
|
||||||
|
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
EnhancedChatComponent::EnhancedChatComponent(Rom* rom_context)
|
||||||
|
: rom_context_(rom_context) {
|
||||||
|
// Initialize agent service
|
||||||
|
if (rom_context_) {
|
||||||
|
agent_service_.SetRomContext(rom_context_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize autocomplete
|
||||||
|
autocomplete_engine_.RegisterCommand("/help", "Show help message");
|
||||||
|
autocomplete_engine_.RegisterCommand("/exit", "Exit the chat");
|
||||||
|
autocomplete_engine_.RegisterCommand("/clear", "Clear chat history");
|
||||||
|
autocomplete_engine_.RegisterCommand("/rom_info", "Display ROM information");
|
||||||
|
autocomplete_engine_.RegisterCommand("/status", "Show chat status");
|
||||||
|
|
||||||
|
// Create components
|
||||||
|
input_component_ = CreateInputComponent();
|
||||||
|
history_component_ = CreateHistoryComponent();
|
||||||
|
chat_container_ = CreateChatContainer();
|
||||||
|
|
||||||
|
// Set up event handlers
|
||||||
|
input_event_handler_ = [this](const Event& event) {
|
||||||
|
return HandleInputEvents(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
history_event_handler_ = [this](const Event& event) {
|
||||||
|
return HandleHistoryEvents(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedChatComponent::GetComponent() {
|
||||||
|
return chat_container_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::SetRomContext(Rom* rom_context) {
|
||||||
|
rom_context_ = rom_context;
|
||||||
|
if (rom_context_) {
|
||||||
|
agent_service_.SetRomContext(rom_context_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::SendMessage(const std::string& message) {
|
||||||
|
if (message.empty()) return;
|
||||||
|
|
||||||
|
ProcessMessage(message);
|
||||||
|
input_message_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::ClearHistory() {
|
||||||
|
chat_history_.clear();
|
||||||
|
selected_history_index_ = 0;
|
||||||
|
UpdateHistoryDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::ResetConversation() {
|
||||||
|
agent_service_.ResetConversation();
|
||||||
|
ClearHistory();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedChatComponent::CreateInputComponent() {
|
||||||
|
auto input = Input(&input_message_, "Type your message...");
|
||||||
|
|
||||||
|
auto send_button = Button("Send", [this] {
|
||||||
|
SendMessage(input_message_);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto clear_button = Button("Clear", [this] {
|
||||||
|
ClearHistory();
|
||||||
|
});
|
||||||
|
|
||||||
|
auto container = Container::Horizontal({
|
||||||
|
input,
|
||||||
|
send_button,
|
||||||
|
clear_button
|
||||||
|
});
|
||||||
|
|
||||||
|
return CatchEvent(container, input_event_handler_);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedChatComponent::CreateHistoryComponent() {
|
||||||
|
return Renderer([this] {
|
||||||
|
return RenderHistoryArea();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedChatComponent::CreateChatContainer() {
|
||||||
|
auto container = Container::Vertical({
|
||||||
|
history_component_,
|
||||||
|
input_component_
|
||||||
|
});
|
||||||
|
|
||||||
|
return Renderer(container, [this] {
|
||||||
|
return vbox({
|
||||||
|
text("🤖 AI Chat") | bold | center,
|
||||||
|
separator(),
|
||||||
|
history_component_->Render() | flex | frame,
|
||||||
|
separator(),
|
||||||
|
input_component_->Render(),
|
||||||
|
separator(),
|
||||||
|
text("Commands: /help, /exit, /clear, /rom_info, /status") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnhancedChatComponent::HandleInputEvents(const Event& event) {
|
||||||
|
if (event == Event::Return) {
|
||||||
|
if (input_message_.empty()) return true;
|
||||||
|
|
||||||
|
SendMessage(input_message_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('q')) {
|
||||||
|
// Exit chat or go back
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnhancedChatComponent::HandleHistoryEvents(const Event& event) {
|
||||||
|
if (event == Event::ArrowUp) {
|
||||||
|
if (selected_history_index_ > 0) {
|
||||||
|
selected_history_index_--;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::ArrowDown) {
|
||||||
|
if (selected_history_index_ < static_cast<int>(chat_history_.size()) - 1) {
|
||||||
|
selected_history_index_++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::ProcessMessage(const std::string& message) {
|
||||||
|
// Handle special commands
|
||||||
|
if (message == "/exit") {
|
||||||
|
// Signal to parent component to exit
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message == "/clear") {
|
||||||
|
ClearHistory();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message == "/help") {
|
||||||
|
AddMessageToHistory("System",
|
||||||
|
"Available commands: /help, /exit, /clear, /rom_info, /status");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message == "/rom_info") {
|
||||||
|
if (rom_context_) {
|
||||||
|
AddMessageToHistory("System",
|
||||||
|
absl::StrFormat("ROM: %s | Size: %d bytes",
|
||||||
|
rom_context_->title(), rom_context_->size()));
|
||||||
|
} else {
|
||||||
|
AddMessageToHistory("System", "No ROM loaded");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message == "/status") {
|
||||||
|
AddMessageToHistory("System",
|
||||||
|
absl::StrFormat("Chat Status: %d messages, %s",
|
||||||
|
chat_history_.size(),
|
||||||
|
focused_ ? "Focused" : "Not focused"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add user message to history
|
||||||
|
AddMessageToHistory("You", message);
|
||||||
|
|
||||||
|
// Send to agent service
|
||||||
|
auto response = agent_service_.SendMessage(message);
|
||||||
|
if (response.ok()) {
|
||||||
|
// Agent response will be handled by the service
|
||||||
|
// For now, add a placeholder response
|
||||||
|
AddMessageToHistory("Agent", "Response received (integration pending)");
|
||||||
|
} else {
|
||||||
|
AddMessageToHistory("System",
|
||||||
|
absl::StrCat("Error: ", response.status().message()));
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateHistoryDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::AddMessageToHistory(const std::string& sender, const std::string& message) {
|
||||||
|
chat_history_.push_back({sender, message});
|
||||||
|
|
||||||
|
// Limit history size
|
||||||
|
if (static_cast<int>(chat_history_.size()) > max_history_lines_) {
|
||||||
|
chat_history_.erase(chat_history_.begin());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-scroll to bottom
|
||||||
|
selected_history_index_ = chat_history_.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedChatComponent::UpdateHistoryDisplay() {
|
||||||
|
// Trigger re-render of history component
|
||||||
|
// This is handled automatically by FTXUI
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedChatComponent::RenderChatMessage(const std::string& sender, const std::string& message) {
|
||||||
|
Color sender_color;
|
||||||
|
if (sender == "You") {
|
||||||
|
sender_color = Color::Yellow;
|
||||||
|
} else if (sender == "Agent") {
|
||||||
|
sender_color = Color::Green;
|
||||||
|
} else {
|
||||||
|
sender_color = Color::Cyan;
|
||||||
|
}
|
||||||
|
|
||||||
|
return hbox({
|
||||||
|
text(sender) | bold | color(sender_color),
|
||||||
|
text(": "),
|
||||||
|
text(message) | flex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedChatComponent::RenderInputArea() {
|
||||||
|
return hbox({
|
||||||
|
text("You: ") | bold,
|
||||||
|
input_component_->Render() | flex
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedChatComponent::RenderHistoryArea() {
|
||||||
|
if (chat_history_.empty()) {
|
||||||
|
return vbox({
|
||||||
|
text("No messages yet. Start chatting!") | dim | center
|
||||||
|
}) | flex | center;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Element> messages;
|
||||||
|
for (const auto& [sender, message] : chat_history_) {
|
||||||
|
messages.push_back(RenderChatMessage(sender, message));
|
||||||
|
}
|
||||||
|
|
||||||
|
return vbox(messages) | flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
84
src/cli/tui/enhanced_chat_component.h
Normal file
84
src/cli/tui/enhanced_chat_component.h
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
#ifndef YAZE_CLI_TUI_ENHANCED_CHAT_COMPONENT_H
|
||||||
|
#define YAZE_CLI_TUI_ENHANCED_CHAT_COMPONENT_H
|
||||||
|
|
||||||
|
#include <ftxui/component/component.hpp>
|
||||||
|
#include <ftxui/dom/elements.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "app/rom.h"
|
||||||
|
#include "cli/service/agent/conversational_agent_service.h"
|
||||||
|
#include "cli/util/autocomplete.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
|
||||||
|
// Enhanced chat component that integrates with the unified layout
|
||||||
|
class EnhancedChatComponent {
|
||||||
|
public:
|
||||||
|
explicit EnhancedChatComponent(Rom* rom_context = nullptr);
|
||||||
|
|
||||||
|
// Component interface
|
||||||
|
ftxui::Component GetComponent();
|
||||||
|
void SetRomContext(Rom* rom_context);
|
||||||
|
|
||||||
|
// Chat functionality
|
||||||
|
void SendMessage(const std::string& message);
|
||||||
|
void ClearHistory();
|
||||||
|
void ResetConversation();
|
||||||
|
|
||||||
|
// State management
|
||||||
|
bool IsFocused() const { return focused_; }
|
||||||
|
void SetFocused(bool focused) { focused_ = focused; }
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
void SetMaxHistoryLines(int lines) { max_history_lines_ = lines; }
|
||||||
|
int GetMaxHistoryLines() const { return max_history_lines_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Component creation
|
||||||
|
ftxui::Component CreateInputComponent();
|
||||||
|
ftxui::Component CreateHistoryComponent();
|
||||||
|
ftxui::Component CreateChatContainer();
|
||||||
|
|
||||||
|
// Event handling
|
||||||
|
bool HandleInputEvents(const ftxui::Event& event);
|
||||||
|
bool HandleHistoryEvents(const ftxui::Event& event);
|
||||||
|
|
||||||
|
// Message processing
|
||||||
|
void ProcessMessage(const std::string& message);
|
||||||
|
void AddMessageToHistory(const std::string& sender, const std::string& message);
|
||||||
|
void UpdateHistoryDisplay();
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
ftxui::Element RenderChatMessage(const std::string& sender, const std::string& message);
|
||||||
|
ftxui::Element RenderInputArea();
|
||||||
|
ftxui::Element RenderHistoryArea();
|
||||||
|
|
||||||
|
// State
|
||||||
|
Rom* rom_context_;
|
||||||
|
agent::ConversationalAgentService agent_service_;
|
||||||
|
AutocompleteEngine autocomplete_engine_;
|
||||||
|
|
||||||
|
// UI State
|
||||||
|
std::string input_message_;
|
||||||
|
std::vector<std::pair<std::string, std::string>> chat_history_;
|
||||||
|
int selected_history_index_ = 0;
|
||||||
|
bool focused_ = false;
|
||||||
|
int max_history_lines_ = 20;
|
||||||
|
|
||||||
|
// Components
|
||||||
|
ftxui::Component input_component_;
|
||||||
|
ftxui::Component history_component_;
|
||||||
|
ftxui::Component chat_container_;
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
std::function<bool(const ftxui::Event&)> input_event_handler_;
|
||||||
|
std::function<bool(const ftxui::Event&)> history_event_handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif // YAZE_CLI_TUI_ENHANCED_CHAT_COMPONENT_H
|
||||||
251
src/cli/tui/enhanced_status_panel.cc
Normal file
251
src/cli/tui/enhanced_status_panel.cc
Normal file
@@ -0,0 +1,251 @@
|
|||||||
|
#include "cli/tui/enhanced_status_panel.h"
|
||||||
|
|
||||||
|
#include <ftxui/component/component.hpp>
|
||||||
|
#include <ftxui/dom/elements.hpp>
|
||||||
|
#include <chrono>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
EnhancedStatusPanel::EnhancedStatusPanel(Rom* rom_context)
|
||||||
|
: rom_context_(rom_context) {
|
||||||
|
// Initialize status data
|
||||||
|
CollectRomInfo();
|
||||||
|
CollectSystemInfo();
|
||||||
|
CollectLayoutInfo();
|
||||||
|
|
||||||
|
// Create components
|
||||||
|
rom_info_section_ = CreateRomInfoSection();
|
||||||
|
system_info_section_ = CreateSystemInfoSection();
|
||||||
|
layout_info_section_ = CreateLayoutInfoSection();
|
||||||
|
error_section_ = CreateErrorSection();
|
||||||
|
status_container_ = CreateStatusContainer();
|
||||||
|
|
||||||
|
// Set up event handlers
|
||||||
|
status_event_handler_ = [this](Event event) {
|
||||||
|
return HandleStatusEvents(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedStatusPanel::GetComponent() {
|
||||||
|
return status_container_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::SetRomContext(Rom* rom_context) {
|
||||||
|
rom_context_ = rom_context;
|
||||||
|
UpdateRomInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::UpdateRomInfo() {
|
||||||
|
CollectRomInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::UpdateSystemInfo() {
|
||||||
|
CollectSystemInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::UpdateLayoutInfo() {
|
||||||
|
CollectLayoutInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::SetError(const std::string& error) {
|
||||||
|
current_error_ = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::ClearError() {
|
||||||
|
current_error_.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedStatusPanel::CreateStatusContainer() {
|
||||||
|
auto container = Container::Vertical({
|
||||||
|
rom_info_section_,
|
||||||
|
system_info_section_,
|
||||||
|
layout_info_section_,
|
||||||
|
error_section_
|
||||||
|
});
|
||||||
|
|
||||||
|
return Renderer(container, [this] {
|
||||||
|
return vbox({
|
||||||
|
text("📊 Status Panel") | bold | center,
|
||||||
|
separator(),
|
||||||
|
rom_info_section_->Render(),
|
||||||
|
separator(),
|
||||||
|
system_info_section_->Render(),
|
||||||
|
separator(),
|
||||||
|
layout_info_section_->Render(),
|
||||||
|
separator(),
|
||||||
|
error_section_->Render(),
|
||||||
|
separator(),
|
||||||
|
RenderStatusBar()
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedStatusPanel::CreateRomInfoSection() {
|
||||||
|
return Renderer([this] {
|
||||||
|
return RenderRomInfo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedStatusPanel::CreateSystemInfoSection() {
|
||||||
|
return Renderer([this] {
|
||||||
|
return RenderSystemInfo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedStatusPanel::CreateLayoutInfoSection() {
|
||||||
|
return Renderer([this] {
|
||||||
|
return RenderLayoutInfo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component EnhancedStatusPanel::CreateErrorSection() {
|
||||||
|
return Renderer([this] {
|
||||||
|
return RenderErrorInfo();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EnhancedStatusPanel::HandleStatusEvents(const Event& event) {
|
||||||
|
if (event == Event::Character('e')) {
|
||||||
|
SetExpanded(!expanded_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('d')) {
|
||||||
|
SetShowDetailedInfo(!show_detailed_info_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedStatusPanel::RenderRomInfo() {
|
||||||
|
if (!rom_info_.loaded) {
|
||||||
|
return vbox({
|
||||||
|
text("🎮 ROM Information") | bold | color(Color::Red),
|
||||||
|
text("No ROM loaded") | color(Color::Red),
|
||||||
|
text("Load a ROM to see information") | dim
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return vbox({
|
||||||
|
text("🎮 ROM Information") | bold | color(Color::Green),
|
||||||
|
text(absl::StrFormat("Title: %s", rom_info_.title)) | color(Color::White),
|
||||||
|
text(absl::StrFormat("Size: %s", rom_info_.size)) | color(Color::Cyan),
|
||||||
|
text(absl::StrFormat("Checksum: %s", rom_info_.checksum)) | color(Color::Yellow),
|
||||||
|
text(absl::StrFormat("Region: %s", rom_info_.region)) | color(Color::Magenta)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedStatusPanel::RenderSystemInfo() {
|
||||||
|
return vbox({
|
||||||
|
text("💻 System Information") | bold | color(Color::Blue),
|
||||||
|
text(absl::StrFormat("Time: %s", system_info_.current_time)) | color(Color::White),
|
||||||
|
text(absl::StrFormat("Memory: %s", system_info_.memory_usage)) | color(Color::Cyan),
|
||||||
|
text(absl::StrFormat("CPU: %s", system_info_.cpu_usage)) | color(Color::Yellow),
|
||||||
|
text(absl::StrFormat("Disk: %s", system_info_.disk_space)) | color(Color::Green)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedStatusPanel::RenderLayoutInfo() {
|
||||||
|
return vbox({
|
||||||
|
text("🖥️ Layout Information") | bold | color(Color::Magenta),
|
||||||
|
text(absl::StrFormat("Active Panel: %s", layout_info_.active_panel)) | color(Color::White),
|
||||||
|
text(absl::StrFormat("Panel Count: %s", layout_info_.panel_count)) | color(Color::Cyan),
|
||||||
|
text(absl::StrFormat("Layout Mode: %s", layout_info_.layout_mode)) | color(Color::Yellow),
|
||||||
|
text(absl::StrFormat("Focus State: %s", layout_info_.focus_state)) | color(Color::Green)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedStatusPanel::RenderErrorInfo() {
|
||||||
|
if (current_error_.empty()) {
|
||||||
|
return vbox({
|
||||||
|
text("✅ No Errors") | color(Color::Green)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return vbox({
|
||||||
|
text("⚠️ Error") | bold | color(Color::Red),
|
||||||
|
text(current_error_) | color(Color::Yellow)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Element EnhancedStatusPanel::RenderStatusBar() {
|
||||||
|
return hbox({
|
||||||
|
text("e: Expand | d: Details | q: Quit") | dim,
|
||||||
|
filler(),
|
||||||
|
text(expanded_ ? "EXPANDED" : "COLLAPSED") | color(Color::Cyan),
|
||||||
|
filler(),
|
||||||
|
text(show_detailed_info_ ? "DETAILED" : "SIMPLE") | color(Color::Yellow)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::CollectRomInfo() {
|
||||||
|
if (!rom_context_) {
|
||||||
|
rom_info_.loaded = false;
|
||||||
|
rom_info_.title = "No ROM";
|
||||||
|
rom_info_.size = "0 bytes";
|
||||||
|
rom_info_.checksum = "N/A";
|
||||||
|
rom_info_.region = "N/A";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rom_info_.loaded = true;
|
||||||
|
rom_info_.title = rom_context_->title();
|
||||||
|
rom_info_.size = absl::StrFormat("%d bytes", rom_context_->size());
|
||||||
|
|
||||||
|
// Calculate checksum (simplified)
|
||||||
|
uint32_t checksum = 0;
|
||||||
|
if (rom_context_->size() > 0) {
|
||||||
|
for (size_t i = 0; i < std::min(rom_context_->size(), size_t(1024)); ++i) {
|
||||||
|
checksum += rom_context_->vector()[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rom_info_.checksum = absl::StrFormat("0x%08X", checksum);
|
||||||
|
|
||||||
|
// Determine region (simplified)
|
||||||
|
if (rom_context_->size() > 0) {
|
||||||
|
uint8_t region_byte = rom_context_->vector()[0x7FD9]; // SNES region byte
|
||||||
|
switch (region_byte) {
|
||||||
|
case 0x00: rom_info_.region = "NTSC"; break;
|
||||||
|
case 0x01: rom_info_.region = "PAL"; break;
|
||||||
|
default: rom_info_.region = "Unknown"; break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rom_info_.region = "Unknown";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::CollectSystemInfo() {
|
||||||
|
// Get current time
|
||||||
|
auto now = std::chrono::system_clock::now();
|
||||||
|
auto time_t = std::chrono::system_clock::to_time_t(now);
|
||||||
|
auto tm = *std::localtime(&time_t);
|
||||||
|
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << std::put_time(&tm, "%H:%M:%S");
|
||||||
|
system_info_.current_time = ss.str();
|
||||||
|
|
||||||
|
// Placeholder system info (in a real implementation, you'd query the system)
|
||||||
|
system_info_.memory_usage = "Unknown";
|
||||||
|
system_info_.cpu_usage = "Unknown";
|
||||||
|
system_info_.disk_space = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
void EnhancedStatusPanel::CollectLayoutInfo() {
|
||||||
|
// Placeholder layout info (in a real implementation, you'd get this from the layout manager)
|
||||||
|
layout_info_.active_panel = "Main Menu";
|
||||||
|
layout_info_.panel_count = "4";
|
||||||
|
layout_info_.layout_mode = "Unified";
|
||||||
|
layout_info_.focus_state = "Chat";
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
106
src/cli/tui/enhanced_status_panel.h
Normal file
106
src/cli/tui/enhanced_status_panel.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#ifndef YAZE_CLI_TUI_ENHANCED_STATUS_PANEL_H
|
||||||
|
#define YAZE_CLI_TUI_ENHANCED_STATUS_PANEL_H
|
||||||
|
|
||||||
|
#include <ftxui/component/component.hpp>
|
||||||
|
#include <ftxui/dom/elements.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "app/rom.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
|
||||||
|
// Enhanced status panel with comprehensive system information
|
||||||
|
class EnhancedStatusPanel {
|
||||||
|
public:
|
||||||
|
explicit EnhancedStatusPanel(Rom* rom_context = nullptr);
|
||||||
|
|
||||||
|
// Component interface
|
||||||
|
ftxui::Component GetComponent();
|
||||||
|
void SetRomContext(Rom* rom_context);
|
||||||
|
|
||||||
|
// Status updates
|
||||||
|
void UpdateRomInfo();
|
||||||
|
void UpdateSystemInfo();
|
||||||
|
void UpdateLayoutInfo();
|
||||||
|
void SetError(const std::string& error);
|
||||||
|
void ClearError();
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
void SetShowDetailedInfo(bool show) { show_detailed_info_ = show; }
|
||||||
|
bool GetShowDetailedInfo() const { return show_detailed_info_; }
|
||||||
|
|
||||||
|
// State management
|
||||||
|
bool IsExpanded() const { return expanded_; }
|
||||||
|
void SetExpanded(bool expanded) { expanded_ = expanded; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Component creation
|
||||||
|
ftxui::Component CreateStatusContainer();
|
||||||
|
ftxui::Component CreateRomInfoSection();
|
||||||
|
ftxui::Component CreateSystemInfoSection();
|
||||||
|
ftxui::Component CreateLayoutInfoSection();
|
||||||
|
ftxui::Component CreateErrorSection();
|
||||||
|
|
||||||
|
// Event handling
|
||||||
|
bool HandleStatusEvents(const ftxui::Event& event);
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
ftxui::Element RenderRomInfo();
|
||||||
|
ftxui::Element RenderSystemInfo();
|
||||||
|
ftxui::Element RenderLayoutInfo();
|
||||||
|
ftxui::Element RenderErrorInfo();
|
||||||
|
ftxui::Element RenderStatusBar();
|
||||||
|
|
||||||
|
// Data collection
|
||||||
|
void CollectRomInfo();
|
||||||
|
void CollectSystemInfo();
|
||||||
|
void CollectLayoutInfo();
|
||||||
|
|
||||||
|
// State
|
||||||
|
Rom* rom_context_;
|
||||||
|
bool expanded_ = false;
|
||||||
|
bool show_detailed_info_ = true;
|
||||||
|
|
||||||
|
// Status data
|
||||||
|
struct RomInfo {
|
||||||
|
std::string title;
|
||||||
|
std::string size;
|
||||||
|
std::string checksum;
|
||||||
|
std::string region;
|
||||||
|
bool loaded = false;
|
||||||
|
} rom_info_;
|
||||||
|
|
||||||
|
struct SystemInfo {
|
||||||
|
std::string current_time;
|
||||||
|
std::string memory_usage;
|
||||||
|
std::string cpu_usage;
|
||||||
|
std::string disk_space;
|
||||||
|
} system_info_;
|
||||||
|
|
||||||
|
struct LayoutInfo {
|
||||||
|
std::string active_panel;
|
||||||
|
std::string panel_count;
|
||||||
|
std::string layout_mode;
|
||||||
|
std::string focus_state;
|
||||||
|
} layout_info_;
|
||||||
|
|
||||||
|
std::string current_error_;
|
||||||
|
|
||||||
|
// Components
|
||||||
|
ftxui::Component status_container_;
|
||||||
|
ftxui::Component rom_info_section_;
|
||||||
|
ftxui::Component system_info_section_;
|
||||||
|
ftxui::Component layout_info_section_;
|
||||||
|
ftxui::Component error_section_;
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
std::function<bool(const ftxui::Event&)> status_event_handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif // YAZE_CLI_TUI_ENHANCED_STATUS_PANEL_H
|
||||||
@@ -12,9 +12,8 @@
|
|||||||
#include "util/bps.h"
|
#include "util/bps.h"
|
||||||
#include "util/file_util.h"
|
#include "util/file_util.h"
|
||||||
#include "app/core/asar_wrapper.h"
|
#include "app/core/asar_wrapper.h"
|
||||||
#include "app/zelda3/overworld/overworld.h"
|
|
||||||
#include "cli/cli.h"
|
#include "cli/cli.h"
|
||||||
#include "cli/tui/command_palette.h"
|
#include "cli/tui/unified_layout.h"
|
||||||
#include "cli/z3ed_ascii_logo.h"
|
#include "cli/z3ed_ascii_logo.h"
|
||||||
#include "cli/service/agent/simple_chat_session.h"
|
#include "cli/service/agent/simple_chat_session.h"
|
||||||
#include "cli/service/agent/conversational_agent_service.h"
|
#include "cli/service/agent/conversational_agent_service.h"
|
||||||
@@ -865,7 +864,7 @@ void DashboardComponent(ftxui::ScreenInteractive &screen) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
auto event_handler = CatchEvent(layout, [&](Event event) {
|
auto event_handler = CatchEvent(layout, [&](const Event& event) {
|
||||||
if (event == Event::Character('q')) {
|
if (event == Event::Character('q')) {
|
||||||
SwitchComponents(screen, LayoutID::kExit);
|
SwitchComponents(screen, LayoutID::kExit);
|
||||||
return true;
|
return true;
|
||||||
@@ -943,7 +942,7 @@ void MainMenuComponent(ftxui::ScreenInteractive &screen) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Catch events like pressing Enter to switch layout or pressing 'q' to exit.
|
// Catch events like pressing Enter to switch layout or pressing 'q' to exit.
|
||||||
auto main_component = CatchEvent(renderer, [&](Event event) {
|
auto main_component = CatchEvent(renderer, [&](const Event& event) {
|
||||||
if (event == Event::Return) {
|
if (event == Event::Return) {
|
||||||
switch ((MainMenuEntry)selected) {
|
switch ((MainMenuEntry)selected) {
|
||||||
case MainMenuEntry::kLoadRom:
|
case MainMenuEntry::kLoadRom:
|
||||||
@@ -989,141 +988,22 @@ void MainMenuComponent(ftxui::ScreenInteractive &screen) {
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void ShowMain() {
|
void ShowMain() {
|
||||||
auto screen = ScreenInteractive::TerminalOutput();
|
// Use the new unified layout system
|
||||||
while (app_context.current_layout != LayoutID::kExit) {
|
UnifiedLayout unified_layout(&app_context.rom);
|
||||||
if (app_context.rom.is_loaded() && app_context.current_layout == LayoutID::kMainMenu) {
|
|
||||||
app_context.current_layout = LayoutID::kDashboard;
|
// Configure the layout
|
||||||
}
|
LayoutConfig config;
|
||||||
|
config.left_panel_width = 30;
|
||||||
switch (app_context.current_layout) {
|
config.right_panel_width = 40;
|
||||||
case LayoutID::kDashboard: {
|
config.bottom_panel_height = 15;
|
||||||
DashboardComponent(screen);
|
config.show_chat = true;
|
||||||
} break;
|
config.show_status = true;
|
||||||
case LayoutID::kMainMenu: {
|
config.show_tools = true;
|
||||||
MainMenuComponent(screen);
|
|
||||||
} break;
|
unified_layout.SetLayoutConfig(config);
|
||||||
case LayoutID::kLoadRom: {
|
|
||||||
LoadRomComponent(screen);
|
// Run the unified layout
|
||||||
} break;
|
unified_layout.Run();
|
||||||
case LayoutID::kAIAgentChat: {
|
|
||||||
// Launch simple chat session for agent interaction
|
|
||||||
agent::SimpleChatSession chat;
|
|
||||||
chat.SetRomContext(&app_context.rom);
|
|
||||||
agent::AgentConfig config;
|
|
||||||
config.output_format = agent::AgentOutputFormat::kFriendly;
|
|
||||||
chat.SetConfig(config);
|
|
||||||
|
|
||||||
std::cout << "\n🤖 AI Agent Chat (type 'back' to return to menu)\n" << std::endl;
|
|
||||||
chat.RunInteractive();
|
|
||||||
|
|
||||||
app_context.current_layout = LayoutID::kMainMenu;
|
|
||||||
} break;
|
|
||||||
case LayoutID::kTodoManager: {
|
|
||||||
TodoManagerComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kRomTools: {
|
|
||||||
// Show submenu for ROM tools
|
|
||||||
int submenu_selected = 0;
|
|
||||||
static const std::vector<std::string> tools = {
|
|
||||||
"Apply Asar Patch", "Apply BPS Patch", "Extract Symbols",
|
|
||||||
"Validate Assembly", "Generate Save", "Back"
|
|
||||||
};
|
|
||||||
auto submenu = Menu(&tools, &submenu_selected);
|
|
||||||
auto submenu_component = CatchEvent(submenu, [&](Event event) {
|
|
||||||
if (event == Event::Return) {
|
|
||||||
if (submenu_selected == 0) app_context.current_layout = LayoutID::kApplyAsarPatch;
|
|
||||||
else if (submenu_selected == 1) app_context.current_layout = LayoutID::kApplyBpsPatch;
|
|
||||||
else if (submenu_selected == 2) app_context.current_layout = LayoutID::kExtractSymbols;
|
|
||||||
else if (submenu_selected == 3) app_context.current_layout = LayoutID::kValidateAssembly;
|
|
||||||
else if (submenu_selected == 4) app_context.current_layout = LayoutID::kGenerateSaveFile;
|
|
||||||
else app_context.current_layout = LayoutID::kMainMenu;
|
|
||||||
screen.ExitLoopClosure()();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
screen.Loop(submenu_component);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kGraphicsTools: {
|
|
||||||
// Show submenu for graphics tools
|
|
||||||
int submenu_selected = 0;
|
|
||||||
static const std::vector<std::string> tools = {
|
|
||||||
"Palette Editor", "Hex Viewer", "Back"
|
|
||||||
};
|
|
||||||
auto submenu = Menu(&tools, &submenu_selected);
|
|
||||||
auto submenu_component = CatchEvent(submenu, [&](Event event) {
|
|
||||||
if (event == Event::Return) {
|
|
||||||
if (submenu_selected == 0) app_context.current_layout = LayoutID::kPaletteEditor;
|
|
||||||
else if (submenu_selected == 1) app_context.current_layout = LayoutID::kHexViewer;
|
|
||||||
else app_context.current_layout = LayoutID::kMainMenu;
|
|
||||||
screen.ExitLoopClosure()();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
});
|
|
||||||
screen.Loop(submenu_component);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kTestingTools: {
|
|
||||||
app_context.error_message = "Testing tools coming soon";
|
|
||||||
app_context.current_layout = LayoutID::kError;
|
|
||||||
} break;
|
|
||||||
case LayoutID::kSettings: {
|
|
||||||
app_context.error_message = "Settings TUI coming soon - use GUI for now";
|
|
||||||
app_context.current_layout = LayoutID::kError;
|
|
||||||
} break;
|
|
||||||
case LayoutID::kApplyAsarPatch: {
|
|
||||||
ApplyAsarPatchComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kApplyBpsPatch: {
|
|
||||||
ApplyBpsPatchComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kExtractSymbols: {
|
|
||||||
ExtractSymbolsComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kValidateAssembly: {
|
|
||||||
ValidateAssemblyComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kGenerateSaveFile: {
|
|
||||||
GenerateSaveFileComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kPaletteEditor: {
|
|
||||||
PaletteEditorComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kHexViewer: {
|
|
||||||
HexViewerComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kCommandPalette: {
|
|
||||||
CommandPaletteComponent component;
|
|
||||||
auto cmd_component = component.Render();
|
|
||||||
screen.Loop(cmd_component);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kHelp: {
|
|
||||||
HelpComponent(screen);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kError: {
|
|
||||||
// Display error message and return to main menu.
|
|
||||||
auto error_button = Button("Back to Main Menu", [&] {
|
|
||||||
app_context.error_message.clear();
|
|
||||||
SwitchComponents(screen, LayoutID::kMainMenu);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto error_renderer = Renderer(error_button, [&] {
|
|
||||||
return vbox({
|
|
||||||
text("⚠️ Error") | center | bold | color(Color::Red),
|
|
||||||
separator(),
|
|
||||||
text(app_context.error_message) | color(Color::Yellow) | center,
|
|
||||||
separator(),
|
|
||||||
error_button->Render() | center
|
|
||||||
}) | center | border;
|
|
||||||
});
|
|
||||||
|
|
||||||
screen.Loop(error_renderer);
|
|
||||||
} break;
|
|
||||||
case LayoutID::kExit:
|
|
||||||
default:
|
|
||||||
return; // Exit the application.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace cli
|
} // namespace cli
|
||||||
|
|||||||
569
src/cli/tui/unified_layout.cc
Normal file
569
src/cli/tui/unified_layout.cc
Normal file
@@ -0,0 +1,569 @@
|
|||||||
|
#include "cli/tui/unified_layout.h"
|
||||||
|
|
||||||
|
#include <ftxui/component/component.hpp>
|
||||||
|
#include <ftxui/component/screen_interactive.hpp>
|
||||||
|
#include <ftxui/dom/elements.hpp>
|
||||||
|
#include <ftxui/screen/terminal.hpp>
|
||||||
|
|
||||||
|
#include "absl/strings/str_cat.h"
|
||||||
|
#include "absl/strings/str_format.h"
|
||||||
|
#include "cli/tui/tui.h"
|
||||||
|
#include "cli/service/agent/conversational_agent_service.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
|
||||||
|
using namespace ftxui;
|
||||||
|
|
||||||
|
UnifiedLayout::UnifiedLayout(Rom* rom_context)
|
||||||
|
: screen_(ScreenInteractive::TerminalOutput()),
|
||||||
|
rom_context_(rom_context) {
|
||||||
|
// Initialize chat TUI
|
||||||
|
chat_tui_ = std::make_unique<tui::ChatTUI>(rom_context_);
|
||||||
|
|
||||||
|
// Set default configuration
|
||||||
|
config_ = LayoutConfig{};
|
||||||
|
|
||||||
|
// Initialize state
|
||||||
|
state_ = PanelState{};
|
||||||
|
if (rom_context_) {
|
||||||
|
state_.current_rom_file = rom_context_->title();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create components
|
||||||
|
main_menu_panel_ = CreateMainMenuPanel();
|
||||||
|
chat_panel_ = CreateChatPanel();
|
||||||
|
status_panel_ = CreateStatusPanel();
|
||||||
|
tools_panel_ = CreateToolsPanel();
|
||||||
|
hex_viewer_panel_ = CreateHexViewerPanel();
|
||||||
|
palette_editor_panel_ = CreatePaletteEditorPanel();
|
||||||
|
todo_manager_panel_ = CreateTodoManagerPanel();
|
||||||
|
rom_tools_panel_ = CreateRomToolsPanel();
|
||||||
|
graphics_tools_panel_ = CreateGraphicsToolsPanel();
|
||||||
|
settings_panel_ = CreateSettingsPanel();
|
||||||
|
help_panel_ = CreateHelpPanel();
|
||||||
|
|
||||||
|
// Create layout
|
||||||
|
unified_layout_ = CreateUnifiedLayout();
|
||||||
|
|
||||||
|
// Set up event handlers
|
||||||
|
global_event_handler_ = [this](const Event& event) {
|
||||||
|
return HandleGlobalEvents(event);
|
||||||
|
};
|
||||||
|
|
||||||
|
panel_event_handler_ = [this](const Event& event) {
|
||||||
|
return HandlePanelEvents(event);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::Run() {
|
||||||
|
// Wrap the layout with event handling
|
||||||
|
auto event_handler = CatchEvent(unified_layout_, global_event_handler_);
|
||||||
|
|
||||||
|
screen_.Loop(event_handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::SetRomContext(Rom* rom_context) {
|
||||||
|
rom_context_ = rom_context;
|
||||||
|
if (chat_tui_) {
|
||||||
|
chat_tui_->SetRomContext(rom_context_);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rom_context_) {
|
||||||
|
state_.current_rom_file = rom_context_->title();
|
||||||
|
} else {
|
||||||
|
state_.current_rom_file.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::SwitchMainPanel(PanelType panel) {
|
||||||
|
state_.active_main_panel = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::SwitchToolPanel(PanelType panel) {
|
||||||
|
state_.active_tool_panel = panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::ToggleChat() {
|
||||||
|
config_.show_chat = !config_.show_chat;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::ToggleStatus() {
|
||||||
|
config_.show_status = !config_.show_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnifiedLayout::SetLayoutConfig(const LayoutConfig& config) {
|
||||||
|
config_ = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateMainMenuPanel() {
|
||||||
|
static int selected = 0;
|
||||||
|
MenuOption option;
|
||||||
|
option.focused_entry = &selected;
|
||||||
|
|
||||||
|
auto menu = Menu(&kMainMenuEntries, &selected, option);
|
||||||
|
|
||||||
|
return Renderer(menu, [&] {
|
||||||
|
return vbox({
|
||||||
|
text("🎮 Z3ED Main Menu") | bold | center,
|
||||||
|
separator(),
|
||||||
|
menu->Render(),
|
||||||
|
separator(),
|
||||||
|
text("↑/↓: Navigate | Enter: Select | q: Quit") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateChatPanel() {
|
||||||
|
// Create a simplified chat interface that integrates with the main layout
|
||||||
|
static std::string input_message;
|
||||||
|
auto input_component = Input(&input_message, "Type your message...");
|
||||||
|
|
||||||
|
auto send_button = Button("Send", [&] {
|
||||||
|
if (input_message.empty()) return;
|
||||||
|
|
||||||
|
// Handle chat commands
|
||||||
|
if (input_message == "/exit") {
|
||||||
|
screen_.Exit();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, just clear the input
|
||||||
|
// TODO: Integrate with agent service
|
||||||
|
input_message.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle Enter key
|
||||||
|
input_component = CatchEvent(input_component, [&](Event event) {
|
||||||
|
if (event == Event::Return) {
|
||||||
|
if (input_message.empty()) return true;
|
||||||
|
|
||||||
|
// Handle chat commands
|
||||||
|
if (input_message == "/exit") {
|
||||||
|
screen_.Exit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For now, just clear the input
|
||||||
|
input_message.clear();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
auto container = Container::Vertical({
|
||||||
|
input_component,
|
||||||
|
send_button
|
||||||
|
});
|
||||||
|
|
||||||
|
return Renderer(container, [&] {
|
||||||
|
return vbox({
|
||||||
|
text("🤖 AI Chat") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text("Chat functionality integrated into unified layout") | center | dim,
|
||||||
|
separator(),
|
||||||
|
hbox({
|
||||||
|
text("You: ") | bold,
|
||||||
|
input_component->Render() | flex,
|
||||||
|
text(" "),
|
||||||
|
send_button->Render()
|
||||||
|
}),
|
||||||
|
separator(),
|
||||||
|
text("Commands: /exit, /clear, /help") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateStatusPanel() {
|
||||||
|
return Renderer([&] {
|
||||||
|
std::string rom_info = rom_context_ ?
|
||||||
|
absl::StrFormat("ROM: %s | Size: %d bytes",
|
||||||
|
rom_context_->title(), rom_context_->size()) :
|
||||||
|
"No ROM loaded";
|
||||||
|
|
||||||
|
return vbox({
|
||||||
|
text("📊 Status") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text(rom_info) | color(Color::Green),
|
||||||
|
separator(),
|
||||||
|
text("Panel: ") | bold,
|
||||||
|
text(absl::StrFormat("%s",
|
||||||
|
state_.active_main_panel == PanelType::kMainMenu ? "Main Menu" :
|
||||||
|
state_.active_main_panel == PanelType::kChat ? "Chat" :
|
||||||
|
state_.active_main_panel == PanelType::kHexViewer ? "Hex Viewer" :
|
||||||
|
"Other")),
|
||||||
|
separator(),
|
||||||
|
text("Layout: ") | bold,
|
||||||
|
text(absl::StrFormat("Chat: %s | Status: %s",
|
||||||
|
config_.show_chat ? "ON" : "OFF",
|
||||||
|
config_.show_status ? "ON" : "OFF")),
|
||||||
|
separator(),
|
||||||
|
text("Press 'h' for help, 'q' to quit") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateToolsPanel() {
|
||||||
|
static int selected = 0;
|
||||||
|
static const std::vector<std::string> tools = {
|
||||||
|
"🔧 ROM Tools",
|
||||||
|
"🎨 Graphics Tools",
|
||||||
|
"📝 TODO Manager",
|
||||||
|
"⚙️ Settings",
|
||||||
|
"❓ Help"
|
||||||
|
};
|
||||||
|
|
||||||
|
auto menu = Menu(&tools, &selected);
|
||||||
|
|
||||||
|
return Renderer(menu, [&] {
|
||||||
|
return vbox({
|
||||||
|
text("🛠️ Tools") | bold | center,
|
||||||
|
separator(),
|
||||||
|
menu->Render(),
|
||||||
|
separator(),
|
||||||
|
text("Select a tool category") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateHexViewerPanel() {
|
||||||
|
static int offset = 0;
|
||||||
|
const int lines_to_show = 20;
|
||||||
|
|
||||||
|
return Renderer([&] {
|
||||||
|
if (!rom_context_) {
|
||||||
|
return vbox({
|
||||||
|
text("🔍 Hex Viewer") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text("No ROM loaded") | center | color(Color::Red),
|
||||||
|
separator(),
|
||||||
|
text("Load a ROM to view hex data") | center | dim
|
||||||
|
}) | border;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Element> rows;
|
||||||
|
for (int i = 0; i < lines_to_show; ++i) {
|
||||||
|
int current_offset = offset + (i * 16);
|
||||||
|
if (current_offset >= static_cast<int>(rom_context_->size())) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elements row;
|
||||||
|
row.push_back(text(absl::StrFormat("0x%08X: ", current_offset)) | color(Color::Yellow));
|
||||||
|
|
||||||
|
for (int j = 0; j < 16; ++j) {
|
||||||
|
if (current_offset + j < static_cast<int>(rom_context_->size())) {
|
||||||
|
row.push_back(text(absl::StrFormat("%02X ", rom_context_->vector()[current_offset + j])));
|
||||||
|
} else {
|
||||||
|
row.push_back(text(" "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
row.push_back(separator());
|
||||||
|
|
||||||
|
for (int j = 0; j < 16; ++j) {
|
||||||
|
if (current_offset + j < static_cast<int>(rom_context_->size())) {
|
||||||
|
char c = rom_context_->vector()[current_offset + j];
|
||||||
|
row.push_back(text(std::isprint(c) ? std::string(1, c) : "."));
|
||||||
|
} else {
|
||||||
|
row.push_back(text(" "));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rows.push_back(hbox(row));
|
||||||
|
}
|
||||||
|
|
||||||
|
return vbox({
|
||||||
|
text("🔍 Hex Viewer") | bold | center,
|
||||||
|
separator(),
|
||||||
|
vbox(rows) | frame | flex,
|
||||||
|
separator(),
|
||||||
|
text(absl::StrFormat("Offset: 0x%08X", offset)) | color(Color::Cyan),
|
||||||
|
separator(),
|
||||||
|
text("↑/↓: Scroll | q: Back") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreatePaletteEditorPanel() {
|
||||||
|
return Renderer([&] {
|
||||||
|
return vbox({
|
||||||
|
text("🎨 Palette Editor") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text("Palette editing functionality") | center,
|
||||||
|
text("coming soon...") | center | dim,
|
||||||
|
separator(),
|
||||||
|
text("This panel will allow editing") | center,
|
||||||
|
text("color palettes from the ROM") | center,
|
||||||
|
separator(),
|
||||||
|
text("Press 'q' to go back") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateTodoManagerPanel() {
|
||||||
|
return Renderer([&] {
|
||||||
|
return vbox({
|
||||||
|
text("📝 TODO Manager") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text("TODO management functionality") | center,
|
||||||
|
text("coming soon...") | center | dim,
|
||||||
|
separator(),
|
||||||
|
text("This panel will integrate with") | center,
|
||||||
|
text("the existing TODO manager") | center,
|
||||||
|
separator(),
|
||||||
|
text("Press 'q' to go back") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateRomToolsPanel() {
|
||||||
|
static int selected = 0;
|
||||||
|
static const std::vector<std::string> tools = {
|
||||||
|
"Apply Asar Patch",
|
||||||
|
"Apply BPS Patch",
|
||||||
|
"Extract Symbols",
|
||||||
|
"Validate Assembly",
|
||||||
|
"Generate Save File",
|
||||||
|
"Back"
|
||||||
|
};
|
||||||
|
|
||||||
|
auto menu = Menu(&tools, &selected);
|
||||||
|
|
||||||
|
return Renderer(menu, [&] {
|
||||||
|
return vbox({
|
||||||
|
text("🔧 ROM Tools") | bold | center,
|
||||||
|
separator(),
|
||||||
|
menu->Render(),
|
||||||
|
separator(),
|
||||||
|
text("Select a ROM tool") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateGraphicsToolsPanel() {
|
||||||
|
static int selected = 0;
|
||||||
|
static const std::vector<std::string> tools = {
|
||||||
|
"Palette Editor",
|
||||||
|
"Hex Viewer",
|
||||||
|
"Back"
|
||||||
|
};
|
||||||
|
|
||||||
|
auto menu = Menu(&tools, &selected);
|
||||||
|
|
||||||
|
return Renderer(menu, [&] {
|
||||||
|
return vbox({
|
||||||
|
text("🎨 Graphics Tools") | bold | center,
|
||||||
|
separator(),
|
||||||
|
menu->Render(),
|
||||||
|
separator(),
|
||||||
|
text("Select a graphics tool") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateSettingsPanel() {
|
||||||
|
return Renderer([&] {
|
||||||
|
return vbox({
|
||||||
|
text("⚙️ Settings") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text("Settings panel") | center,
|
||||||
|
text("coming soon...") | center | dim,
|
||||||
|
separator(),
|
||||||
|
text("This panel will contain") | center,
|
||||||
|
text("application settings") | center,
|
||||||
|
separator(),
|
||||||
|
text("Press 'q' to go back") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateHelpPanel() {
|
||||||
|
return Renderer([&] {
|
||||||
|
return vbox({
|
||||||
|
text("❓ Help") | bold | center,
|
||||||
|
separator(),
|
||||||
|
text("Z3ED Unified Layout Help") | center,
|
||||||
|
separator(),
|
||||||
|
text("Global Shortcuts:") | bold,
|
||||||
|
text(" q - Quit application"),
|
||||||
|
text(" h - Show this help"),
|
||||||
|
text(" c - Toggle chat panel"),
|
||||||
|
text(" s - Toggle status panel"),
|
||||||
|
text(" t - Switch to tools"),
|
||||||
|
text(" m - Switch to main menu"),
|
||||||
|
separator(),
|
||||||
|
text("Navigation:") | bold,
|
||||||
|
text(" ↑/↓ - Navigate menus"),
|
||||||
|
text(" Enter - Select item"),
|
||||||
|
text(" Tab - Switch panels"),
|
||||||
|
separator(),
|
||||||
|
text("Press 'q' to go back") | dim | center
|
||||||
|
}) | border;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateUnifiedLayout() {
|
||||||
|
top_layout_ = CreateTopLayout();
|
||||||
|
bottom_layout_ = CreateBottomLayout();
|
||||||
|
|
||||||
|
// Create vertical split between top and bottom
|
||||||
|
return ResizableSplitBottom(
|
||||||
|
top_layout_,
|
||||||
|
bottom_layout_,
|
||||||
|
&config_.bottom_panel_height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateTopLayout() {
|
||||||
|
// Left panel: Main menu or tools
|
||||||
|
Component left_panel;
|
||||||
|
switch (state_.active_main_panel) {
|
||||||
|
case PanelType::kMainMenu:
|
||||||
|
left_panel = main_menu_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kHexViewer:
|
||||||
|
left_panel = hex_viewer_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kPaletteEditor:
|
||||||
|
left_panel = palette_editor_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kTodoManager:
|
||||||
|
left_panel = todo_manager_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kRomTools:
|
||||||
|
left_panel = rom_tools_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kGraphicsTools:
|
||||||
|
left_panel = graphics_tools_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kSettings:
|
||||||
|
left_panel = settings_panel_;
|
||||||
|
break;
|
||||||
|
case PanelType::kHelp:
|
||||||
|
left_panel = help_panel_;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
left_panel = main_menu_panel_;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Right panel: Status or tools
|
||||||
|
Component right_panel;
|
||||||
|
if (config_.show_status) {
|
||||||
|
right_panel = status_panel_;
|
||||||
|
} else {
|
||||||
|
right_panel = tools_panel_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create horizontal split between left and right
|
||||||
|
return ResizableSplitRight(
|
||||||
|
left_panel,
|
||||||
|
right_panel,
|
||||||
|
&config_.right_panel_width
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Component UnifiedLayout::CreateBottomLayout() {
|
||||||
|
if (!config_.show_chat) {
|
||||||
|
return Renderer([] { return text(""); });
|
||||||
|
}
|
||||||
|
|
||||||
|
return chat_panel_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnifiedLayout::HandleGlobalEvents(const Event& event) {
|
||||||
|
// Global shortcuts
|
||||||
|
if (event == Event::Character('q')) {
|
||||||
|
screen_.Exit();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('h')) {
|
||||||
|
SwitchMainPanel(PanelType::kHelp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('c')) {
|
||||||
|
ToggleChat();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('s')) {
|
||||||
|
ToggleStatus();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('t')) {
|
||||||
|
SwitchMainPanel(PanelType::kRomTools);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event == Event::Character('m')) {
|
||||||
|
SwitchMainPanel(PanelType::kMainMenu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool UnifiedLayout::HandlePanelEvents(const Event& event) {
|
||||||
|
// Panel-specific event handling
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element UnifiedLayout::RenderPanelHeader(PanelType panel) {
|
||||||
|
std::string title;
|
||||||
|
switch (panel) {
|
||||||
|
case PanelType::kMainMenu:
|
||||||
|
title = "🎮 Main Menu";
|
||||||
|
break;
|
||||||
|
case PanelType::kChat:
|
||||||
|
title = "🤖 AI Chat";
|
||||||
|
break;
|
||||||
|
case PanelType::kStatus:
|
||||||
|
title = "📊 Status";
|
||||||
|
break;
|
||||||
|
case PanelType::kTools:
|
||||||
|
title = "🛠️ Tools";
|
||||||
|
break;
|
||||||
|
case PanelType::kHexViewer:
|
||||||
|
title = "🔍 Hex Viewer";
|
||||||
|
break;
|
||||||
|
case PanelType::kPaletteEditor:
|
||||||
|
title = "🎨 Palette Editor";
|
||||||
|
break;
|
||||||
|
case PanelType::kTodoManager:
|
||||||
|
title = "📝 TODO Manager";
|
||||||
|
break;
|
||||||
|
case PanelType::kRomTools:
|
||||||
|
title = "🔧 ROM Tools";
|
||||||
|
break;
|
||||||
|
case PanelType::kGraphicsTools:
|
||||||
|
title = "🎨 Graphics Tools";
|
||||||
|
break;
|
||||||
|
case PanelType::kSettings:
|
||||||
|
title = "⚙️ Settings";
|
||||||
|
break;
|
||||||
|
case PanelType::kHelp:
|
||||||
|
title = "❓ Help";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return text(title) | bold | center;
|
||||||
|
}
|
||||||
|
|
||||||
|
Element UnifiedLayout::RenderStatusBar() {
|
||||||
|
return hbox({
|
||||||
|
text(absl::StrFormat("Panel: %s",
|
||||||
|
state_.active_main_panel == PanelType::kMainMenu ? "Main" : "Other")) | color(Color::Cyan),
|
||||||
|
filler(),
|
||||||
|
text(absl::StrFormat("ROM: %s",
|
||||||
|
state_.current_rom_file.empty() ? "None" : state_.current_rom_file)) | color(Color::Green),
|
||||||
|
filler(),
|
||||||
|
text("q: Quit | h: Help | c: Chat | s: Status") | dim
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
140
src/cli/tui/unified_layout.h
Normal file
140
src/cli/tui/unified_layout.h
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#ifndef YAZE_CLI_TUI_UNIFIED_LAYOUT_H
|
||||||
|
#define YAZE_CLI_TUI_UNIFIED_LAYOUT_H
|
||||||
|
|
||||||
|
#include <ftxui/component/component.hpp>
|
||||||
|
#include <ftxui/dom/elements.hpp>
|
||||||
|
#include <ftxui/screen/screen.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "app/rom.h"
|
||||||
|
#include "cli/tui/chat_tui.h"
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
namespace tui {
|
||||||
|
class ChatTUI;
|
||||||
|
} // namespace tui
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
namespace yaze {
|
||||||
|
namespace cli {
|
||||||
|
|
||||||
|
// Panel types for the unified layout
|
||||||
|
enum class PanelType {
|
||||||
|
kMainMenu,
|
||||||
|
kChat,
|
||||||
|
kStatus,
|
||||||
|
kTools,
|
||||||
|
kHexViewer,
|
||||||
|
kPaletteEditor,
|
||||||
|
kTodoManager,
|
||||||
|
kRomTools,
|
||||||
|
kGraphicsTools,
|
||||||
|
kSettings,
|
||||||
|
kHelp
|
||||||
|
};
|
||||||
|
|
||||||
|
// Layout configuration
|
||||||
|
struct LayoutConfig {
|
||||||
|
int left_panel_width = 30; // Menu/Tools panel
|
||||||
|
int right_panel_width = 40; // Status/Info panel
|
||||||
|
int bottom_panel_height = 15; // Chat panel
|
||||||
|
bool show_chat = true;
|
||||||
|
bool show_status = true;
|
||||||
|
bool show_tools = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Panel state management
|
||||||
|
struct PanelState {
|
||||||
|
PanelType active_main_panel = PanelType::kMainMenu;
|
||||||
|
PanelType active_tool_panel = PanelType::kRomTools;
|
||||||
|
bool chat_focused = false;
|
||||||
|
bool status_expanded = false;
|
||||||
|
std::string current_rom_file;
|
||||||
|
std::string current_error;
|
||||||
|
};
|
||||||
|
|
||||||
|
class UnifiedLayout {
|
||||||
|
public:
|
||||||
|
explicit UnifiedLayout(Rom* rom_context = nullptr);
|
||||||
|
|
||||||
|
// Main interface
|
||||||
|
void Run();
|
||||||
|
void SetRomContext(Rom* rom_context);
|
||||||
|
|
||||||
|
// Panel management
|
||||||
|
void SwitchMainPanel(PanelType panel);
|
||||||
|
void SwitchToolPanel(PanelType panel);
|
||||||
|
void ToggleChat();
|
||||||
|
void ToggleStatus();
|
||||||
|
|
||||||
|
// Configuration
|
||||||
|
void SetLayoutConfig(const LayoutConfig& config);
|
||||||
|
LayoutConfig GetLayoutConfig() const { return config_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Component creation
|
||||||
|
ftxui::Component CreateMainMenuPanel();
|
||||||
|
ftxui::Component CreateChatPanel();
|
||||||
|
ftxui::Component CreateStatusPanel();
|
||||||
|
ftxui::Component CreateToolsPanel();
|
||||||
|
ftxui::Component CreateHexViewerPanel();
|
||||||
|
ftxui::Component CreatePaletteEditorPanel();
|
||||||
|
ftxui::Component CreateTodoManagerPanel();
|
||||||
|
ftxui::Component CreateRomToolsPanel();
|
||||||
|
ftxui::Component CreateGraphicsToolsPanel();
|
||||||
|
ftxui::Component CreateSettingsPanel();
|
||||||
|
ftxui::Component CreateHelpPanel();
|
||||||
|
|
||||||
|
// Layout assembly
|
||||||
|
ftxui::Component CreateUnifiedLayout();
|
||||||
|
ftxui::Component CreateTopLayout();
|
||||||
|
ftxui::Component CreateBottomLayout();
|
||||||
|
|
||||||
|
// Event handling
|
||||||
|
bool HandleGlobalEvents(const ftxui::Event& event);
|
||||||
|
bool HandlePanelEvents(const ftxui::Event& event);
|
||||||
|
|
||||||
|
// Rendering
|
||||||
|
ftxui::Element RenderPanelHeader(PanelType panel);
|
||||||
|
ftxui::Element RenderStatusBar();
|
||||||
|
|
||||||
|
// State
|
||||||
|
ftxui::ScreenInteractive screen_;
|
||||||
|
Rom* rom_context_;
|
||||||
|
LayoutConfig config_;
|
||||||
|
PanelState state_;
|
||||||
|
|
||||||
|
// Components
|
||||||
|
std::unique_ptr<tui::ChatTUI> chat_tui_;
|
||||||
|
|
||||||
|
// Panel components (cached for performance)
|
||||||
|
ftxui::Component main_menu_panel_;
|
||||||
|
ftxui::Component chat_panel_;
|
||||||
|
ftxui::Component status_panel_;
|
||||||
|
ftxui::Component tools_panel_;
|
||||||
|
ftxui::Component hex_viewer_panel_;
|
||||||
|
ftxui::Component palette_editor_panel_;
|
||||||
|
ftxui::Component todo_manager_panel_;
|
||||||
|
ftxui::Component rom_tools_panel_;
|
||||||
|
ftxui::Component graphics_tools_panel_;
|
||||||
|
ftxui::Component settings_panel_;
|
||||||
|
ftxui::Component help_panel_;
|
||||||
|
|
||||||
|
// Layout components
|
||||||
|
ftxui::Component unified_layout_;
|
||||||
|
ftxui::Component top_layout_;
|
||||||
|
ftxui::Component bottom_layout_;
|
||||||
|
|
||||||
|
// Event handlers
|
||||||
|
std::function<bool(const ftxui::Event&)> global_event_handler_;
|
||||||
|
std::function<bool(const ftxui::Event&)> panel_event_handler_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cli
|
||||||
|
} // namespace yaze
|
||||||
|
|
||||||
|
#endif // YAZE_CLI_TUI_UNIFIED_LAYOUT_H
|
||||||
@@ -48,6 +48,9 @@ add_executable(
|
|||||||
cli/cli_main.cc
|
cli/cli_main.cc
|
||||||
cli/cli.cc
|
cli/cli.cc
|
||||||
cli/tui/tui.cc
|
cli/tui/tui.cc
|
||||||
|
cli/tui/unified_layout.cc
|
||||||
|
cli/tui/enhanced_chat_component.cc
|
||||||
|
cli/tui/enhanced_status_panel.cc
|
||||||
cli/handlers/compress.cc
|
cli/handlers/compress.cc
|
||||||
cli/handlers/patch.cc
|
cli/handlers/patch.cc
|
||||||
cli/handlers/tile16_transfer.cc
|
cli/handlers/tile16_transfer.cc
|
||||||
|
|||||||
Reference in New Issue
Block a user