Fixed a couple of subtle bounding box vertical positioning issues relating to the handling of text baseline alignment. The issue would generally manifest when laying out multiple items on a same line, with varying heights and text baseline offsets.
Some specific examples, e.g. a button with regular frame padding followed by another item with a multi-line label and no frame padding, such as: multi-line text, small button, tree node item, etc. The second item was correctly offset to match text baseline, and would interact/display correctly,but it wouldn't push the contents area boundary low enough.
diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt
index 64bbe6b..825dcd1 100644
--- a/docs/CHANGELOG.txt
+++ b/docs/CHANGELOG.txt
@@ -37,6 +37,13 @@
-
Other Changes:
+- Fixed a couple of subtle bounding box vertical positioning issues relating to the handling of text
+ baseline alignment. The issue would generally manifest when laying out multiple items on a same line,
+ with varying heights and text baseline offsets.
+ Some specific examples, e.g. a button with regular frame padding followed by another item with a
+ multi-line label and no frame padding, such as: multi-line text, small button, tree node item, etc.
+ The second item was correctly offset to match text baseline, and would interact/display correctly,
+ but it wouldn't push the contents area boundary low enough.
- InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787)
- TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow
incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897)
diff --git a/imgui.cpp b/imgui.cpp
index 7bf2bf5..a35b20b 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -2976,8 +2976,13 @@
if (window->SkipItems)
return;
+ // We increase the height in this function to accommodate for baseline offset.
+ // In theory we should be offsetting the starting position (window->DC.CursorPos), that will be the topic of a larger refactor,
+ // but since ItemSize() is not yet an API that moves the cursor (to handle e.g. wrapping) enlarging the height has the same effect.
+ const float offset_to_match_baseline_y = ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y);
+ const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y);
+
// Always align ourselves on pixel boundaries
- const float line_height = ImMax(window->DC.CurrLineSize.y, size.y);
//if (g.IO.KeyAlt) window->DrawList->AddRect(window->DC.CursorPos, window->DC.CursorPos + ImVec2(size.x, line_height), IM_COL32(255,0,0,200)); // [DEBUG]
window->DC.CursorPosPrevLine.x = window->DC.CursorPos.x + size.x;
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y;
@@ -7120,7 +7125,7 @@
}
window->DC.CurrLineTextBaseOffset = ImMax(window->DC.PrevLineTextBaseOffset, group_data.BackupCurrLineTextBaseOffset); // FIXME: Incorrect, we should grab the base offset from the *first line* of the group but it is hard to obtain now.
- ItemSize(group_bb.GetSize(), 0.0f);
+ ItemSize(group_bb.GetSize(), window->DC.CurrLineTextBaseOffset);
ItemAdd(group_bb, 0);
// If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group.
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 0da7353..c90a7e6 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -359,17 +359,18 @@
const char* text_begin = g.TempBuffer;
const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
- const float text_base_offset_y = ImMax(0.0f, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
- const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
- const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding
- ItemSize(bb);
+ const ImVec2 total_size = ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x * 2) : 0.0f), label_size.y); // Empty text doesn't add padding
+ ImVec2 pos = window->DC.CursorPos;
+ pos.y += window->DC.CurrLineTextBaseOffset;
+ ItemSize(total_size, 0.0f);
+ const ImRect bb(pos, pos + total_size);
if (!ItemAdd(bb, 0))
return;
// Render
ImU32 text_col = GetColorU32(ImGuiCol_Text);
- RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f), text_col);
- RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
+ RenderBullet(window->DrawList, bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, g.FontSize*0.5f), text_col);
+ RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
}
//-------------------------------------------------------------------------
@@ -5200,7 +5201,7 @@
ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style;
const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0;
- const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, 0.0f);
+ const ImVec2 padding = (display_frame || (flags & ImGuiTreeNodeFlags_FramePadding)) ? style.FramePadding : ImVec2(style.FramePadding.x, ImMin(window->DC.CurrLineTextBaseOffset, style.FramePadding.y));
if (!label_end)
label_end = FindRenderedTextEnd(label);
@@ -5225,7 +5226,7 @@
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it
const float text_width = g.FontSize + (label_size.x > 0.0f ? label_size.x + padding.x*2 : 0.0f); // Include collapser
ImVec2 text_pos(window->DC.CursorPos.x + text_offset_x, window->DC.CursorPos.y + text_offset_y);
- ItemSize(ImVec2(text_width, frame_height), text_offset_y);
+ ItemSize(ImVec2(text_width, frame_height), padding.y);
// For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
ImRect interact_bb = frame_bb;