Internals: ImGuiListClipper using absolute coordinate (instead of relative one). Minor no-op tweaks + ImDrawListSplitter assert
This commit is contained in:
parent
1dd322c6fb
commit
82711251b6
31
imgui.cpp
31
imgui.cpp
@ -2239,7 +2239,8 @@ void ImGuiTextBuffer::appendfv(const char* fmt, va_list args)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] ImGuiListClipper
|
||||
// This is currently not as flexible/powerful as it should be, needs some rework (see TODO)
|
||||
// This is currently not as flexible/powerful as it should be and really confusing/spaghetti, mostly because we changed
|
||||
// the API mid-way through development and support two ways to using the clipper, needs some rework (see TODO)
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
|
||||
@ -2247,12 +2248,14 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
|
||||
// Set cursor position and a few other things so that SetScrollHereY() and Columns() can work when seeking cursor.
|
||||
// FIXME: It is problematic that we have to do that here, because custom/equivalent end-user code would stumble on the same issue.
|
||||
// The clipper should probably have a 4th step to display the last item in a regular manner.
|
||||
ImGui::SetCursorPosY(pos_y);
|
||||
ImGuiWindow* window = ImGui::GetCurrentWindow();
|
||||
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
|
||||
window->DC.PrevLineSize.y = (line_height - GImGui->Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
window->DC.CursorPos.y = pos_y;
|
||||
window->DC.CursorMaxPos.y = ImMax(window->DC.CursorMaxPos.y, pos_y);
|
||||
window->DC.CursorPosPrevLine.y = window->DC.CursorPos.y - line_height; // Setting those fields so that SetScrollHereY() can properly function after the end of our clipper usage.
|
||||
window->DC.PrevLineSize.y = (line_height - g.Style.ItemSpacing.y); // If we end up needing more accurate data (to e.g. use SameLine) we may as well make the clipper have a fourth step to let user process and display the last item in their list.
|
||||
if (ImGuiColumns* columns = window->DC.CurrentColumns)
|
||||
columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
|
||||
columns->LineMinY = window->DC.CursorPos.y; // Setting this so that cell Y position are set properly
|
||||
}
|
||||
|
||||
// Use case A: Begin() called from constructor with items_height<0, then called again from Sync() in StepNo 1
|
||||
@ -2260,7 +2263,10 @@ static void SetCursorPosYAndSetupDummyPrevLine(float pos_y, float line_height)
|
||||
// FIXME-LEGACY: Ideally we should remove the Begin/End functions but they are part of the legacy API we still support. This is why some of the code in Step() calling Begin() and reassign some fields, spaghetti style.
|
||||
void ImGuiListClipper::Begin(int count, float items_height)
|
||||
{
|
||||
StartPosY = ImGui::GetCursorPosY();
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
StartPosY = window->DC.CursorPos.y;
|
||||
ItemsHeight = items_height;
|
||||
ItemsCount = count;
|
||||
StepNo = 0;
|
||||
@ -2287,7 +2293,10 @@ void ImGuiListClipper::End()
|
||||
|
||||
bool ImGuiListClipper::Step()
|
||||
{
|
||||
if (ItemsCount == 0 || ImGui::GetCurrentWindowRead()->SkipItems)
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
if (ItemsCount == 0 || window->SkipItems)
|
||||
{
|
||||
ItemsCount = -1;
|
||||
return false;
|
||||
@ -2296,16 +2305,16 @@ bool ImGuiListClipper::Step()
|
||||
{
|
||||
DisplayStart = 0;
|
||||
DisplayEnd = 1;
|
||||
StartPosY = ImGui::GetCursorPosY();
|
||||
StartPosY = window->DC.CursorPos.y;
|
||||
StepNo = 1;
|
||||
return true;
|
||||
}
|
||||
if (StepNo == 1) // Step 1: the clipper infer height from first element, calculate the actual range of elements to display, and position the cursor before the first element.
|
||||
{
|
||||
if (ItemsCount == 1) { ItemsCount = -1; return false; }
|
||||
float items_height = ImGui::GetCursorPosY() - StartPosY;
|
||||
float items_height = window->DC.CursorPos.y - StartPosY;
|
||||
IM_ASSERT(items_height > 0.0f); // If this triggers, it means Item 0 hasn't moved the cursor vertically
|
||||
Begin(ItemsCount-1, items_height);
|
||||
Begin(ItemsCount - 1, items_height);
|
||||
DisplayStart++;
|
||||
DisplayEnd++;
|
||||
StepNo = 3;
|
||||
|
@ -4022,7 +4022,7 @@ static void ShowExampleAppLongText(bool* p_open)
|
||||
static ImGuiTextBuffer log;
|
||||
static int lines = 0;
|
||||
ImGui::Text("Printing unusually long amount of text.");
|
||||
ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped manually\0Multiple calls to Text(), not clipped (slow)\0");
|
||||
ImGui::Combo("Test type", &test_type, "Single call to TextUnformatted()\0Multiple calls to Text(), clipped\0Multiple calls to Text(), not clipped (slow)\0");
|
||||
ImGui::Text("Buffer contents: %d lines, %d bytes", lines, log.size());
|
||||
if (ImGui::Button("Clear")) { log.clear(); lines = 0; }
|
||||
ImGui::SameLine();
|
||||
|
@ -1304,7 +1304,7 @@ void ImDrawListSplitter::Merge(ImDrawList* draw_list)
|
||||
|
||||
void ImDrawListSplitter::SetCurrentChannel(ImDrawList* draw_list, int idx)
|
||||
{
|
||||
IM_ASSERT(idx < _Count);
|
||||
IM_ASSERT(idx >= 0 && idx < _Count);
|
||||
if (_Current == idx)
|
||||
return;
|
||||
// Overwrite ImVector (12/16 bytes), four times. This is merely a silly optimization instead of doing .swap()
|
||||
|
Loading…
Reference in New Issue
Block a user