| 3237 | } |
| 3238 | |
| 3239 | static bool ImGuiListClipper_StepInternal(ImGuiListClipper* clipper) |
| 3240 | { |
| 3241 | ImGuiContext& g = *clipper->Ctx; |
| 3242 | ImGuiWindow* window = g.CurrentWindow; |
| 3243 | ImGuiListClipperData* data = (ImGuiListClipperData*)clipper->TempData; |
| 3244 | IM_ASSERT(data != NULL && "Called ImGuiListClipper::Step() too many times, or before ImGuiListClipper::Begin() ?"); |
| 3245 | |
| 3246 | ImGuiTable* table = g.CurrentTable; |
| 3247 | if (table && table->IsInsideRow) |
| 3248 | ImGui::TableEndRow(table); |
| 3249 | |
| 3250 | // No items |
| 3251 | if (clipper->ItemsCount == 0 || GetSkipItemForListClipping()) |
| 3252 | return false; |
| 3253 | |
| 3254 | // While we are in frozen row state, keep displaying items one by one, unclipped |
| 3255 | // FIXME: Could be stored as a table-agnostic state. |
| 3256 | if (data->StepNo == 0 && table != NULL && !table->IsUnfrozenRows) |
| 3257 | { |
| 3258 | clipper->DisplayStart = data->ItemsFrozen; |
| 3259 | clipper->DisplayEnd = ImMin(data->ItemsFrozen + 1, clipper->ItemsCount); |
| 3260 | if (clipper->DisplayStart < clipper->DisplayEnd) |
| 3261 | data->ItemsFrozen++; |
| 3262 | return true; |
| 3263 | } |
| 3264 | |
| 3265 | // Step 0: Let you process the first element (regardless of it being visible or not, so we can measure the element height) |
| 3266 | bool calc_clipping = false; |
| 3267 | if (data->StepNo == 0) |
| 3268 | { |
| 3269 | clipper->StartPosY = window->DC.CursorPos.y; |
| 3270 | if (clipper->ItemsHeight <= 0.0f) |
| 3271 | { |
| 3272 | // Submit the first item (or range) so we can measure its height (generally the first range is 0..1) |
| 3273 | data->Ranges.push_front(ImGuiListClipperRange::FromIndices(data->ItemsFrozen, data->ItemsFrozen + 1)); |
| 3274 | clipper->DisplayStart = ImMax(data->Ranges[0].Min, data->ItemsFrozen); |
| 3275 | clipper->DisplayEnd = ImMin(data->Ranges[0].Max, clipper->ItemsCount); |
| 3276 | data->StepNo = 1; |
| 3277 | return true; |
| 3278 | } |
| 3279 | calc_clipping = true; // If on the first step with known item height, calculate clipping. |
| 3280 | } |
| 3281 | |
| 3282 | // Step 1: Let the clipper infer height from first range |
| 3283 | if (clipper->ItemsHeight <= 0.0f) |
| 3284 | { |
| 3285 | IM_ASSERT(data->StepNo == 1); |
| 3286 | if (table) |
| 3287 | IM_ASSERT(table->RowPosY1 == clipper->StartPosY && table->RowPosY2 == window->DC.CursorPos.y); |
| 3288 | |
| 3289 | bool affected_by_floating_point_precision = ImIsFloatAboveGuaranteedIntegerPrecision((float)clipper->StartPosY) || ImIsFloatAboveGuaranteedIntegerPrecision(window->DC.CursorPos.y); |
| 3290 | if (affected_by_floating_point_precision) |
| 3291 | { |
| 3292 | // Mitigation/hack for very large range: assume last time height constitute line height. |
| 3293 | clipper->ItemsHeight = window->DC.PrevLineSize.y + g.Style.ItemSpacing.y; // FIXME: Technically wouldn't allow multi-line entries. |
| 3294 | window->DC.CursorPos.y = (float)(clipper->StartPosY + clipper->ItemsHeight); |
| 3295 | } |
| 3296 | else |
no test coverage detected