cabana: fix clipped control outlines and filter sizing (#38795)

* cabana: fix clipped control outlines and filter sizing

* cabana: remove added comments

* cabana: document control helper API usage
This commit is contained in:
Trey Moen
2026-09-07 12:05:26 -07:00
committed by GitHub
parent cb70ba89aa
commit 9c02eebb72
6 changed files with 27 additions and 10 deletions
+1 -1
View File
@@ -139,7 +139,7 @@ void ChartView::updateLayout() {
const ImVec2 top_left = layout_.rect.Min + ImVec2(LAYOUT_MARGINS.x, LAYOUT_MARGINS.y);
layout_.move_icon_rect = ImRect(top_left, top_left + grip);
const ImVec2 btn_size(iconButtonWidth(), iconButtonWidth());
const ImVec2 close_min(layout_.rect.Max.x - LAYOUT_MARGINS.z - btn_size.x, top_left.y);
const ImVec2 close_min(layout_.rect.Max.x - std::max(LAYOUT_MARGINS.z, CONTROL_OUTLINE_PADDING) - btn_size.x, top_left.y);
layout_.close_btn_rect = ImRect(close_min, close_min + btn_size);
const ImVec2 manage_min(close_min.x - btn_size.x - ImGui::GetStyle().ItemInnerSpacing.x, top_left.y);
layout_.manage_btn_rect = ImRect(manage_min, manage_min + btn_size);
+14 -1
View File
@@ -62,9 +62,21 @@ bool inputTextMultiline(const char *label, std::string *s, const ImVec2 &size, I
inputCallback, &ctx);
}
bool beginControlChild(const char *id, const ImVec2 &size, ImGuiWindowFlags flags) {
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(CONTROL_OUTLINE_PADDING, CONTROL_OUTLINE_PADDING));
const bool visible = ImGui::BeginChild(id, size, ImGuiChildFlags_AlwaysUseWindowPadding, flags);
ImGui::PopStyleVar();
return visible;
}
bool clearableInput(const char *label, std::string *s, const char *hint, ImGuiInputTextCallback validator) {
const float width = ImGui::CalcItemWidth();
const float clear_width = iconButtonWidth() + ImGui::GetStyle().ItemInnerSpacing.x;
const bool show_clear = !s->empty() && width >= clear_width + ImGui::GetFrameHeight();
ImGui::SetNextItemWidth(show_clear ? width - clear_width : width);
ImGui::BeginGroup();
bool changed = validatedInput(label, s, validator, hint);
if (!s->empty()) {
if (show_clear) {
ImGui::SameLine(0.0f, ImGui::GetStyle().ItemInnerSpacing.x);
ImGui::PushID(label);
if (iconButton("clear", icon::X_LG)) {
@@ -73,6 +85,7 @@ bool clearableInput(const char *label, std::string *s, const char *hint, ImGuiIn
}
ImGui::PopID();
}
ImGui::EndGroup();
return changed;
}
+5 -1
View File
@@ -31,7 +31,11 @@ inline bool inputText(const char *label, std::string *s, const char *hint = "",
bool inputTextMultiline(const char *label, std::string *s, const ImVec2 &size, ImGuiInputTextFlags flags = 0);
// an input with a trailing clear button once it holds text; true when the text changed
constexpr float CONTROL_OUTLINE_PADDING = 1.0f;
// Always pair with ImGui::EndChild(), even when false is returned.
bool beginControlChild(const char *id, const ImVec2 &size, ImGuiWindowFlags flags = 0);
// SetNextItemWidth includes the field and clear button. Returns true when text changes.
bool clearableInput(const char *label, std::string *s, const char *hint = "", ImGuiInputTextCallback validator = nullptr);
bool comboBox(const char *label, int *index, const std::vector<std::string> &items);
@@ -132,11 +132,13 @@ void LogsWidget::exportToCSV() {
void LogsWidget::draw() {
const ImGuiStyle &style = ImGui::GetStyle();
beginControlChild("toolbar", ImVec2(0, ImGui::GetFrameHeight() + CONTROL_OUTLINE_PADDING * 2),
ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
// toolbar: the export button is right aligned and never clipped, the value input shrinks first
const float export_w = iconButtonWidth();
if (!sigs_.empty()) {
const float clear_w = value_edit_.empty() ? 0.0f : iconButtonWidth();
const float fixed = DISPLAY_TYPE_WIDTH + SIGNALS_WIDTH + COMPARE_WIDTH + clear_w + style.ItemSpacing.x * 4 + export_w;
const float fixed = DISPLAY_TYPE_WIDTH + SIGNALS_WIDTH + COMPARE_WIDTH + style.ItemSpacing.x * 4 + export_w;
const float value_w = std::clamp(ImGui::GetContentRegionAvail().x - fixed, 30.0f, 120.0f);
ImGui::SetNextItemWidth(DISPLAY_TYPE_WIDTH);
@@ -169,6 +171,7 @@ void LogsWidget::draw() {
if (iconButton("export_csv", icon::FILETYPE_CSV)) exportToCSV();
ImGui::EndDisabled();
disabledItemTooltip("Export to CSV file...");
ImGui::EndChild();
ImGui::Separator();
drawTable();
@@ -434,12 +434,11 @@ void MessagesWidget::drawHeader() {
}
// the filter editors under the header
const float clear_width = iconButtonWidth();
ImGui::TableNextRow();
for (int i = 0; i < MessageList::COLUMN_COUNT; i++) {
if (!ImGui::TableSetColumnIndex(i)) continue;
ImGui::PushID(i);
ImGui::SetNextItemWidth(filters_[i].empty() ? -FLT_MIN : std::max(1.0f, ImGui::GetContentRegionAvail().x - clear_width));
ImGui::SetNextItemWidth(-FLT_MIN);
const std::string placeholder = std::string("Filter ") + COLUMN_TITLES[i];
if (clearableInput("##filter", &filters_[i], placeholder.c_str())) {
std::map<int, std::string> filters;
@@ -737,10 +737,8 @@ void SignalView::collapseAll() {
void SignalView::drawTree() {
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(ImGui::GetStyle().ItemSpacing.x, 0.0f));
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0.0f, 0.0f));
const float min_height = std::max(ImGui::GetContentRegionAvail().y, 300.0f);
const bool visible = ImGui::BeginChild("tree", ImVec2(0, min_height), ImGuiChildFlags_None);
ImGui::PopStyleVar();
const bool visible = beginControlChild("tree", ImVec2(0, min_height));
if (visible) {
DrawContext ctx{ImGui::GetWindowDrawList(), ImGui::GetCursorScreenPos().x, ImGui::GetContentRegionAvail().x, rowHeight()};
// the press that closes an open editor is consumed by the focus change, the index widgets never see it