From 8bac6d428d147041566c001c3927496957dc2a03 Mon Sep 17 00:00:00 2001 From: omar Date: Mon, 3 Dec 2018 23:52:48 +0100 Subject: [PATCH] Docking: Another attempt at tidying the inconsistent focus / tab bar reordering issues, and toward generalizing single window dock nodes. (#2109) --- imgui.cpp | 33 +++++++++++++++++++++------------ imgui_internal.h | 1 - imgui_widgets.cpp | 10 ++++------ 3 files changed, 25 insertions(+), 19 deletions(-) diff --git a/imgui.cpp b/imgui.cpp index 3fd666d8..bbfd48b8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -10337,7 +10337,7 @@ void ImGui::DockContextProcessDock(ImGuiContext* ctx, ImGuiDockRequest* req) // Update selection immediately if (ImGuiTabBar* tab_bar = target_node->TabBar) - tab_bar->NextSelectedTabId = tab_bar->WantFocusTabId = next_selected_id; + tab_bar->NextSelectedTabId = next_selected_id; MarkIniSettingsDirty(); } @@ -10461,6 +10461,10 @@ static void ImGui::DockNodeAddWindow(ImGuiDockNode* node, ImGuiWindow* window, b { node->TabBar = IM_NEW(ImGuiTabBar)(); node->TabBar->SelectedTabId = node->TabBar->NextSelectedTabId = node->SelectedTabID; + + // Add existing windows + for (int n = 0; n < node->Windows.Size - 1; n++) + TabBarAddTab(node->TabBar, node->Windows[n], ImGuiTabItemFlags_None); } TabBarAddTab(node->TabBar, window, ImGuiTabItemFlags_Unsorted); } @@ -10835,7 +10839,7 @@ static void ImGui::DockNodeUpdate(ImGuiDockNode* node) char window_label[20]; DockNodeGetHostWindowTitle(node, window_label, IM_ARRAYSIZE(window_label)); ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_DockNodeHost; - //window_flags |= ImGuiWindowFlags_NoFocusOnAppearing; + window_flags |= ImGuiWindowFlags_NoFocusOnAppearing; window_flags |= ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse; @@ -11018,6 +11022,8 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w if (tab_bar == NULL) tab_bar = node->TabBar = IM_NEW(ImGuiTabBar)(); + ImGuiID focus_tab_id = 0; + // Collapse button changes shape and display a list if (IsPopupOpen("#TabListMenu")) { @@ -11037,7 +11043,7 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w ImGuiTabItem* tab = &tab_bar->Tabs[tab_n]; IM_ASSERT(tab->Window != NULL); if (Selectable(tab->Window->Name, tab->ID == tab_bar->SelectedTabId)) - tab_bar->NextSelectedTabId = tab_bar->WantFocusTabId = tab->ID; + focus_tab_id = tab_bar->NextSelectedTabId = tab->ID; SameLine(); Text(" "); } @@ -11046,8 +11052,6 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w } } - ImGuiID focus_tab_id = 0; - // Title bar node->IsFocused = is_focused; if (is_focused) @@ -11063,11 +11067,16 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w if (IsItemActive()) focus_tab_id = tab_bar->SelectedTabId; - // Submit new tabs + // Submit new tabs and apply NavWindow focus back to the tab bar. They will be added as Unsorted and sorted below based on relative DockOrder value. const int tabs_count_old = tab_bar->Tabs.Size; for (int window_n = 0; window_n < node->Windows.Size; window_n++) - if (TabBarFindTabByID(tab_bar, node->Windows[window_n]->ID) == NULL) - TabBarAddTab(tab_bar, node->Windows[window_n], ImGuiTabItemFlags_Unsorted); + { + ImGuiWindow* window = node->Windows[window_n]; + if (g.NavWindow && g.NavWindow->RootWindowDockStop == window) + tab_bar->SelectedTabId = window->ID; + if (TabBarFindTabByID(tab_bar, window->ID) == NULL) + TabBarAddTab(tab_bar, window, 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; @@ -11170,13 +11179,13 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w } // Forward focus from host node to selected window - if (is_focused && g.NavWindow == host_window && !g.NavWindowingTarget) - focus_tab_id = tab_bar->SelectedTabId; + //if (is_focused && g.NavWindow == host_window && !g.NavWindowingTarget) + // focus_tab_id = tab_bar->SelectedTabId; // When clicked on a tab we requested focus to the docked child // This overrides the value set by "forward focus from host node to selected window". - if (tab_bar->WantFocusTabId) - focus_tab_id = tab_bar->WantFocusTabId; + if (tab_bar->NextSelectedTabId) + focus_tab_id = tab_bar->NextSelectedTabId; // Apply navigation focus if (focus_tab_id != 0) diff --git a/imgui_internal.h b/imgui_internal.h index 07b62002..5ab77baa 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1355,7 +1355,6 @@ struct ImGuiTabBar ImGuiID SelectedTabId; // Selected tab ImGuiID NextSelectedTabId; ImGuiID VisibleTabId; // Can occasionally be != SelectedTabId (e.g. when previewing contents for CTRL+TAB preview) - ImGuiID WantFocusTabId; // Request focus for the window associated to this tab. Used and only honored by DockNode (meaningless for standalone tab bars) int CurrFrameVisible; int PrevFrameVisible; ImRect BarRect; diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index 072ff021..fe9bc637 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5813,7 +5813,7 @@ namespace ImGui ImGuiTabBar::ImGuiTabBar() { ID = 0; - SelectedTabId = NextSelectedTabId = VisibleTabId = WantFocusTabId = 0; + SelectedTabId = NextSelectedTabId = VisibleTabId = 0; CurrFrameVisible = PrevFrameVisible = -1; OffsetMax = OffsetNextTab = 0.0f; ScrollingAnim = ScrollingTarget = 0.0f; @@ -5960,7 +5960,6 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar) // Setup next selected tab ImGuiID scroll_track_selected_tab_id = 0; - tab_bar->WantFocusTabId = 0; if (tab_bar->NextSelectedTabId) { tab_bar->SelectedTabId = tab_bar->NextSelectedTabId; @@ -6157,7 +6156,6 @@ void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id) if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id)) tab_bar->Tabs.erase(tab); if (tab_bar->VisibleTabId == tab_id) { tab_bar->VisibleTabId = 0; } - if (tab_bar->WantFocusTabId == tab_id) { tab_bar->WantFocusTabId = 0; } if (tab_bar->SelectedTabId == tab_id) { tab_bar->SelectedTabId = 0; } if (tab_bar->NextSelectedTabId == tab_id) { tab_bar->NextSelectedTabId = 0; } } @@ -6447,8 +6445,8 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, bool hovered, held; bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags); hovered |= (g.HoveredId == id); - if (pressed || ((flags & ImGuiTabItemFlags_SetSelected) && !tab_contents_visible)) // SetSelected can only be passed on explicit tab bar, so we don't need to set WantFocusTabId - tab_bar->NextSelectedTabId = tab_bar->WantFocusTabId = id; + if (pressed || ((flags & ImGuiTabItemFlags_SetSelected) && !tab_contents_visible)) // SetSelected can only be passed on explicit tab bar + tab_bar->NextSelectedTabId = id; // Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered) if (!held) @@ -6531,7 +6529,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, // Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget. const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup); if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1))) - tab_bar->NextSelectedTabId = tab_bar->WantFocusTabId = id; + tab_bar->NextSelectedTabId = id; if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton) flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;