Procházet zdrojové kódy

Docking: Fixed tab order restoring (follow up to 67be485e, broken in 455dc6e2)

omar před 7 roky
rodič
revize
4053d9d638
3 změnil soubory, kde provedl 24 přidání a 18 odebrání
  1. 15 8
      imgui.cpp
  2. 4 3
      imgui_internal.h
  3. 5 7
      imgui_widgets.cpp

+ 15 - 8
imgui.cpp

@@ -10229,7 +10229,7 @@ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, b
             node->TabBar = IM_NEW(ImGuiTabBar)();
             node->TabBar = IM_NEW(ImGuiTabBar)();
             node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabID;
             node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabID;
         }
         }
-        TabBarAddTab(node->TabBar, window);
+        TabBarAddTab(node->TabBar, window, ImGuiTabItemFlags_Unsorted);
     }
     }
 
 
     DockNodeUpdateVisibleFlag(node);
     DockNodeUpdateVisibleFlag(node);
@@ -10729,15 +10729,22 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
                 tab_bar->SelectedTabId = focused_id;
                 tab_bar->SelectedTabId = focused_id;
     }
     }
 
 
-    // Submit tabs order
-    // If multiple tabs are appearing on the same frame, we add them ahead sorted based on their persistent DockOrder value
-    int tabs_count_old = tab_bar->Tabs.Size;
+    // Submit new tabs
+    const int tabs_count_old = tab_bar->Tabs.Size;
     for (int window_n = 0; window_n < node->Windows.Size; window_n++)
     for (int window_n = 0; window_n < node->Windows.Size; window_n++)
         if (TabBarFindTabByID(tab_bar, node->Windows[window_n]->ID) == NULL)
         if (TabBarFindTabByID(tab_bar, node->Windows[window_n]->ID) == NULL)
-            TabBarAddTab(tab_bar, node->Windows[window_n]);
-    //printf("[%05d] Sorting %d new appearing tabs\n", g.FrameCount, tab_bar->Tabs.Size - tabs_count_old);
-    if (tab_bar->Tabs.Size > tabs_count_old + 1)
-        ImQsort(tab_bar->Tabs.Data + tabs_count_old, tab_bar->Tabs.Size - tabs_count_old, sizeof(ImGuiTabItem), TabItemComparerByDockOrder);
+            TabBarAddTab(tab_bar, node->Windows[window_n], ImGuiTabItemFlags_Unsorted);
+
+    // If multiple tabs are appearing on the same frame, sort them based on their persistent DockOrder value
+    int tabs_unsorted_start = tab_bar->Tabs.Size;
+    for (int tab_n = tab_bar->Tabs.Size - 1; tab_n >= 0 && (tab_bar->Tabs[tab_n].Flags & ImGuiTabItemFlags_Unsorted); tab_n--)
+    {
+        tab_bar->Tabs[tab_n].Flags &= ~ImGuiTabItemFlags_Unsorted;
+        tabs_unsorted_start = tab_n;
+    }
+    //printf("[%05d] Sorting %d new appearing tabs\n", g.FrameCount, tab_bar->Tabs.Size - tabs_unsorted_start);
+    if (tab_bar->Tabs.Size > tabs_unsorted_start + 1)
+        ImQsort(tab_bar->Tabs.Data + tabs_unsorted_start, tab_bar->Tabs.Size - tabs_unsorted_start, sizeof(ImGuiTabItem), TabItemComparerByDockOrder);
 
 
     // Selected newly added tabs, or persistent tab ID if the tab bar was just recreated
     // Selected newly added tabs, or persistent tab ID if the tab bar was just recreated
     if (tab_bar_is_recreated && TabBarFindTabByID(tab_bar, node->SelectedTabID) != NULL)
     if (tab_bar_is_recreated && TabBarFindTabByID(tab_bar, node->SelectedTabID) != NULL)

+ 4 - 3
imgui_internal.h

