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.
| 7939 | // This is called only once a frame before by the first call to ItemTab() |
| 7940 | // The reason we're not calling it in BeginTabBar() is to leave a chance to the user to call the SetTabItemClosed() functions. |
| 7941 | static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) |
| 7942 | { |
| 7943 | ImGuiContext& g = *GImGui; |
| 7944 | tab_bar->WantLayout = false; |
| 7945 | |
| 7946 | // Garbage collect by compacting list |
| 7947 | // Detect if we need to sort out tab list (e.g. in rare case where a tab changed section) |
| 7948 | int tab_dst_n = 0; |
| 7949 | bool need_sort_by_section = false; |
| 7950 | ImGuiTabBarSection sections[3]; // Layout sections: Leading, Central, Trailing |
| 7951 | for (int tab_src_n = 0; tab_src_n < tab_bar->Tabs.Size; tab_src_n++) |
| 7952 | { |
| 7953 | ImGuiTabItem* tab = &tab_bar->Tabs[tab_src_n]; |
| 7954 | if (tab->LastFrameVisible < tab_bar->PrevFrameVisible || tab->WantClose) |
| 7955 | { |
| 7956 | // Remove tab |
| 7957 | if (tab_bar->VisibleTabId == tab->ID) { tab_bar->VisibleTabId = 0; } |
| 7958 | if (tab_bar->SelectedTabId == tab->ID) { tab_bar->SelectedTabId = 0; } |
| 7959 | if (tab_bar->NextSelectedTabId == tab->ID) { tab_bar->NextSelectedTabId = 0; } |
| 7960 | continue; |
| 7961 | } |
| 7962 | if (tab_dst_n != tab_src_n) |
| 7963 | tab_bar->Tabs[tab_dst_n] = tab_bar->Tabs[tab_src_n]; |
| 7964 | |
| 7965 | tab = &tab_bar->Tabs[tab_dst_n]; |
| 7966 | tab->IndexDuringLayout = (ImS16)tab_dst_n; |
| 7967 | |
| 7968 | // We will need sorting if tabs have changed section (e.g. moved from one of Leading/Central/Trailing to another) |
| 7969 | int curr_tab_section_n = TabItemGetSectionIdx(tab); |
| 7970 | if (tab_dst_n > 0) |
| 7971 | { |
| 7972 | ImGuiTabItem* prev_tab = &tab_bar->Tabs[tab_dst_n - 1]; |
| 7973 | int prev_tab_section_n = TabItemGetSectionIdx(prev_tab); |
| 7974 | if (curr_tab_section_n == 0 && prev_tab_section_n != 0) |
| 7975 | need_sort_by_section = true; |
| 7976 | if (prev_tab_section_n == 2 && curr_tab_section_n != 2) |
| 7977 | need_sort_by_section = true; |
| 7978 | } |
| 7979 | |
| 7980 | sections[curr_tab_section_n].TabCount++; |
| 7981 | tab_dst_n++; |
| 7982 | } |
| 7983 | if (tab_bar->Tabs.Size != tab_dst_n) |
| 7984 | tab_bar->Tabs.resize(tab_dst_n); |
| 7985 | |
| 7986 | if (need_sort_by_section) |
| 7987 | ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerBySection); |
| 7988 | |
| 7989 | // Calculate spacing between sections |
| 7990 | sections[0].Spacing = sections[0].TabCount > 0 && (sections[1].TabCount + sections[2].TabCount) > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; |
| 7991 | sections[1].Spacing = sections[1].TabCount > 0 && sections[2].TabCount > 0 ? g.Style.ItemInnerSpacing.x : 0.0f; |
| 7992 | |
| 7993 | // Setup next selected tab |
| 7994 | ImGuiID scroll_to_tab_id = 0; |
| 7995 | if (tab_bar->NextSelectedTabId) |
| 7996 | { |
| 7997 | tab_bar->SelectedTabId = tab_bar->NextSelectedTabId; |
| 7998 | tab_bar->NextSelectedTabId = 0; |
nothing calls this directly
no test coverage detected