From 8074b4914834e2892000fc1f359fdb8cf84e88ac Mon Sep 17 00:00:00 2001 From: omar Date: Wed, 5 Aug 2020 19:23:00 +0200 Subject: [PATCH] Selectable: Fixed highlight/hit extent when used with horizontal scrolling (in or outside columns). (#3187, #3386) # Conflicts: # imgui_widgets.cpp --- docs/CHANGELOG.txt | 2 ++ imgui.cpp | 1 + imgui_internal.h | 5 +++-- imgui_widgets.cpp | 10 ++++++---- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 7cc16314e219..c9d14d564396 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -49,6 +49,8 @@ Other Changes: clipping, more than 16 KB characters are visible in the same low-level ImDrawList::RenderText call. ImGui-level functions such as TextUnformatted() are not affected. This is quite rare but it will be addressed later). (#3349) +- Selectable: Fixed highlight/hit extent when used with horizontal scrolling (in or outside columns). + Also fixed related text clipping when used in a column after the first one. (#3187, #3386) - Scrolling: Avoid SetScroll, SetScrollFromPos functions from snapping on the edge of scroll limits when close-enough by (WindowPadding - ItemPadding), which was a tweak with too many side-effects. The behavior is still present in SetScrollHere functions as they are more explicitly diff --git a/imgui.cpp b/imgui.cpp index e6d7f61d311a..c61273557034 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5898,6 +5898,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags) window->WorkRect.Min.y = ImFloor(window->InnerRect.Min.y - window->Scroll.y + ImMax(window->WindowPadding.y, window->WindowBorderSize)); window->WorkRect.Max.x = window->WorkRect.Min.x + work_rect_size_x; window->WorkRect.Max.y = window->WorkRect.Min.y + work_rect_size_y; + window->ParentWorkRect = window->WorkRect; // [LEGACY] Content Region // FIXME-OBSOLETE: window->ContentRegionRect.Max is currently very misleading / partly faulty, but some BeginChild() patterns relies on it. diff --git a/imgui_internal.h b/imgui_internal.h index e0f8ae02bb5f..65e6e9e7104a 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1015,7 +1015,7 @@ struct ImGuiColumns float HostCursorMaxPosX; // Backup of CursorMaxPos at the time of BeginColumns() ImRect HostInitialClipRect; // Backup of ClipRect at the time of BeginColumns() ImRect HostBackupClipRect; // Backup of ClipRect during PushColumnsBackground()/PopColumnsBackground() - ImRect HostWorkRect; // Backup of WorkRect at the time of BeginColumns() + ImRect HostBackupParentWorkRect;//Backup of WorkRect at the time of BeginColumns() ImVector Columns; ImDrawListSplitter Splitter; @@ -1612,7 +1612,8 @@ struct IMGUI_API ImGuiWindow ImRect OuterRectClipped; // == Window->Rect() just after setup in Begin(). == window->Rect() for root window. ImRect InnerRect; // Inner rectangle (omit title bar, menu bar, scroll bar) ImRect InnerClipRect; // == InnerRect shrunk by WindowPadding*0.5f on each side, clipped within viewport or parent clip rect. - ImRect WorkRect; // Cover the whole scrolling region, shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentRegionRect over time (from 1.71+ onward). + ImRect WorkRect; // Initially covers the whole scrolling region. Reduced by containers e.g columns/tables when active. Shrunk by WindowPadding*1.0f on each side. This is meant to replace ContentRegionRect over time (from 1.71+ onward). + ImRect ParentWorkRect; // Backup of WorkRect before entering a container such as columns/tables. Used by e.g. SpanAllColumns functions to easily access. Stacked containers are responsible for maintaining this. // FIXME-WORKRECT: Could be a stack? ImRect ClipRect; // Current clipping/scissoring rectangle, evolve as we are using PushClipRect(), etc. == DrawList->clip_rect_stack.back(). ImRect ContentRegionRect; // FIXME: This is currently confusing/misleading. It is essentially WorkRect but not handling of scrolling. We currently rely on it as right/bottom aligned sizing operation need some size to rely on. ImVec2ih HitTestHoleSize; // Define an optional rectangular hole where mouse will pass-through the window. diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 55dc64333c30..1d4362d0d31f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5704,8 +5704,8 @@ bool ImGui::Selectable(const char* label, bool selected, ImGuiSelectableFlags fl ItemSize(size, 0.0f); // Fill horizontal space - const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Min.x : pos.x; - const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ContentRegionRect.Max.x : GetContentRegionMaxAbs().x; + const float min_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ParentWorkRect.Min.x : pos.x; + const float max_x = (flags & ImGuiSelectableFlags_SpanAllColumns) ? window->ParentWorkRect.Max.x : window->WorkRect.Max.x; if (size_arg.x == 0.0f || (flags & ImGuiSelectableFlags_SpanAvailWidth)) size.x = ImMax(label_size.x, max_x - min_x); @@ -7665,7 +7665,8 @@ void ImGui::BeginColumns(const char* str_id, int columns_count, ImGuiColumnsFlag columns->HostCursorPosY = window->DC.CursorPos.y; columns->HostCursorMaxPosX = window->DC.CursorMaxPos.x; columns->HostInitialClipRect = window->ClipRect; - columns->HostWorkRect = window->WorkRect; + columns->HostBackupParentWorkRect = window->ParentWorkRect; + window->ParentWorkRect = window->WorkRect; // Set state for first column // We aim so that the right-most column will have the same clipping width as other after being clipped by parent ClipRect @@ -7845,7 +7846,8 @@ void ImGui::EndColumns() } columns->IsBeingResized = is_being_resized; - window->WorkRect = columns->HostWorkRect; + window->WorkRect = window->ParentWorkRect; + window->ParentWorkRect = columns->HostBackupParentWorkRect; window->DC.CurrentColumns = NULL; window->DC.ColumnsOffset.x = 0.0f; window->DC.CursorPos.x = IM_FLOOR(window->Pos.x + window->DC.Indent.x + window->DC.ColumnsOffset.x);