feat: Refactor UI Layouts and Enhance Visibility in AgentChatWidget and AgentEditor

- Restored a compact single-row layout for the AI provider selection in AgentChatWidget, improving visibility and accessibility.
- Removed redundant RenderAgentConfigPanel to streamline the UI, ensuring the connection header is always visible.
- Updated the collaboration panel to be always visible, enhancing user interaction without the need for collapsing headers.
- Modified the AgentEditor layout to feature a three-column design with always-visible settings and status cards, improving organization and user experience.
- Enhanced the chat history popup with a more compact title and provider dropdown, ensuring buttons are properly spaced and functional.
This commit is contained in:
scawful
2025-10-05 12:46:00 -04:00
parent 8e7c179d47
commit 02a72051f6
3 changed files with 120 additions and 66 deletions

View File

@@ -830,9 +830,10 @@ void AgentChatWidget::Draw() {
float vertical_padding = (55.0f - content_height) / 2.0f; float vertical_padding = (55.0f - content_height) / 2.0f;
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + vertical_padding); ImGui::SetCursorPosY(ImGui::GetCursorPosY() + vertical_padding);
// Two-row layout for better visibility // Compact single row layout (restored)
ImGui::Text(ICON_MD_SMART_TOY " AI Provider:"); ImGui::TextColored(accent_color, ICON_MD_SMART_TOY);
ImGui::SetNextItemWidth(-1); ImGui::SameLine();
ImGui::SetNextItemWidth(95);
const char* providers[] = {"Mock", "Ollama", "Gemini"}; const char* providers[] = {"Mock", "Ollama", "Gemini"};
int current_provider = (agent_config_.ai_provider == "mock") ? 0 int current_provider = (agent_config_.ai_provider == "mock") ? 0
: (agent_config_.ai_provider == "ollama") ? 1 : (agent_config_.ai_provider == "ollama") ? 1
@@ -1036,10 +1037,11 @@ void AgentChatWidget::Draw() {
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,
ImVec2(4, 3)); // Compact padding ImVec2(4, 3)); // Compact padding
RenderAgentConfigPanel(); // Removed RenderAgentConfigPanel - duplicates connection header
RenderZ3EDCommandPanel(); RenderZ3EDCommandPanel();
RenderMultimodalPanel(); RenderMultimodalPanel();
RenderCollaborationPanel(); RenderCollaborationPanel();
RenderRomSyncPanel(); // Always visible now
RenderProposalManagerPanel(); RenderProposalManagerPanel();
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
@@ -1056,15 +1058,16 @@ void AgentChatWidget::Draw() {
void AgentChatWidget::RenderCollaborationPanel() { void AgentChatWidget::RenderCollaborationPanel() {
ImGui::PushID("CollabPanel"); ImGui::PushID("CollabPanel");
// Update reactive status color based on connection state // Update reactive status color
const bool connected = collaboration_state_.active; const bool connected = collaboration_state_.active;
collaboration_status_color_ = connected ? ImVec4(0.133f, 0.545f, 0.133f, 1.0f) collaboration_status_color_ = connected ? ImVec4(0.133f, 0.545f, 0.133f, 1.0f)
: ImVec4(0.6f, 0.6f, 0.6f, 1.0f); : ImVec4(0.6f, 0.6f, 0.6f, 1.0f);
if (!ImGui::CollapsingHeader(ICON_MD_PEOPLE " Collaboration & Network")) { // Always visible (no collapsing header)
ImGui::PopID(); ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.12f, 0.14f, 0.18f, 0.95f));
return; ImGui::BeginChild("CollabPanel", ImVec2(0, 200), true);
} ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_PEOPLE " Collaboration");
ImGui::Separator();
// Mode selector (compact inline) // Mode selector (compact inline)
ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f),
@@ -1383,6 +1386,8 @@ void AgentChatWidget::RenderCollaborationPanel() {
ImGui::EndTable(); ImGui::EndTable();
} }
ImGui::EndChild();
ImGui::PopStyleColor();
ImGui::PopID(); // CollabPanel ImGui::PopID(); // CollabPanel
} }

View File

