| 2426 | } |
| 2427 | |
| 2428 | bool ImGuiListClipper::Step() |
| 2429 | { |
| 2430 | ImGuiContext& g = *GImGui; |
| 2431 | ImGuiWindow* window = g.CurrentWindow; |
| 2432 | ImGuiListClipperData* data = (ImGuiListClipperData*)TempData; |
| 2433 | |
| 2434 | ImGuiTable* table = g.CurrentTable; |
| 2435 | if (table && table->IsInsideRow) |
| 2436 | ImGui::TableEndRow(table); |
| 2437 | |
| 2438 | // No items |
| 2439 | if (ItemsCount == 0 || GetSkipItemForListClipping()) |
| 2440 | return (void)End(), false; |
| 2441 | |
| 2442 | // While we are in frozen row state, keep displaying items one by one, unclipped |
| 2443 | // FIXME: Could be stored as a table-agnostic state. |
| 2444 | if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows) |
| 2445 | { |
| 2446 | DisplayStart = data->ItemsFrozen; |
| 2447 | DisplayEnd = data->ItemsFrozen + 1; |
| 2448 | if (DisplayStart >= ItemsCount) |
| 2449 | return (void)End(), false; |
| 2450 | data->ItemsFrozen++; |
| 2451 | return true; |
| 2452 | } |
| 2453 | |
| 2454 | // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height) |
| 2455 | bool calc_clipping = false; |
| 2456 | if (data->StepNo == 0) |
| 2457 | { |
| 2458 | StartPosY = window->DC.CursorPos.y; |
| 2459 | if (ItemsHeight <= 0.0f) |
| 2460 | { |
| 2461 | // Submit the first item (or range) so we can measure its height (generally the first range is 0..1) |
| 2462 | data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1)); |
| 2463 | DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen); |
| 2464 | DisplayEnd = ImMin(data->Ranges[0].Max, ItemsCount); |
| 2465 | if (DisplayStart == DisplayEnd) |
| 2466 | return (void)End(), false; |
| 2467 | data->StepNo = 1; |
| 2468 | return true; |
| 2469 | } |
| 2470 | calc_clipping = true; // If on the first step with known item height, calculate clipping. |
| 2471 | } |
| 2472 | |
| 2473 | // Step 1: Let the clipper infer height from first range |
| 2474 | if (ItemsHeight <= 0.0f) |
| 2475 | { |
| 2476 | IM_ASSERT(data->StepNo == 1); |
| 2477 | if (table) |
| 2478 | IM_ASSERT(table->RowPosY1 == StartPosY && table->RowPosY2 == window->DC.CursorPos.y); |
| 2479 | |
| 2480 | ItemsHeight = (window->DC.CursorPos.y - StartPosY) / (float)(DisplayEnd - DisplayStart); |
| 2481 | bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); |
| 2482 | if (affected_by_floating_point_precision) |
| 2483 | ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. |
| 2484 | |
| 2485 | IM_ASSERT(ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); |
no test coverage detected