Merge branch 'master' into docking

# Conflicts:
#	imgui.cpp
This commit is contained in:
ocornut 2026-10-30 19:56:15 +01:00
commit d682dc41f5
8 changed files with 110 additions and 69 deletions

View File

@ -66,14 +66,33 @@ Autumn cleanup of stuff marked obsolete more than two years ago:
Other Changes:
- Style: `StyleColorsDark()`: tweaked WindowBg to be darker than in 1.93.0.
- Style: added `style.SymbolArrowSizeFactor`, `style.SymbolArrowThicknessFactor` to tweak
the shape and look of arrows. Made default arrow stroked. (#5233, #2431, #2235, #6730, #8243)
- Style:
- `StyleColorsDark()`: tweaked WindowBg to be darker than in 1.93.0.
- Added `style.SymbolArrowSizeFactor`, `style.SymbolArrowThicknessFactor` to tweak the
shape and look of arrows. Made default arrow stroked. (#5233, #2431, #2235, #6730, #8243)
Legacy arrow: size: (0.60f,0.70f), thickness: 0.0f
New arrow: size: (0.72f,0.40f), thickness: 0.30f
- TreeNode:
- TreeNodeGetOpen(): added flags parameter to allow passing `ImGuiTreeNodeFlags_DefaultOpen`
or `ImGuiTreeNodeFlags_Leaf`. (#9569, #9592, #3823, #9251) [@adalisk-emikhaylov, @Yaki-Blake]
- Popups:
- Modals: fixed an assert displaying a modal in an environment where
`io.DisplayFramebufferScale` is not an integer (regression in 1.93.0). (#9598)
- Tables:
- Fixed various border overshooting issues, some mostly visible with transparent
borders and under specific conditions: (#4678)
- On non-scrolling tables, inner horizontal borders slightly overlapped
outer vertical ones with certain settings.
- On non-scrolling tables, clamping lower border coordinates to stay within
visible range (no visible change, but it makes ImDrawCmd AABB more sensible).
- Fixed vertical inner borders slightly overlapping bottom outer border.
- Fixed various issues using `ImGuiTableFlags_NoHostExtendX`/`_NoHostExtendY`:
- Fixed selectable highlight straying off the X2/Y2 clipping limit.
- Fixed parent window work rectangle affecting the Y2 clipping limit.
- Fixed the Y2 clipping limit overlapping bottom outer border.
- Multi-Select:
- Fixed `ImGuiSelectionBasicStorage::GetNextSelectedItem()` reading one past the
end of storage when trailing items are unselected (#9604) [@MilosLord]
- ImVec2: added a check for cases where a custom `IM_VEC2_CLASS_EXTRA` macro
adds an extra `operator=` to ImVec2. This isn't supported but should not
be needed as you should have a constructor to convert from your type to ImVec2.

View File

@ -6334,7 +6334,8 @@ static void ImGui::RenderDimmedBackgroundBehindWindow(ImGuiWindow* window, ImU32
draw_list->PushClipRect(viewport_rect.Min - ImVec2(1, 1), viewport_rect.Max + ImVec2(1, 1), false); // FIXME: Need to strictly ensure ImDrawCmd are not merged (ElemCount==6 checks below will verify that)
ImDrawCmd cmd = draw_list->CmdBuffer.back();
IM_ASSERT(cmd.ElemCount == 0);
draw_list->AddRectFilled(viewport_rect.Min, viewport_rect.Max, col);
draw_list->PrimReserve(6, 4);
draw_list->PrimRect(viewport_rect.Min, viewport_rect.Max, col);
cmd = draw_list->CmdBuffer.back();
draw_list->CmdBuffer.pop_back();
draw_list->CmdBuffer.push_front(cmd);

View File

@ -30,7 +30,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.93.1 WIP"
#define IMGUI_VERSION_NUM 19301
#define IMGUI_VERSION_NUM 19302
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.

View File

@ -6514,7 +6514,9 @@ static void DemoWindowTables()
{
static char text_bufs[3 * 5][16]; // Mini text storage for 3x5 cells
static bool init = true;
if (!show_widget_frame_bg)
if (show_widget_frame_bg)
ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
else
ImGui::PushStyleColor(ImGuiCol_FrameBg, 0);
for (int cell = 0; cell < 3 * 5; cell++)
{
@ -6526,7 +6528,9 @@ static void DemoWindowTables()
ImGui::InputText("##cell", text_bufs[cell], IM_COUNTOF(text_bufs[cell]));
ImGui::PopID();
}
if (!show_widget_frame_bg)
if (show_widget_frame_bg)
ImGui::PopStyleVar();
else
ImGui::PopStyleColor();
init = false;
ImGui::EndTable();
@ -7040,6 +7044,7 @@ static void DemoWindowTables()
if (ImGui::TreeNode("Outer size"))
{
IMGUI_DEMO_MARKER("Tables/Outer size");
// Showcasing use of ImGuiTableFlags_NoHostExtendX and ImGuiTableFlags_NoHostExtendY
// Important to that note how the two flags have slightly different behaviors!
ImGui::Text("Using NoHostExtendX and NoHostExtendY:");
@ -7135,7 +7140,7 @@ static void DemoWindowTables()
// We use a transparent color so we can see the one behind in case our target is RowBg1 and RowBg0 was already targeted by the ImGuiTableFlags_RowBg flag.
if (row_bg_type != 0)
{
ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.65f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.65f)); // Flat or Gradient?
ImU32 row_bg_color = ImGui::GetColorU32(row_bg_type == 1 ? ImVec4(0.7f, 0.3f, 0.3f, 0.40f) : ImVec4(0.2f + row * 0.1f, 0.2f, 0.2f, 0.40f)); // Flat or Gradient?
ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0 + row_bg_target, row_bg_color);
}

View File

@ -7589,9 +7589,9 @@ void ImGui::RenderArrowEx(ImDrawList* draw_list, ImVec2 pos, ImU32 col, float co
// Pixel align when at a right angle
if (is_fill && (cos_a * sin_a >= -FLT_EPSILON) && (cos_a * sin_a <= FLT_EPSILON))
{
p[0] = ImRoundSigned64(p[0]);
p[1] = ImRoundSigned64(p[1]);
p[2] = ImRoundSigned64(p[2]);
p[0] = ImRoundSigned(p[0]);
p[1] = ImRoundSigned(p[1]);
p[2] = ImRoundSigned(p[2]);
}
if (is_fill)

View File

@ -295,8 +295,8 @@ extern IMGUI_API ImGuiContext* GImGui; // Current implicit context pointer
#define IM_MEMALIGN(_OFF,_ALIGN) (((_OFF) + ((_ALIGN) - 1)) & ~((_ALIGN) - 1)) // Memory align e.g. IM_ALIGN(0,4)=0, IM_ALIGN(1,4)=4, IM_ALIGN(4,4)=4, IM_ALIGN(5,4)=8
#define IM_F32_TO_INT8_UNBOUND(_VAL) ((int)((_VAL) * 255.0f + ((_VAL)>=0 ? 0.5f : -0.5f))) // Unsaturated, for display purpose
#define IM_F32_TO_INT8_SAT(_VAL) ((int)(ImSaturate(_VAL) * 255.0f + 0.5f)) // Saturated, always output 0..255
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // Positive values only! ImTrunc() is not inlined in MSVC debug builds
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // Positive values only!
#define IM_TRUNC(_VAL) ((float)(int)(_VAL)) // Positive values only! == ImTrunc() which is not inlined in MSVC debug builds
#define IM_ROUND(_VAL) ((float)(int)((_VAL) + 0.5f)) // Positive values only! == ImRoundPositive() which is not inlined in MSVC debug builds.
//#define IM_FLOOR IM_TRUNC // [OBSOLETE] Renamed in 1.90.0 (Sept 2023)
// Hint for branch prediction
@ -553,14 +553,16 @@ inline float ImSaturate(float f) { return
inline float ImLengthSqr(const ImVec2& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y); }
inline float ImLengthSqr(const ImVec4& lhs) { return (lhs.x * lhs.x) + (lhs.y * lhs.y) + (lhs.z * lhs.z) + (lhs.w * lhs.w); }
inline float ImInvLength(const ImVec2& lhs, float fail_value) { float d = (lhs.x * lhs.x) + (lhs.y * lhs.y); if (d > 0.0f) return ImRsqrt(d); return fail_value; }
inline float ImTrunc(float f) { return (float)(int)(f); }
inline float ImTrunc(float f) { return (float)(int)(f); } // == IM_TRUNC()
inline ImVec2 ImTrunc(const ImVec2& v) { return ImVec2((float)(int)(v.x), (float)(int)(v.y)); }
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
inline float ImFloor(float f) { return (float)((f >= 0 || (float)(int)f == f) ? (int)f : (int)f - 1); } // Decent replacement for floorf()
inline ImVec2 ImFloor(const ImVec2& v) { return ImVec2(ImFloor(v.x), ImFloor(v.y)); }
inline float ImTrunc64(float f) { return (float)(ImS64)(f); }
inline float ImRoundPositive(float f) { return (float)(int)(f + 0.5f); } // == IM_ROUND(). Positive values only.
inline float ImRoundPositive64(float f) { return (float)(ImS64)(f + 0.5f); } // Positive values only.
inline float ImRoundSigned(float f) { return (float)(int)(f >= 0.0f ? f + 0.5f : f - 0.5f); }
inline ImVec2 ImRoundSigned(const ImVec2& v) { return ImVec2((float)(int)(v.x >= 0.0f ? v.x + 0.5f : v.x - 0.5f), (float)(int)(v.y >= 0.0f ? v.y + 0.5f : v.y - 0.5f)); }
inline float ImRoundSigned64(float f) { return (float)(ImS64)(f >= 0.0f ? f + 0.5f : f - 0.5f); }
inline ImVec2 ImRoundSigned64(const ImVec2& v) { return ImVec2((float)(ImS64)(v.x >= 0.0f ? v.x + 0.5f : v.x - 0.5f), (float)(ImS64)(v.y >= 0.0f ? v.y + 0.5f : v.y - 0.5f)); }
inline float ImCeilFast(float f) { int i = (int)f; return (float)(i + (f > (float)i)); } // Consider using the bit-hack version (search for "0x1p120f").
inline int ImModPositive(int a, int b) { return (a + b) % b; }
inline float ImDot(const ImVec2& a, const ImVec2& b) { return a.x * b.x + a.y * b.y; }
@ -664,6 +666,7 @@ struct IMGUI_API ImRect
void TranslateY(float dy) { Min.y += dy; Max.y += dy; }
void ClipWith(const ImRect& r) { Min = ImMax(Min, r.Min); Max = ImMin(Max, r.Max); } // Simple version, may lead to an inverted rectangle, which is fine for Contains/Overlaps test but not for display.
void ClipWithFull(const ImRect& r) { Min = ImClamp(Min, r.Min, r.Max); Max = ImClamp(Max, r.Min, r.Max); } // Full version, ensure both points are fully clipped.
void ShrinkClamp(const ImVec2& inset_min, const ImVec2& inset_max) { Min.x = ImMin(Min.x + inset_min.x, Max.x); Min.y = ImMin(Min.y + inset_min.y, Max.y); Max.x = ImMax(Max.x - inset_max.x, Min.x); Max.y = ImMax(Max.y - inset_max.y, Min.y); }
bool IsInverted() const { return Min.x > Max.x || Min.y > Max.y; }
ImVec4 ToVec4() const { return ImVec4(Min.x, Min.y, Max.x, Max.y); }
const ImVec4& AsVec4() const { return *(const ImVec4*)&Min.x; }
@ -3390,6 +3393,7 @@ struct IMGUI_API ImGuiTable
ImU32 BorderColorLight;
float BorderX1;
float BorderX2;
float BorderSize;
float HostIndentX;
float MinColumnWidth;
float OuterPaddingX;

View File

@ -478,29 +478,27 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
temp_data->HostBackupItemWidthStackSize = outer_window->DC.ItemWidthStack.Size;
inner_window->DC.PrevLineSize = inner_window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
// Border size
// FIXME-WIP: Changing this is not currently simple due to ClipRect requirements. Easier to manage with new 1.93 primitives though.
const float border_size = table->BorderSize = TABLE_BORDER_SIZE;
// Make borders not overlap our contents by offsetting HostClipRect (#6765, #7428, #3752)
// (we normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the
// limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap
// problem only affect scrolling tables in this case we can get away with doing it without extra cost).
if (inner_window != outer_window)
// - We normally shouldn't alter HostClipRect as we rely on TableMergeDrawChannels() expanding non-clipped column toward the
// limits of that rectangle, in order for ImDrawListSplitter::Merge() to merge the draw commands. However since the overlap
// problem only affect scrolling tables in this case we can get away with doing it without extra cost).
// - (FIXME: Because inner_window's Scrollbar doesn't know about border size, since it's not encoded in window->WindowBorderSize,
// it already overlaps it and doesn't need an extra offset. Ideally we should be able to pass custom border size with
// different x/y values to BeginChild().)
// - For non-scrolling window, this is applied to table->InnerClipRect below.
ImRect border_size_outer =
{
// FIXME: Because inner_window's Scrollbar doesn't know about border size, since it's not encoded in window->WindowBorderSize,
// it already overlaps it and doesn't need an extra offset. Ideally we should be able to pass custom border size with
// different x/y values to BeginChild().
const float border_size = TABLE_BORDER_SIZE;
if (flags & ImGuiTableFlags_BordersOuterV)
{
table->HostClipRect.Min.x = ImMin(table->HostClipRect.Min.x + border_size, table->HostClipRect.Max.x);
if (inner_window->DecoOuterSizeX2 == 0.0f)
table->HostClipRect.Max.x = ImMax(table->HostClipRect.Max.x - border_size, table->HostClipRect.Min.x);
}
if (flags & ImGuiTableFlags_BordersOuterH)
{
table->HostClipRect.Min.y = ImMin(table->HostClipRect.Min.y + border_size, table->HostClipRect.Max.y);
if (inner_window->DecoOuterSizeY2 == 0.0f)
table->HostClipRect.Max.y = ImMax(table->HostClipRect.Max.y - border_size, table->HostClipRect.Min.y);
}
}
(flags & ImGuiTableFlags_BordersOuterV) ? border_size : 0.0f,
(flags & ImGuiTableFlags_BordersOuterH) ? border_size : 0.0f,
((flags & ImGuiTableFlags_BordersOuterV) && ((inner_window == outer_window) || inner_window->DecoOuterSizeX2 == 0.0f)) ? border_size : 0.0f,
((flags & ImGuiTableFlags_BordersOuterH) && ((inner_window == outer_window) || inner_window->DecoOuterSizeY2 == 0.0f)) ? border_size : 0.0f,
};
if (inner_window != outer_window)
table->HostClipRect.ShrinkClamp(border_size_outer.Min, border_size_outer.Max);
// Padding and Spacing
// - None ........Content..... Pad .....Content........
@ -509,14 +507,14 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
// - PadOuter+PadInner | Pad ..Content.. Pad | Pad ..Content.. Pad |
const bool pad_outer_x = (flags & ImGuiTableFlags_NoPadOuterX) ? false : (flags & ImGuiTableFlags_PadOuterX) ? true : (flags & ImGuiTableFlags_BordersOuterV) != 0;
const bool pad_inner_x = (flags & ImGuiTableFlags_NoPadInnerX) ? false : true;
const float inner_spacing_for_border = (flags & ImGuiTableFlags_BordersInnerV) ? TABLE_BORDER_SIZE : 0.0f;
const float inner_spacing_for_border = (flags & ImGuiTableFlags_BordersInnerV) ? border_size : 0.0f;
const float inner_spacing_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) == 0) ? g.Style.CellPadding.x : 0.0f;
const float inner_padding_explicit = (pad_inner_x && (flags & ImGuiTableFlags_BordersInnerV) != 0) ? g.Style.CellPadding.x : 0.0f;
table->CellSpacingX1 = inner_spacing_explicit + inner_spacing_for_border;
table->CellSpacingX2 = inner_spacing_explicit;
table->CellPaddingX = inner_padding_explicit;
const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
const float outer_padding_for_border = (flags & ImGuiTableFlags_BordersOuterV) ? border_size : 0.0f;
const float outer_padding_explicit = pad_outer_x ? g.Style.CellPadding.x : 0.0f;
table->OuterPaddingX = (outer_padding_for_border + outer_padding_explicit) - table->CellPaddingX;
@ -525,9 +523,12 @@ bool ImGui::BeginTableEx(const char* name, ImGuiID id, int columns_count, ImG
table->RowBgColorCounter = 0;
table->LastRowFlags = ImGuiTableRowFlags_None;
table->InnerClipRect = (inner_window == outer_window) ? table->WorkRect : inner_window->ClipRect;
if (inner_window == outer_window)
table->InnerClipRect.ShrinkClamp(border_size_outer.Min, border_size_outer.Max);
table->InnerClipRect.ClipWith(table->WorkRect); // We need this to honor inner_width
table->InnerClipRect.ClipWithFull(table->HostClipRect);
table->InnerClipRect.Max.y = (flags & ImGuiTableFlags_NoHostExtendY) ? ImMin(table->InnerClipRect.Max.y, inner_window->WorkRect.Max.y) : table->HostClipRect.Max.y;
if ((flags & ImGuiTableFlags_NoHostExtendY) == 0)
table->InnerClipRect.Max.y = table->HostClipRect.Max.y;
table->RowPosY1 = table->RowPosY2 = table->WorkRect.Min.y; // This is needed somehow
table->RowTextBaseline = 0.0f; // This will be cleared again by TableBeginRow()
@ -1277,7 +1278,7 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
}
if (order_n < table->FreezeColumnsCount)
host_clip_rect.Min.x = ImClamp(column->MaxX + TABLE_BORDER_SIZE, host_clip_rect.Min.x, host_clip_rect.Max.x);
host_clip_rect.Min.x = ImClamp(column->MaxX + table->BorderSize, host_clip_rect.Min.x, host_clip_rect.Max.x);
offset_x += column->WidthGiven + table->CellSpacingX1 + table->CellSpacingX2 + table->CellPaddingX * 2.0f;
}
@ -1309,8 +1310,9 @@ void ImGui::TableUpdateLayout(ImGuiTable* table)
table->Flags &= ~ImGuiTableFlags_NoHostExtendX;
if (table->Flags & ImGuiTableFlags_NoHostExtendX)
{
table->OuterRect.Max.x = table->WorkRect.Max.x = unused_x1;
table->InnerClipRect.Max.x = ImMin(table->InnerClipRect.Max.x, unused_x1);
const float border_size_outer_w = (table->Flags & ImGuiTableFlags_BordersOuterV) ? table->BorderSize : 0.0f;
table->OuterRect.Max.x = table->WorkRect.Max.x = ImMin(table->OuterRect.Max.x, unused_x1 + border_size_outer_w);
table->InnerClipRect.Max.x = ImClamp(table->OuterRect.Max.x - border_size_outer_w, table->InnerClipRect.Min.x, table->InnerClipRect.Max.x);
}
table->InnerWindow->ParentWorkRect = table->WorkRect;
table->BorderX1 = table->InnerClipRect.Min.x;
@ -1503,10 +1505,10 @@ void ImGui::EndTable()
// but since the later is likely to be impossible to do we'd rather update both axes together.
if (table->Flags & ImGuiTableFlags_ScrollX)
{
const float outer_padding_for_border = (table->Flags & ImGuiTableFlags_BordersOuterV) ? TABLE_BORDER_SIZE : 0.0f;
const float border_size_outer_w = (table->Flags & ImGuiTableFlags_BordersOuterV) ? table->BorderSize : 0.0f;
float max_pos_x = inner_window->DC.CursorMaxPos.x;
if (table->RightMostEnabledColumn != -1)
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - outer_padding_for_border);
max_pos_x = ImMax(max_pos_x, table->Columns[table->RightMostEnabledColumn].WorkMaxX + table->CellPaddingX + table->OuterPaddingX - border_size_outer_w);
if (table->ResizedColumn != -1)
max_pos_x = ImMax(max_pos_x, table->ResizeLockMinContentsX2);
inner_window->DC.CursorMaxPos.x = max_pos_x + table->TempData->AngledHeadersExtraWidth;
@ -2168,7 +2170,6 @@ void ImGui::TableEndRow(ImGuiTable* table)
// Decide of top border color
ImU32 top_border_col = 0;
const float border_size = TABLE_BORDER_SIZE;
if (table->CurrentRow > 0 && (table->Flags & ImGuiTableFlags_BordersInnerH))
top_border_col = (table->LastRowFlags & ImGuiTableRowFlags_Headers) ? table->BorderColorStrong : table->BorderColorLight;
@ -2215,11 +2216,11 @@ void ImGui::TableEndRow(ImGuiTable* table)
// Draw top border
if (top_border_col && bg_y1 >= table->BgClipRect.Min.y && bg_y1 < table->BgClipRect.Max.y)
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y1, top_border_col, border_size);
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y1, top_border_col, table->BorderSize, ImDrawFlags_StrokeCenterBiased);
// Draw bottom border at the row unfreezing mark (always strong)
if (draw_strong_bottom_border && bg_y2 >= table->BgClipRect.Min.y && bg_y2 < table->BgClipRect.Max.y)
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y2, table->BorderColorStrong, border_size);
window->DrawList->AddLineH(table->BorderX1, table->BorderX2, bg_y2, table->BorderColorStrong, table->BorderSize, ImDrawFlags_StrokeCenterBiased);
}
// End frozen rows (when we are past the last frozen row line, teleport cursor and alter clipping rectangle)
@ -2734,6 +2735,10 @@ void ImGui::TableSetupDrawChannels(ImGuiTable* table)
table->Bg0ClipRectForDrawCmd = table->OuterWindow->ClipRect;
table->Bg2ClipRectForDrawCmd = table->HostClipRect;
IM_ASSERT(table->BgClipRect.Min.y <= table->BgClipRect.Max.y);
if (table->Flags & ImGuiTableFlags_NoHostExtendX)
table->Bg2ClipRectForDrawCmd.Max.x = ImMin(table->Bg2ClipRectForDrawCmd.Max.x, table->BgClipRect.Max.x); // Don't apply to Bg0: shapes in Bg0 are already CPU clipped and it makes merging fails.
if (table->Flags & ImGuiTableFlags_NoHostExtendY)
table->Bg2ClipRectForDrawCmd.Max.y = ImMin(table->Bg2ClipRectForDrawCmd.Max.y, table->BgClipRect.Max.y); // "
}
// This function reorder draw channels based on matching clip rectangle, to facilitate merging them. Called by EndTable().
@ -2891,7 +2896,7 @@ void ImGui::TableMergeDrawChannels(ImGuiTable* table)
merge_clip_rect.Min.x = ImMin(merge_clip_rect.Min.x, host_rect.Min.x);
if ((merge_group_n & 2) == 0 || !has_freeze_v)
merge_clip_rect.Min.y = ImMin(merge_clip_rect.Min.y, host_rect.Min.y);
if ((merge_group_n & 1) != 0)
if ((merge_group_n & 1) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendX) == 0)
merge_clip_rect.Max.x = ImMax(merge_clip_rect.Max.x, host_rect.Max.x);
if ((merge_group_n & 2) != 0 && (table->Flags & ImGuiTableFlags_NoHostExtendY) == 0)
merge_clip_rect.Max.y = ImMax(merge_clip_rect.Max.y, host_rect.Max.y);
@ -2951,19 +2956,25 @@ static ImU32 TableGetColumnBorderCol(ImGuiTable* table, int order_n, int column_
void ImGui::TableDrawBorders(ImGuiTable* table)
{
ImGuiWindow* inner_window = table->InnerWindow;
if (!table->OuterWindow->ClipRect.Overlaps(table->OuterRect))
if (!table->OuterWindow->ClipRect.Overlaps(table->OuterRect)) // Note how OuterWindow->ClipRect == table->Bg0ClipRectForDrawCmd
return;
ImDrawList* inner_drawlist = inner_window->DrawList;
table->DrawSplitter->SetCurrentChannel(inner_drawlist, TABLE_DRAW_CHANNEL_BG0);
inner_drawlist->PushClipRect(table->Bg0ClipRectForDrawCmd.Min, table->Bg0ClipRectForDrawCmd.Max, false);
inner_drawlist->PushClipRect(table->OuterWindow->ClipRect.Min, table->OuterWindow->ClipRect.Max, false);
// For e.g. non scrolling table we limit vertex coordinates in order to keep ImDrawCmd AABB roughly within visible range.
const float border_size_outer_w = (table->Flags & ImGuiTableFlags_BordersOuterV) ? table->BorderSize : 0.0f;
const float border_size_outer_h = (table->Flags & ImGuiTableFlags_BordersOuterH) ? table->BorderSize : 0.0f;
const float border_size_inner = table->BorderSize;
const float draw_y2_limit = table->OuterWindow->ClipRect.Max.y + (2.0f * ImMax(border_size_outer_h, inner_drawlist->_FringeScale));
// Draw inner border and resizing feedback
ImGuiTableInstanceData* table_instance = TableGetInstanceData(table, table->InstanceCurrent);
const float border_size = TABLE_BORDER_SIZE;
const float draw_y1 = ImMax(table->InnerRect.Min.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight) + ((table->Flags & ImGuiTableFlags_BordersOuterH) ? border_size : 0.0f);
const float draw_y2_body = table->InnerRect.Max.y;
const float draw_y2_head = table->IsUsingHeaders ? ImMin(table->InnerRect.Max.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastTopHeadersRowHeight) : draw_y1;
const float draw_y1 = ImMax(table->InnerRect.Min.y, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table->AngledHeadersHeight) + ((table->Flags & ImGuiTableFlags_BordersOuterH) ? border_size_outer_h : 0.0f);
const float draw_y2_body = ImMin(table->InnerRect.Max.y - border_size_outer_h, draw_y2_limit);
const float draw_y2_head = table->IsUsingHeaders ? ImMin(draw_y2_body, (table->FreezeRowsCount >= 1 ? table->InnerRect.Min.y : table->WorkRect.Min.y) + table_instance->LastTopHeadersRowHeight) : draw_y1;
if (table->Flags & ImGuiTableFlags_BordersInnerV)
{
for (int order_n = 0; order_n < table->ColumnsCount; order_n++)
@ -2996,7 +3007,7 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0)
draw_y2 = draw_y2_body;
if (draw_y2 > draw_y1)
inner_drawlist->AddLineV(column->MaxX, draw_y1, draw_y2, TableGetColumnBorderCol(table, order_n, column_n), border_size);
inner_drawlist->AddLineV(column->MaxX, draw_y1, draw_y2, TableGetColumnBorderCol(table, order_n, column_n), border_size_inner);
}
}
@ -3009,30 +3020,30 @@ void ImGui::TableDrawBorders(ImGuiTable* table)
// parent. In inner_window, it won't reach out over scrollbars. Another weird solution would be to display part
// of it in inner window, and the part that's over scrollbars in the outer window..)
// Either solution currently won't allow us to use a larger border size: the border would clipped.
const ImRect outer_border = table->OuterRect;
ImRect outer_border = table->OuterRect;
outer_border.Max.y = ImMin(outer_border.Max.y, draw_y2_limit); // Clamp but keep bottom border non-visible.
const ImU32 outer_col = table->BorderColorStrong;
if ((table->Flags & ImGuiTableFlags_BordersOuter) == ImGuiTableFlags_BordersOuter)
{
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, border_size);
inner_drawlist->AddRect(outer_border.Min, outer_border.Max, outer_col, 0.0f, border_size_outer_w);
}
else if (table->Flags & ImGuiTableFlags_BordersOuterV)
{
inner_drawlist->AddLineV(outer_border.Min.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
inner_drawlist->AddLineV(outer_border.Max.x - border_size, outer_border.Min.y, outer_border.Max.y, outer_col, border_size);
inner_drawlist->AddLineV(outer_border.Min.x, outer_border.Min.y, outer_border.Max.y, outer_col, border_size_outer_w);
inner_drawlist->AddLineV(outer_border.Max.x - border_size_outer_w, outer_border.Min.y, outer_border.Max.y, outer_col, border_size_outer_w);
}
else if (table->Flags & ImGuiTableFlags_BordersOuterH)
{
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Min.y, outer_col, border_size);
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Max.y - border_size, outer_col, border_size);
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Min.y, outer_col, border_size_outer_h);
inner_drawlist->AddLineH(outer_border.Min.x, outer_border.Max.x, outer_border.Max.y - border_size_outer_h, outer_col, border_size_outer_h);
}
}
if ((table->Flags & ImGuiTableFlags_BordersInnerH) && table->RowPosY2 < table->OuterRect.Max.y)
{
// Draw bottom-most row border between it is above outer border.
const float h_inset = (table->Flags & ImGuiTableFlags_BordersOuterV) ? border_size : 0.0f;
// Draw bottom-most row border between it and above outer border.
const float border_y = table->RowPosY2;
if (border_y >= table->BgClipRect.Min.y && border_y < table->BgClipRect.Max.y)
inner_drawlist->AddLineH(table->BorderX1 + h_inset, table->BorderX2 - h_inset, border_y, table->BorderColorLight, border_size);
inner_drawlist->AddLineH(table->BorderX1, table->BorderX2, border_y, table->BorderColorLight, border_size_inner);
}
inner_drawlist->PopClipRect();
@ -3625,8 +3636,9 @@ void ImGui::TableAngledHeadersRowEx(ImGuiID row_id, float angle, float max_label
if (pass == 1)
{
// Draw border
const float border_size = TABLE_BORDER_SIZE;
draw_list->AddLine(bg_shape[0] + ImVec2(border_size * 0.5f, 0.0f), bg_shape[3] + ImVec2(border_size * 0.5f, 0.0f), TableGetColumnBorderCol(table, order_n, column_n), border_size);
draw_list->AddLine(
bg_shape[0] + ImVec2(table->BorderSize * 0.5f, 0.0f),
bg_shape[3] + ImVec2(table->BorderSize * 0.5f, 0.0f), TableGetColumnBorderCol(table, order_n, column_n), table->BorderSize);
}
}
PopClipRect();

View File

@ -4478,7 +4478,7 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
if (new_text_len + BufTextLen + 1 > obj->TextA.Size && is_resizable && !is_readonly)
{
IM_ASSERT(Buf == obj->TextA.Data);
int new_buf_size = BufTextLen + ImClamp(new_text_len * 4, 32, ImMax(256, new_text_len)) + 1;
int new_buf_size = BufTextLen + ImClamp(new_text_len, 32, ImMax(256, new_text_len)) + 1;
obj->TextA.resize(new_buf_size + 1);
obj->TextSrc = obj->TextA.Data;
Buf = obj->TextA.Data;
@ -8810,7 +8810,7 @@ bool ImGuiSelectionBasicStorage::GetNextSelectedItem(void** opaque_it, ImGuiID*
it = _Storage.Data.Data;
IM_ASSERT(it >= _Storage.Data.Data && it <= it_end);
if (it != it_end)
while (it->val_i == 0 && it < it_end)
while (it < it_end && it->val_i == 0)
it++;
const bool has_more = (it != it_end);
*opaque_it = has_more ? (void**)(it + 1) : (void**)(it);