@@ -183,28 +183,34 @@ void AgentEditor::DrawDashboard() {
if (ImGui::BeginTabItem(ICON_MD_SMART_TOY " Bot Studio")) { if (ImGui::BeginTabItem(ICON_MD_SMART_TOY " Bot Studio")) {
ImGui::Spacing(); ImGui::Spacing();
// Use ImGui table for clean 3-column resizable layout // Three-column layout: Config+Status | Editors | Profiles
ImGuiTableFlags table_flags = ImGuiTableFlags_Resizable | ImGuiTableFlags table_flags = ImGuiTableFlags_Resizable |
ImGuiTableFlags_BordersInnerV | ImGuiTableFlags_BordersInnerV |
ImGuiTableFlags_SizingStretchProp; ImGuiTableFlags_SizingStretchProp;
if (ImGui::BeginTable("BotStudioLayout", 3, table_flags)) { if (ImGui::BeginTable("BotStudioLayout", 3, table_flags)) {
ImGui::TableSetupColumn("Config", ImGuiTableColumnFlags_WidthFixed, 380.0f); ImGui::TableSetupColumn("Settings", ImGuiTableColumnFlags_WidthFixed, 320.0f);
ImGui::TableSetupColumn("Editors", ImGuiTableColumnFlags_WidthStretch); ImGui::TableSetupColumn("Editors", ImGuiTableColumnFlags_WidthStretch);
ImGui::TableSetupColumn("Profiles", ImGuiTableColumnFlags_WidthFixed, 320.0f); ImGui::TableSetupColumn("Profiles", ImGuiTableColumnFlags_WidthFixed, 280.0f);
ImGui::TableNextRow(); ImGui::TableNextRow();
// Column 1: Configuration // Column 1: AI Provider, Behavior, ROM, Tips, Metrics (merged!)
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushID("ConfigColumn"); ImGui::PushID("SettingsColumn");
// Provider settings (always visible)
DrawConfigurationPanel(); DrawConfigurationPanel();
ImGui::Spacing();
// Status cards (always visible)
DrawStatusPanel();
ImGui::PopID(); ImGui::PopID();
// Column 2: Editors (Prompt + Tiles + New) // Column 2: Tabbed Editors
ImGui::TableNextColumn(); ImGui::TableNextColumn();
ImGui::PushID("EditorsColumn"); ImGui::PushID("EditorsColumn");
// Tabbed editors for better organization
if (ImGui::BeginTabBar("EditorTabs", ImGuiTabBarFlags_None)) { if (ImGui::BeginTabBar("EditorTabs", ImGuiTabBarFlags_None)) {
if (ImGui::BeginTabItem(ICON_MD_EDIT " System Prompt")) { if (ImGui::BeginTabItem(ICON_MD_EDIT " System Prompt")) {
DrawPromptEditorPanel(); DrawPromptEditorPanel();
@@ -474,42 +480,57 @@ void AgentEditor::DrawConfigurationPanel() {
} }
void AgentEditor::DrawStatusPanel() { void AgentEditor::DrawStatusPanel() {
// Chat Status // Always visible status cards (no collapsing)
if (ImGui::CollapsingHeader(ICON_MD_CHAT " Chat Status", ImGuiTreeNodeFlags_DefaultOpen)) {
if (chat_widget_ && chat_widget_->is_active()) { // Chat Status Card
ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f), ICON_MD_CHECK_CIRCLE " Chat Active"); ImGui::BeginChild("ChatStatusCard", ImVec2(0, 100), true);
} else { ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_CHAT " Chat");
ImGui::TextDisabled(ICON_MD_CANCEL " Chat Inactive"); ImGui::Separator();
}
if (chat_widget_ && chat_widget_->is_active()) {
ImGui::Spacing(); ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f), ICON_MD_CHECK_CIRCLE " Active");
if (ImGui::Button(ICON_MD_OPEN_IN_NEW " Open Chat", ImVec2(-1, 0))) { } else {
OpenChatWindow(); ImGui::TextDisabled(ICON_MD_CANCEL " Inactive");
}
} }
// ROM Context ImGui::Spacing();
if (ImGui::CollapsingHeader(ICON_MD_GAMEPAD " ROM Context")) { if (ImGui::Button(ICON_MD_OPEN_IN_NEW " Open", ImVec2(-1, 0))) {
if (rom_ && rom_->is_loaded()) { OpenChatWindow();
ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f), ICON_MD_CHECK_CIRCLE " ROM Loaded");
ImGui::TextDisabled("ROM is ready for agent operations");
} else {
ImGui::TextColored(ImVec4(0.8f, 0.2f, 0.2f, 1.0f), ICON_MD_WARNING " No ROM");
ImGui::TextDisabled("Load a ROM to enable full features");
}
} }
ImGui::EndChild();
// Collaboration Status ImGui::Spacing();
if (ImGui::CollapsingHeader(ICON_MD_PEOPLE " Collaboration")) {
ImGui::TextDisabled("Mode: %s", current_mode_ == CollaborationMode::kLocal ? "Local" : "Network"); // ROM Context Card
if (in_session_) { ImGui::BeginChild("RomStatusCard", ImVec2(0, 100), true);
ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f), ICON_MD_CHECK_CIRCLE " In Session"); ImGui::TextColored(ImVec4(1.0f, 0.843f, 0.0f, 1.0f), ICON_MD_GAMEPAD " ROM");
ImGui::TextDisabled("Session: %s", current_session_name_.c_str()); ImGui::Separator();
ImGui::TextDisabled("Participants: %zu", current_participants_.size());
} else { if (rom_ && rom_->is_loaded()) {
ImGui::TextDisabled(ICON_MD_INFO " Not in session"); ImGui::TextColored(ImVec4(0.133f, 0.545f, 0.133f, 1.0f), ICON_MD_CHECK_CIRCLE " Loaded");
} ImGui::TextDisabled("Title: %s", rom_->title().c_str());
ImGui::TextDisabled("Tools: Ready");
} else {
ImGui::TextColored(ImVec4(0.8f, 0.2f, 0.2f, 1.0f), ICON_MD_WARNING " Not Loaded");
ImGui::TextDisabled("Load ROM for AI tools");
} }
ImGui::EndChild();
ImGui::Spacing();
// Quick Tips Card
ImGui::BeginChild("QuickTipsCard", ImVec2(0, 150), true);
ImGui::TextColored(ImVec4(0.196f, 0.6f, 0.8f, 1.0f), ICON_MD_TIPS_AND_UPDATES " Quick Tips");
ImGui::Separator();
ImGui::Spacing();
ImGui::BulletText("Ctrl+H: Toggle chat popup");
ImGui::BulletText("Ctrl+P: View proposals");
ImGui::BulletText("Edit prompts in center");
ImGui::BulletText("Create custom bots");
ImGui::BulletText("Save/load chat sessions");
ImGui::EndChild();
} }
void AgentEditor::DrawMetricsPanel() { void AgentEditor::DrawMetricsPanel() {

View File

@@ -179,10 +179,18 @@ void AgentChatHistoryPopup::DrawHeader() {
ImGui::Dummy(ImVec2(0, 8)); ImGui::Dummy(ImVec2(0, 8));
// Title // Title and provider dropdown (like connection header)
ImGui::Text("%s AI Chat", ICON_MD_CHAT); ImGui::Text(ICON_MD_CHAT);
ImGui::SameLine();
ImGui::SameLine(ImGui::GetContentRegionAvail().x - 95); // Model dropdown (compact)
ImGui::SetNextItemWidth(120);
static int provider_idx = 0;
const char* providers[] = {"Mock", "Ollama", "Gemini"};
ImGui::Combo("##popup_provider", &provider_idx, providers, 3);
// Buttons properly spaced from right edge
ImGui::SameLine(ImGui::GetCursorPosX() + ImGui::GetContentRegionAvail().x - 75.0f);
// Compact mode toggle // Compact mode toggle
if (ImGui::SmallButton(compact_mode_ ? ICON_MD_UNFOLD_MORE : ICON_MD_UNFOLD_LESS)) { if (ImGui::SmallButton(compact_mode_ ? ICON_MD_UNFOLD_MORE : ICON_MD_UNFOLD_LESS)) {
@@ -194,14 +202,15 @@ void AgentChatHistoryPopup::DrawHeader() {
ImGui::SameLine(); ImGui::SameLine();
// Full chat button // Full chat button (closes popup when opened)
if (ImGui::SmallButton(ICON_MD_OPEN_IN_NEW)) { if (ImGui::SmallButton(ICON_MD_OPEN_IN_NEW)) {
if (open_chat_callback_) { if (open_chat_callback_) {
open_chat_callback_(); open_chat_callback_();
visible_ = false; // Close popup when opening main chat
} }
} }
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Open full chat window"); ImGui::SetTooltip("Open full chat");
} }
ImGui::SameLine(); ImGui::SameLine();
@@ -233,38 +242,41 @@ void AgentChatHistoryPopup::DrawHeader() {
} }
void AgentChatHistoryPopup::DrawQuickActions() { void AgentChatHistoryPopup::DrawQuickActions() {
float button_width = (ImGui::GetContentRegionAvail().x - 8) / 3.0f; // 4 buttons with narrower width
float button_width = (ImGui::GetContentRegionAvail().x - 15) / 4.0f;
// Multimodal snapshot button // Multimodal snapshot button
if (ImGui::Button(ICON_MD_CAMERA, ImVec2(button_width, 32))) { if (ImGui::Button(ICON_MD_CAMERA, ImVec2(button_width, 30))) {
if (capture_snapshot_callback_) { if (capture_snapshot_callback_) {
capture_snapshot_callback_(); capture_snapshot_callback_();
} }
} }
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Capture screenshot for Gemini analysis"); ImGui::SetTooltip("Capture screenshot");
} }
ImGui::SameLine(); ImGui::SameLine();
// Filter button // Filter button with icon indicator
const char* filter_icon = ICON_MD_FILTER_LIST; const char* filter_icons[] = {ICON_MD_FILTER_LIST, ICON_MD_PERSON, ICON_MD_SMART_TOY};
if (ImGui::Button(filter_icon, ImVec2(button_width, 32))) { int filter_idx = static_cast<int>(message_filter_);
if (ImGui::Button(filter_icons[filter_idx], ImVec2(button_width, 30))) {
ImGui::OpenPopup("FilterPopup"); ImGui::OpenPopup("FilterPopup");
} }
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Filter messages"); const char* filter_names[] = {"All", "User only", "Agent only"};
ImGui::SetTooltip("Filter: %s", filter_names[filter_idx]);
} }
// Filter popup // Filter popup
if (ImGui::BeginPopup("FilterPopup")) { if (ImGui::BeginPopup("FilterPopup")) {
if (ImGui::Selectable("All Messages", message_filter_ == MessageFilter::kAll)) { if (ImGui::Selectable(ICON_MD_FILTER_LIST " All Messages", message_filter_ == MessageFilter::kAll)) {
message_filter_ = MessageFilter::kAll; message_filter_ = MessageFilter::kAll;
} }
if (ImGui::Selectable("User Only", message_filter_ == MessageFilter::kUserOnly)) { if (ImGui::Selectable(ICON_MD_PERSON " User Only", message_filter_ == MessageFilter::kUserOnly)) {
message_filter_ = MessageFilter::kUserOnly; message_filter_ = MessageFilter::kUserOnly;
} }
if (ImGui::Selectable("Agent Only", message_filter_ == MessageFilter::kAgentOnly)) { if (ImGui::Selectable(ICON_MD_SMART_TOY " Agent Only", message_filter_ == MessageFilter::kAgentOnly)) {
message_filter_ = MessageFilter::kAgentOnly; message_filter_ = MessageFilter::kAgentOnly;
} }
ImGui::EndPopup(); ImGui::EndPopup();
@@ -272,8 +284,20 @@ void AgentChatHistoryPopup::DrawQuickActions() {
ImGui::SameLine(); ImGui::SameLine();
// Save session button
if (ImGui::Button(ICON_MD_SAVE, ImVec2(button_width, 30))) {
if (toast_manager_) {
toast_manager_->Show(ICON_MD_SAVE " Session auto-saved", ToastType::kSuccess, 1.5f);
}
}
if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Save chat session");
}
ImGui::SameLine();
// Clear button // Clear button
if (ImGui::Button(ICON_MD_DELETE, ImVec2(button_width, 32))) { if (ImGui::Button(ICON_MD_DELETE, ImVec2(button_width, 30))) {
ClearHistory(); ClearHistory();
} }
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
@@ -287,7 +311,6 @@ void AgentChatHistoryPopup::DrawInputSection() {
// Input field using theme colors // Input field using theme colors
bool send_message = false; bool send_message = false;
ImGui::SetNextItemWidth(-1);
if (ImGui::InputTextMultiline("##popup_input", input_buffer_, sizeof(input_buffer_), if (ImGui::InputTextMultiline("##popup_input", input_buffer_, sizeof(input_buffer_),
ImVec2(-1, 60), ImVec2(-1, 60),
ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CtrlEnterForNewLine)) { ImGuiInputTextFlags_EnterReturnsTrue | ImGuiInputTextFlags_CtrlEnterForNewLine)) {
@@ -300,9 +323,10 @@ void AgentChatHistoryPopup::DrawInputSection() {
focus_input_ = false; focus_input_ = false;
} }
// Send button // Send button (proper width)
ImGui::Spacing(); ImGui::Spacing();
if (ImGui::Button(absl::StrFormat("%s Send", ICON_MD_SEND).c_str(), ImVec2(-1, 30)) || send_message) { float send_button_width = ImGui::GetContentRegionAvail().x;
if (ImGui::Button(absl::StrFormat("%s Send", ICON_MD_SEND).c_str(), ImVec2(send_button_width, 32)) || send_message) {
if (std::strlen(input_buffer_) > 0) { if (std::strlen(input_buffer_) > 0) {
SendMessage(input_buffer_); SendMessage(input_buffer_);
std::memset(input_buffer_, 0, sizeof(input_buffer_)); std::memset(input_buffer_, 0, sizeof(input_buffer_));
@@ -312,6 +336,10 @@ void AgentChatHistoryPopup::DrawInputSection() {
if (ImGui::IsItemHovered()) { if (ImGui::IsItemHovered()) {
ImGui::SetTooltip("Send message (Enter) • Ctrl+Enter for newline"); ImGui::SetTooltip("Send message (Enter) • Ctrl+Enter for newline");
} }
// Info text
ImGui::Spacing();
ImGui::TextDisabled(ICON_MD_INFO " Enter: send • Ctrl+Enter: newline");
} }
void AgentChatHistoryPopup::SendMessage(const std::string& message) { void AgentChatHistoryPopup::SendMessage(const std::string& message) {