fix(console): RPC modal — pointer cursor + Material restyle
Two issues from the audit: - Cursor: hovering the modal showed the console's text-select cursor. The output's mouse-interaction guard only suppressed itself under ImGui popups, but this modal is a BeginOverlayDialog (not a popup), so the console kept setting the text cursor underneath. Suppress output interaction while the reference modal is open (!show_commands_popup_). - Design: the two panes used hard 1px child borders and floated unpolished. Restyle to match the portfolio/wallets modals — each pane now sits on a soft DrawGlassPanel surface (borderless child + inner padding), category headers are subtle accent labels (no heavy filled bars), and the selected/hovered row gets a rounded Material fill instead of the sharp Selectable highlight. The glass panes are theme-adaptive (light on light skins), so the command-name blue and the mono example green are floored to readable contrast (FloorLight) and the detail heading uses theme Primary(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -791,7 +791,10 @@ void ConsoleTab::renderOutput()
|
|||||||
win_min.y + ImGui::GetWindowHeight());
|
win_min.y + ImGui::GetWindowHeight());
|
||||||
bool mouse_in_output = (mouse_pos.x >= win_min.x && mouse_pos.x < win_max.x &&
|
bool mouse_in_output = (mouse_pos.x >= win_min.x && mouse_pos.x < win_max.x &&
|
||||||
mouse_pos.y >= win_min.y && mouse_pos.y < win_max.y &&
|
mouse_pos.y >= win_min.y && mouse_pos.y < win_max.y &&
|
||||||
!ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopup));
|
!ImGui::IsPopupOpen("", ImGuiPopupFlags_AnyPopup) &&
|
||||||
|
// The RPC reference is a BeginOverlayDialog (not an ImGui popup), so it
|
||||||
|
// isn't caught above; suppress the output's text cursor + selection under it.
|
||||||
|
!show_commands_popup_);
|
||||||
handleOutputInteraction(mouse_pos, mouse_in_output);
|
handleOutputInteraction(mouse_pos, mouse_in_output);
|
||||||
|
|
||||||
// Draw the visible lines: accent bars, JSON indent guides, selection + filter highlight,
|
// Draw the visible lines: accent bars, JSON indent guides, selection + filter highlight,
|
||||||
@@ -1576,7 +1579,7 @@ void ConsoleTab::renderCommandDetail(const ConsoleCommandEntry& cmd, const char*
|
|||||||
|
|
||||||
// Heading: command name, then category + a safety badge for consequential commands.
|
// Heading: command name, then category + a safety badge for consequential commands.
|
||||||
ImGui::PushFont(Type().subtitle1());
|
ImGui::PushFont(Type().subtitle1());
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(120, 190, 255, 255)), "%s", cmd.name);
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(Primary()), "%s", cmd.name);
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()), "%s", catLabel);
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceDisabled()), "%s", catLabel);
|
||||||
if (cmd.destructive) {
|
if (cmd.destructive) {
|
||||||
@@ -1663,7 +1666,7 @@ void ConsoleTab::renderCommandDetail(const ConsoleCommandEntry& cmd, const char*
|
|||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), "%s", TR("console_ref_builds"));
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), "%s", TR("console_ref_builds"));
|
||||||
ImGui::PushFont(mono);
|
ImGui::PushFont(mono);
|
||||||
ImGui::PushTextWrapPos(0.0f);
|
ImGui::PushTextWrapPos(0.0f);
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(150, 200, 150, 255)), "%s", built.c_str());
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(FloorLight(IM_COL32(150, 200, 150, 255))), "%s", built.c_str());
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
}
|
}
|
||||||
@@ -1674,7 +1677,7 @@ void ConsoleTab::renderCommandDetail(const ConsoleCommandEntry& cmd, const char*
|
|||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), "%s", TR("console_ref_example"));
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(OnSurfaceMedium()), "%s", TR("console_ref_example"));
|
||||||
ImGui::PushFont(mono);
|
ImGui::PushFont(mono);
|
||||||
ImGui::PushTextWrapPos(0.0f);
|
ImGui::PushTextWrapPos(0.0f);
|
||||||
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(IM_COL32(150, 200, 150, 255)), "%s", cmd.example);
|
ImGui::TextColored(ImGui::ColorConvertU32ToFloat4(FloorLight(IM_COL32(150, 200, 150, 255))), "%s", cmd.example);
|
||||||
ImGui::PopTextWrapPos();
|
ImGui::PopTextWrapPos();
|
||||||
ImGui::PopFont();
|
ImGui::PopFont();
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingMd()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingMd()));
|
||||||
@@ -1808,23 +1811,37 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
float detailW = contentW - masterW - gap;
|
float detailW = contentW - masterW - gap;
|
||||||
|
|
||||||
ImFont* mono = Type().mono();
|
ImFont* mono = Type().mono();
|
||||||
ImU32 nameCol = IM_COL32(100, 180, 255, 255);
|
// The panes are theme-adaptive glass (light on light skins), so floor the link-blue to a readable
|
||||||
|
// contrast on light surfaces (FloorLight is a no-op on dark themes).
|
||||||
|
ImU32 nameCol = FloorLight(IM_COL32(100, 180, 255, 255));
|
||||||
float rowH = std::max(20.0f * dp, mono->LegacySize + 6.0f * dp);
|
float rowH = std::max(20.0f * dp, mono->LegacySize + 6.0f * dp);
|
||||||
|
|
||||||
// One master row: mono command name + a warning dot for consequential commands. Click selects
|
// One master row: mono command name + a warning dot for consequential commands, with a soft
|
||||||
// (drives the detail pane); double-click inserts.
|
// rounded selection/hover fill (Material, not the default sharp Selectable highlight). Click
|
||||||
|
// selects (drives the detail pane); double-click inserts.
|
||||||
auto drawRow = [&](int c, int i) {
|
auto drawRow = [&](int c, int i) {
|
||||||
const ConsoleCommandEntry& cmd = categories[c].commands[i];
|
const ConsoleCommandEntry& cmd = categories[c].commands[i];
|
||||||
bool sel = (cmd_sel_cat_ == c && cmd_sel_idx_ == i);
|
bool sel = (cmd_sel_cat_ == c && cmd_sel_idx_ == i);
|
||||||
ImGui::PushID(c * 1000 + i);
|
ImGui::PushID(c * 1000 + i);
|
||||||
ImVec2 rmn = ImGui::GetCursorScreenPos();
|
ImVec2 rmn = ImGui::GetCursorScreenPos();
|
||||||
if (ImGui::Selectable("##cmdrow", sel, ImGuiSelectableFlags_SpanAvailWidth, ImVec2(0, rowH)))
|
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0, 0, 0, 0)); // we draw our own fill
|
||||||
{ cmd_sel_cat_ = c; cmd_sel_idx_ = i; }
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0, 0, 0, 0));
|
||||||
if (ImGui::IsItemHovered()) {
|
ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0, 0, 0, 0));
|
||||||
|
bool clicked = ImGui::Selectable("##cmdrow", sel, ImGuiSelectableFlags_SpanAvailWidth,
|
||||||
|
ImVec2(0, rowH));
|
||||||
|
ImGui::PopStyleColor(3);
|
||||||
|
bool hov = ImGui::IsItemHovered();
|
||||||
|
if (clicked) { cmd_sel_cat_ = c; cmd_sel_idx_ = i; }
|
||||||
|
if (hov) {
|
||||||
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
ImGui::SetMouseCursor(ImGuiMouseCursor_Hand);
|
||||||
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) insertCommandToInput(cmd);
|
if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) insertCommandToInput(cmd);
|
||||||
}
|
}
|
||||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||||
|
float rowW = ImGui::GetItemRectSize().x;
|
||||||
|
if (sel || hov)
|
||||||
|
dl->AddRectFilled(ImVec2(rmn.x, rmn.y + 1.0f * dp),
|
||||||
|
ImVec2(rmn.x + rowW, rmn.y + rowH - 1.0f * dp),
|
||||||
|
sel ? WithAlpha(Primary(), 52) : WithAlpha(OnSurface(), 16), 6.0f * dp);
|
||||||
float tx = rmn.x + Layout::spacingSm();
|
float tx = rmn.x + Layout::spacingSm();
|
||||||
if (cmd.destructive) {
|
if (cmd.destructive) {
|
||||||
float r = 3.0f * dp;
|
float r = 3.0f * dp;
|
||||||
@@ -1836,8 +1853,19 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Both panes sit on soft Material glass surfaces (no hard 1px child border) with inner padding.
|
||||||
|
GlassPanelSpec paneGlass;
|
||||||
|
paneGlass.rounding = 14.0f;
|
||||||
|
paneGlass.fillAlpha = 30;
|
||||||
|
paneGlass.borderAlpha = 30;
|
||||||
|
|
||||||
// MASTER pane.
|
// MASTER pane.
|
||||||
ImGui::BeginChild("##cmdMaster", ImVec2(masterW, bodyH), true);
|
{
|
||||||
|
ImVec2 mMin = ImGui::GetCursorScreenPos();
|
||||||
|
DrawGlassPanel(ImGui::GetWindowDrawList(), mMin, ImVec2(mMin.x + masterW, mMin.y + bodyH), paneGlass);
|
||||||
|
}
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(Layout::spacingMd(), Layout::spacingSm()));
|
||||||
|
ImGui::BeginChild("##cmdMaster", ImVec2(masterW, bodyH), ImGuiChildFlags_AlwaysUseWindowPadding);
|
||||||
{
|
{
|
||||||
if (order.empty()) {
|
if (order.empty()) {
|
||||||
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("console_ref_no_match"));
|
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("console_ref_no_match"));
|
||||||
@@ -1845,21 +1873,33 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
for (auto& p : order) drawRow(p.first, p.second);
|
for (auto& p : order) drawRow(p.first, p.second);
|
||||||
} else {
|
} else {
|
||||||
for (int c = 0; c < (int)categories.size(); c++) {
|
for (int c = 0; c < (int)categories.size(); c++) {
|
||||||
|
// Subtle accent-labelled section header (no heavy filled bar).
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0, 0, 0, 0));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_HeaderHovered,
|
||||||
|
ImGui::ColorConvertU32ToFloat4(WithAlpha(OnSurface(), 14)));
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_HeaderActive,
|
||||||
|
ImGui::ColorConvertU32ToFloat4(WithAlpha(OnSurface(), 20)));
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(Primary()));
|
ImGui::PushStyleColor(ImGuiCol_Text, ImGui::ColorConvertU32ToFloat4(Primary()));
|
||||||
bool open = ImGui::CollapsingHeader(consoleCategoryLabel(categories[c].name),
|
bool open = ImGui::CollapsingHeader(consoleCategoryLabel(categories[c].name),
|
||||||
ImGuiTreeNodeFlags_DefaultOpen);
|
ImGuiTreeNodeFlags_DefaultOpen);
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor(4);
|
||||||
if (open)
|
if (open)
|
||||||
for (int i = 0; i < categories[c].count; i++) drawRow(c, i);
|
for (int i = 0; i < categories[c].count; i++) drawRow(c, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
ImGui::SameLine(0, gap);
|
ImGui::SameLine(0, gap);
|
||||||
|
|
||||||
// DETAIL pane.
|
// DETAIL pane.
|
||||||
ImGui::BeginChild("##cmdDetail", ImVec2(detailW, bodyH), true);
|
{
|
||||||
|
ImVec2 dMin = ImGui::GetCursorScreenPos();
|
||||||
|
DrawGlassPanel(ImGui::GetWindowDrawList(), dMin, ImVec2(dMin.x + detailW, dMin.y + bodyH), paneGlass);
|
||||||
|
}
|
||||||
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(Layout::spacingLg(), Layout::spacingMd()));
|
||||||
|
ImGui::BeginChild("##cmdDetail", ImVec2(detailW, bodyH), ImGuiChildFlags_AlwaysUseWindowPadding);
|
||||||
if (cmd_sel_cat_ >= 0 && cmd_sel_cat_ < (int)categories.size() &&
|
if (cmd_sel_cat_ >= 0 && cmd_sel_cat_ < (int)categories.size() &&
|
||||||
cmd_sel_idx_ >= 0 && cmd_sel_idx_ < categories[cmd_sel_cat_].count) {
|
cmd_sel_idx_ >= 0 && cmd_sel_idx_ < categories[cmd_sel_cat_].count) {
|
||||||
renderCommandDetail(categories[cmd_sel_cat_].commands[cmd_sel_idx_],
|
renderCommandDetail(categories[cmd_sel_cat_].commands[cmd_sel_idx_],
|
||||||
@@ -1870,6 +1910,7 @@ void ConsoleTab::renderCommandsPopup()
|
|||||||
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("console_ref_select_hint"));
|
Type().textColored(TypeStyle::Caption, OnSurfaceDisabled(), TR("console_ref_select_hint"));
|
||||||
}
|
}
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
// Footer.
|
// Footer.
|
||||||
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
ImGui::Dummy(ImVec2(0, Layout::spacingXs()));
|
||||||
|
|||||||
Reference in New Issue
Block a user