| 2738 | } |
| 2739 | |
| 2740 | static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) |
| 2741 | { |
| 2742 | ImGuiContext& g = *GImGui; |
| 2743 | ImGuiWindow* window = g.CurrentWindow; |
| 2744 | ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; |
| 2745 | IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?"); |
| 2746 | |
| 2747 | ImGuiTable* table = g.CurrentTable; |
| 2748 | if (table && table->IsInsideRow) |
| 2749 | ImGui::TableEndRow(table); |
| 2750 | |
| 2751 | // No items |
| 2752 | if (clipper->ItemsCount == 0 || GetSkipItemForListClipping()) |
| 2753 | return false; |
| 2754 | |
| 2755 | // While we are in frozen row state, keep displaying items one by one, unclipped |
| 2756 | // FIXME: Could be stored as a table-agnostic state. |
| 2757 | if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows) |
| 2758 | { |
| 2759 | clipper->DisplayStart = data->ItemsFrozen; |
| 2760 | clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount); |
| 2761 | if (clipper->DisplayStart < clipper->DisplayEnd) |
| 2762 | data->ItemsFrozen++; |
| 2763 | return true; |
| 2764 | } |
| 2765 | |
| 2766 | // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height) |
| 2767 | bool calc_clipping = false; |
| 2768 | if (data->StepNo == 0) |
| 2769 | { |
| 2770 | clipper->StartPosY = window->DC.CursorPos.y; |
| 2771 | if (clipper->ItemsHeight <= 0.0f) |
| 2772 | { |
| 2773 | // Submit the first item (or range) so we can measure its height (generally the first range is 0..1) |
| 2774 | data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1)); |
| 2775 | clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen); |
| 2776 | clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount); |
| 2777 | data->StepNo = 1; |
| 2778 | return true; |
| 2779 | } |
| 2780 | calc_clipping = true; // If on the first step with known item height, calculate clipping. |
| 2781 | } |
| 2782 | |
| 2783 | // Step 1: Let the clipper infer height from first range |
| 2784 | if (clipper->ItemsHeight <= 0.0f) |
| 2785 | { |
| 2786 | IM_ASSERT(data->StepNo == 1); |
| 2787 | if (table) |
| 2788 | IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y); |
| 2789 | |
| 2790 | clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart); |
| 2791 | bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); |
| 2792 | if (affected_by_floating_point_precision) |
| 2793 | clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. |
| 2794 | |
| 2795 | IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); |
| 2796 | calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards. |
| 2797 | } |
no test coverage detected