IM_ASSERT(ItemsCount==-1&&"Forgot to call End(), or to Step() until false?");
}
// Use case A: Begin() called from constructor with items_height<0, then called again from Step() in StepNo 1
// Use case B: Begin() called from constructor with items_height>0
// 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.
// In theory here we should assert that ImGui::GetCursorPosY() == StartPosY + DisplayEnd * ItemsHeight, but it feels saner to just seek at the end and not assert/crash the user.
if(StepNo==0)// Step 0: the clipper let you process the first element, regardless of it being visible or not, so we can measure the element height.
// Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height)
if(StepNo==0)
{
DisplayStart=0;
DisplayEnd=1;
StartPosY=window->DC.CursorPos.y;
StepNo=1;
returntrue;
if(ItemsHeight<=0.0f)
{
// Submit the first item so we can measure its height (generally it is 0..1)
DisplayStart=0;
DisplayEnd=1;
StepNo=1;
returntrue;
}
// Already has item height (given by user in Begin): skip to calculating step
DisplayStart=DisplayEnd;
StepNo=2;
}
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.
// Step 1: the clipper infer height from first element
IM_ASSERT(items_height>0.0f);// If this triggers, it means Item 0 hasn't moved the cursor vertically
Begin(ItemsCount-1,items_height);
DisplayStart++;
DisplayEnd++;
StepNo=3;
returntrue;
IM_ASSERT(ItemsHeight<=0.0f);
ItemsHeight=window->DC.CursorPos.y-StartPosY;
IM_ASSERT(ItemsHeight>0.0f&&"Unable to calculate item height! First item hasn't moved the cursor vertically!");
StepNo=2;
}
if(StepNo==2)// Step 2: empty step only required if an explicit items_height was passed to constructor or Begin() and user still call Step(). Does nothing and switch to Step 3.
// Step 2: calculate the actual range of elements to display, and position the cursor before the first element
if(StepNo==3)// Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
End();
// Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd),
// Advance the cursor to the end of the list and then returns 'false' to end the loop.
// - Step 3: the clipper validate that we have reached the expected Y position (corresponding to element DisplayEnd), advance the cursor to the end of the list and then returns 'false' to end the loop.
structImGuiListClipper
{
intDisplayStart,DisplayEnd;
intDisplayStart;
intDisplayEnd;
intItemsCount;
// [Internal]
@ -1911,12 +1912,12 @@ struct ImGuiListClipper
// items_count: Use -1 to ignore (you can call Begin later). Use INT_MAX if you don't know how many items you have (in which case the cursor won't be advanced in the final step).
// items_height: Use -1.0f to be calculated automatically on first step. Otherwise pass in the distance between your items, typically GetTextLineHeightWithSpacing() or GetFrameHeightWithSpacing().
// If you don't specify an items_height, you NEED to call Step(). If you specify items_height you may call the old Begin()/End() api directly, but prefer calling Step().
ImGuiListClipper(intitems_count=-1,floatitems_height=-1.0f){Begin(items_count,items_height);}// NB: Begin() initialize every fields (as we allow user to call Begin/End multiple times on a same instance if they want).
~ImGuiListClipper(){IM_ASSERT(ItemsCount==-1);}// Assert if user forgot to call End() or Step() until false.
// Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper.
ImGuiContext&g=*GImGui;
boolvalue_changed=false;
ImGuiListClipperclipper(items_count,GetTextLineHeightWithSpacing());// We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.
ImGuiListClipperclipper;
clipper.Begin(items_count,GetTextLineHeightWithSpacing());// We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to.