Fixed a couple of subtle bounding box vertical positioning issues relating to text baseline alignment.

The issue would generally manifest when laying out multiple items on a same line, with varying heights and text baseline offsets. (#2833)
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.
Note: previously the second parameter to ItemSize() was 0.0f was default, now -1.0f to signify "no text baseline offset request". If you have code using ItemSize() with an hardcoded zero you may need to change it. (+1 squashed commits)
This commit is contained in:
omar 2019-10-06 23:17:36 +02:00
parent 75d540d336
commit ec0e953cca
4 changed files with 32 additions and 18 deletions

View File

@ -54,9 +54,16 @@ Breaking Changes:
The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate] The value is unused in master branch but will be used by the multi-viewport feature. (#2851) [@obfuscate]
Other Changes: Other Changes:
- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j]
- InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787) - InputText, Nav: Fixed Home/End key broken when activating Keyboard Navigation. (#787)
- InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578) - InputText: Filter out ASCII 127 (DEL) emitted by low-level OSX layer, as we are using the Key value. (#2578)
- Layout: 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.
- ColorPicker: Fixed SV triangle gradient to block (broken in 1.73). (#2864, #2711). [@lewa-j]
- TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow
incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897)
- DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data
@ -65,6 +72,7 @@ Other Changes:
- Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page. - Docs: Added permanent redirect from https://www.dearimgui.org/faq to FAQ page.
- Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups] - Demo: Added simple item reordering demo in Widgets -> Drag and Drop section. (#2823, #143) [@rokups]
- Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled. - Examples: DX12: Using IDXGIDebug1::ReportLiveObjects() when DX12_ENABLE_DEBUG_LAYER is enabled.
- Examples: Emscripten: Removed NO_FILESYSTEM from Makefile, seems to fail on some setup. (#2734) [@Funto]
- Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics] - Backends: OSX: Fix using Backspace key. (#2578, #2817, #2818) [@DiligentGraphics]
- Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v] - Backends: GLFW: Previously installed user callbacks are now restored on shutdown. (#2836) [@malte-v]

View File

@ -2777,8 +2777,13 @@ void ImGui::ItemSize(const ImVec2& size, float text_baseline_y)
if (window->SkipItems) if (window->SkipItems)
return; 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 = (text_baseline_y >= 0) ? ImMax(0.0f, window->DC.CurrLineTextBaseOffset - text_baseline_y) : 0.0f;
const float line_height = ImMax(window->DC.CurrLineSize.y, size.y + offset_to_match_baseline_y);
// Always align ourselves on pixel boundaries // 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] //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.x = window->DC.CursorPos.x + size.x;
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y; window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y;
@ -6913,7 +6918,7 @@ void ImGui::EndGroup()
} }
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. 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());
ItemAdd(group_bb, 0); 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. // 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.

View File

@ -1543,8 +1543,8 @@ namespace ImGui
IMGUI_API void PushOverrideID(ImGuiID id); IMGUI_API void PushOverrideID(ImGuiID id);
// Basic Helpers for widget code // Basic Helpers for widget code
IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = 0.0f); IMGUI_API void ItemSize(const ImVec2& size, float text_baseline_y = -1.0f);
IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = 0.0f); IMGUI_API void ItemSize(const ImRect& bb, float text_baseline_y = -1.0f);
IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL); IMGUI_API bool ItemAdd(const ImRect& bb, ImGuiID id, const ImRect* nav_bb = NULL);
IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id); IMGUI_API bool ItemHoverable(const ImRect& bb, ImGuiID id);
IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged); IMGUI_API bool IsClippedEx(const ImRect& bb, ImGuiID id, bool clip_even_when_logged);

View File

