| 2862 | } |
| 2863 | |
| 2864 | static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) |
| 2865 | { |
| 2866 | ImGuiContext& g = *clipper->Ctx; |
| 2867 | ImGuiWindow* window = g.CurrentWindow; |
| 2868 | ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; |
| 2869 | IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?"); |
| 2870 | |
| 2871 | ImGuiTable* table = g.CurrentTable; |
| 2872 | if (table && table->IsInsideRow) |
| 2873 | ImGui::TableEndRow(table); |
| 2874 | |
| 2875 | // No items |
| 2876 | if (clipper->ItemsCount == 0 || GetSkipItemForListClipping()) |
| 2877 | return false; |
| 2878 | |
| 2879 | // While we are in frozen row state, keep displaying items one by one, unclipped |
| 2880 | // FIXME: Could be stored as a table-agnostic state. |
| 2881 | if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows) |
| 2882 | { |
| 2883 | clipper->DisplayStart = data->ItemsFrozen; |
| 2884 | clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount); |
| 2885 | if (clipper->DisplayStart < clipper->DisplayEnd) |
| 2886 | data->ItemsFrozen++; |
| 2887 | return true; |
| 2888 | } |
| 2889 | |
| 2890 | // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height) |
| 2891 | bool calc_clipping = false; |
| 2892 | if (data->StepNo == 0) |
| 2893 | { |
| 2894 | clipper->StartPosY = window->DC.CursorPos.y; |
| 2895 | if (clipper->ItemsHeight <= 0.0f) |
| 2896 | { |
| 2897 | // Submit the first item (or range) so we can measure its height (generally the first range is 0..1) |
| 2898 | data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1)); |
| 2899 | clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen); |
| 2900 | clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount); |
| 2901 | data->StepNo = 1; |
| 2902 | return true; |
| 2903 | } |
| 2904 | calc_clipping = true; // If on the first step with known item height, calculate clipping. |
| 2905 | } |
| 2906 | |
| 2907 | // Step 1: Let the clipper infer height from first range |
| 2908 | if (clipper->ItemsHeight <= 0.0f) |
| 2909 | { |
| 2910 | IM_ASSERT(data->StepNo == 1); |
| 2911 | if (table) |
| 2912 | IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y); |
| 2913 | |
| 2914 | clipper->ItemsHeight = (window->DC.CursorPos.y - clipper->StartPosY) / (float)(clipper->DisplayEnd - clipper->DisplayStart); |
| 2915 | bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision(clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); |
| 2916 | if (affected_by_floating_point_precision) |
| 2917 | clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. |
| 2918 | |
| 2919 | IM_ASSERT(clipper->ItemsHeight > 0.0f && "Unable to calculate item height! First item hasn't moved the cursor vertically!"); |
| 2920 | calc_clipping = true; // If item height had to be calculated, calculate clipping afterwards. |
| 2921 | } |
no test coverage detected