This is called only once a frame before by the first call to ItemTab() The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions.
| 7470 | // This is called only once a frame before by the first call to ItemTab() |
| 7471 | // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions. |
| 7472 | static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) |
| 7473 | { |
| 7474 | ImGuiContext& g = *GImGui; |
| 7475 | tab_bar->WantLayout = false; |
| 7476 | |
| 7477 | // Garbage collect by compacting list |
| 7478 | // Detect if we need to sort out tab list (e.g. in rare case where a tab changed section) |
| 7479 | int tab_dst_n = 0; |
| 7480 | bool need_sort_by_section = false; |
| 7481 | ImGuiTabBarSection sections[3]; // Layout sections: Leading, Central, Trailing |
| 7482 | for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++) |
| 7483 | { |
| 7484 | ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n]; |
| 7485 | if (tab->LastFrameVisible < tab_bar->PrevFrameVisible || tab->WantClose) |
| 7486 | { |
| 7487 | // Remove tab |
| 7488 | if (tab_bar->VisibleTabId == tab->ID) { tab_bar->VisibleTabId = 0; } |
| 7489 | if (tab_bar->SelectedTabId == tab->ID) { tab_bar->SelectedTabId = 0; } |
| 7490 | if (tab_bar->NextSelectedTabId == tab->ID) { tab_bar->NextSelectedTabId = 0; } |
| 7491 | continue; |
| 7492 | } |
| 7493 | if (tab_dst_n != tab_src_n) |
| 7494 | tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n]; |
| 7495 | |
| 7496 | tab = &tab_bar->Tabs[tab_dst_n]; |
| 7497 | tab->IndexDuringLayout = (ImS16)tab_dst_n; |
| 7498 | |
| 7499 | // We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another) |
| 7500 | int curr_tab_section_n = TabItemGetSectionIdx(tab); |
| 7501 | if (tab_dst_n > 0) |
| 7502 | { |
| 7503 | ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1]; |
| 7504 | int prev_tab_section_n = TabItemGetSectionIdx(prev_tab); |
| 7505 | if (curr_tab_section_n == 0 && prev_tab_section_n != 0) |
| 7506 | need_sort_by_section = true; |
| 7507 | if (prev_tab_section_n == 2 && curr_tab_section_n != 2) |
| 7508 | need_sort_by_section = true; |
| 7509 | } |
| 7510 | |
| 7511 | sections[curr_tab_section_n].TabCount++; |
| 7512 | tab_dst_n++; |
| 7513 | } |
| 7514 | if (tab_bar->Tabs.Size != tab_dst_n) |
| 7515 | tab_bar->Tabs.resize(tab_dst_n); |
| 7516 | |
| 7517 | if (need_sort_by_section) |
| 7518 | ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerBySection); |
| 7519 | |
| 7520 | // Calculate spacing between sections |
| 7521 | sections[0].Spacing = sections[0].TabCount > 0 && (sections[1].TabCount + sections[2].TabCount) > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; |
| 7522 | sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; |
| 7523 | |
| 7524 | // Setup next selected tab |
| 7525 | ImGuiID scroll_to_tab_id = 0; |
| 7526 | if (tab_bar->NextSelectedTabId) |
| 7527 | { |
| 7528 | tab_bar->SelectedTabId = tab_bar->NextSelectedTabId; |
| 7529 | tab_bar->NextSelectedTabId = 0; |
nothing calls this directly
no test coverage detected