@ -213,7 +213,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
text_size.y = (pos - text_pos).y; text_size.y = (pos - text_pos).y;
ImRect bb(text_pos, text_pos + text_size); ImRect bb(text_pos, text_pos + text_size);
ItemSize(text_size); ItemSize(text_size, 0.0f);
ItemAdd(bb, 0); ItemAdd(bb, 0);
} }
else else
@ -222,7 +222,7 @@ void ImGui::TextEx(const char* text, const char* text_end, ImGuiTextFlags flags)
const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width); const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
ImRect bb(text_pos, text_pos + text_size); ImRect bb(text_pos, text_pos + text_size);
ItemSize(text_size); ItemSize(text_size, 0.0f);
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
return; return;
@ -359,17 +359,18 @@ void ImGui::BulletTextV(const char* fmt, va_list args)
const char* text_begin = g.TempBuffer; const char* text_begin = g.TempBuffer;
const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args); 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 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 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
const float line_height = ImMax(ImMin(window->DC.CurrLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize); ImVec2 pos = window->DC.CursorPos;
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 pos.y += window->DC.CurrLineTextBaseOffset;
ItemSize(bb); ItemSize(total_size, 0.0f);
const ImRect bb(pos, pos + total_size);
if (!ItemAdd(bb, 0)) if (!ItemAdd(bb, 0))
return; return;
// Render // Render
ImU32 text_col = GetColorU32(ImGuiCol_Text); 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); 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, text_base_offset_y), text_begin, text_end, false); RenderText(bb.Min + ImVec2(g.FontSize + style.FramePadding.x * 2, 0.0f), text_begin, text_end, false);
} }
//------------------------------------------------------------------------- //-------------------------------------------------------------------------
@ -691,7 +692,7 @@ bool ImGui::ArrowButtonEx(const char* str_id, ImGuiDir dir, ImVec2 size, ImGuiBu
const ImGuiID id = window->GetID(str_id); const ImGuiID id = window->GetID(str_id);
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size); const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + size);
const float default_size = GetFrameHeight(); const float default_size = GetFrameHeight();
ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : 0.0f); ItemSize(size, (size.y >= default_size) ? g.Style.FramePadding.y : -1.0f);
if (!ItemAdd(bb, id)) if (!ItemAdd(bb, id))
return false; return false;
@ -5211,7 +5212,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
ImGuiContext& g = *GImGui; ImGuiContext& g = *GImGui;
const ImGuiStyle& style = g.Style; const ImGuiStyle& style = g.Style;
const bool display_frame = (flags & ImGuiTreeNodeFlags_Framed) != 0; 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) if (!label_end)
label_end = FindRenderedTextEnd(label); label_end = FindRenderedTextEnd(label);
@ -5236,7 +5237,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l
const float text_offset_y = ImMax(padding.y, window->DC.CurrLineTextBaseOffset); // Latch before ItemSize changes it 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 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); 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 // For regular tree nodes, we arbitrary allow to click past 2 worth of ItemSpacing
ImRect interact_bb = frame_bb; ImRect interact_bb = frame_bb;
@ -5507,7 +5508,7 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl
ImVec2 pos = window->DC.CursorPos; ImVec2 pos = window->DC.CursorPos;
pos.y += window->DC.CurrLineTextBaseOffset; pos.y += window->DC.CurrLineTextBaseOffset;
ImRect bb_inner(pos, pos + size); ImRect bb_inner(pos, pos + size);
ItemSize(size); ItemSize(size, 0.0f);
// Fill horizontal space. // Fill horizontal space.
ImVec2 window_padding = window->WindowPadding; ImVec2 window_padding = window->WindowPadding;
@ -6438,7 +6439,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
tab_bar->FramePadding = g.Style.FramePadding; tab_bar->FramePadding = g.Style.FramePadding;
// Layout // Layout
ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight())); ItemSize(ImVec2(tab_bar->OffsetMaxIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
window->DC.CursorPos.x = tab_bar->BarRect.Min.x; window->DC.CursorPos.x = tab_bar->BarRect.Min.x;
// Draw separator // Draw separator