@@ -1304,8 +1304,9 @@ enum ImGuiTabBarFlagsPrivate_
 
 
 enum ImGuiTabItemFlagsPrivate_
 enum ImGuiTabItemFlagsPrivate_
 {
 {
-    ImGuiTabItemFlags_DockedWindow                  = 1 << 20,
-    ImGuiTabItemFlags_Preview                       = 1 << 21
+    ImGuiTabItemFlags_DockedWindow                  = 1 << 20,  // [Docking]
+    ImGuiTabItemFlags_Unsorted                      = 1 << 22,  // [Docking] Trailing tabs with the _Unsorted flag will be sorted based on the DockOrder of their Window.
+    ImGuiTabItemFlags_Preview                       = 1 << 21   // [Docking] Display tab shape for docking preview (height is adjusted slightly to compensate for the yet missing tab bar)
 };
 };
 
 
 // Storage for one active tab item (sizeof() 32~40 bytes)
 // Storage for one active tab item (sizeof() 32~40 bytes)
@@ -1504,7 +1505,7 @@ namespace ImGui
     // Tab Bars
     // Tab Bars
     IMGUI_API bool          BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags, ImGuiDockNode* dock_node);
     IMGUI_API bool          BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& bb, ImGuiTabBarFlags flags, ImGuiDockNode* dock_node);
     IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
     IMGUI_API ImGuiTabItem* TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id);
-    IMGUI_API void          TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiWindow* window);
+    IMGUI_API void          TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiWindow* window, ImGuiTabItemFlags tab_flags = ImGuiTabItemFlags_None);
     IMGUI_API void          TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
     IMGUI_API void          TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id);
     IMGUI_API void          TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
     IMGUI_API void          TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab);
     IMGUI_API void          TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir);
     IMGUI_API void          TabBarQueueChangeTabOrder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int dir);

+ 5 - 7
imgui_widgets.cpp

@@ -6106,22 +6106,20 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
 
 
 // The purpose of this call is to register tab in advance so we can control their order at the time they appear. 
 // The purpose of this call is to register tab in advance so we can control their order at the time they appear. 
 // Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
 // Otherwise calling this is unnecessary as tabs are appending as needed by the BeginTabItem() function.
-void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiWindow* window)
+void ImGui::TabBarAddTab(ImGuiTabBar* tab_bar, ImGuiWindow* window, ImGuiTabItemFlags tab_flags)
 {
 {
     ImGuiContext& g = *GImGui;
     ImGuiContext& g = *GImGui;
     IM_ASSERT(TabBarFindTabByID(tab_bar, window->ID) == NULL);
     IM_ASSERT(TabBarFindTabByID(tab_bar, window->ID) == NULL);
-    IM_ASSERT(g.CurrentTabBar.empty());        // Can't work while the tab bar is active as our tab doesn't have an X offset yet
+    IM_ASSERT(g.CurrentTabBar.empty());                     // Can't work while the tab bar is active as our tab doesn't have an X offset yet
 
 
     ImGuiTabItem new_tab;
     ImGuiTabItem new_tab;
     new_tab.ID = window->ID;
     new_tab.ID = window->ID;
-    new_tab.LastFrameVisible = tab_bar->CurrFrameVisible;   // Required so BeginTabBar doesn't ditch the tab
+    new_tab.Flags = tab_flags;
+    new_tab.LastFrameVisible = tab_bar->CurrFrameVisible;   // Required so BeginTabBar() doesn't ditch the tab
     if (new_tab.LastFrameVisible == -1)
     if (new_tab.LastFrameVisible == -1)
         new_tab.LastFrameVisible = g.FrameCount - 1;
         new_tab.LastFrameVisible = g.FrameCount - 1;
     new_tab.Window = window;                                // Required so tab bar layout can compute the tab width before tab submission
     new_tab.Window = window;                                // Required so tab bar layout can compute the tab width before tab submission
-    if (tab_bar->Tabs.empty())
-        tab_bar->Tabs.push_back(new_tab);
-    else 
-        tab_bar->Tabs.insert(tab_bar->Tabs.Data + tab_bar->Tabs.Size, new_tab);
+    tab_bar->Tabs.push_back(new_tab);
 }
 }
 
 
 // The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
 // The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.