mirror of
https://github.com/Drezil/imgui.git
synced 2024-11-25 21:17:01 +00:00
Internals: Docking, Tab Bar: Add DockNodeBeginAmendTabBar() and work toward making hybrid dock node with windows tab bars somehow work (not done).
This commit is contained in:
parent
bae2240eda
commit
b26f1530b7
46
imgui.cpp
46
imgui.cpp
@ -12510,6 +12510,8 @@ bool ImGui::DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode*
|
||||
// - DockNodeStartMouseMovingWindow()
|
||||
// - DockNodeUpdate()
|
||||
// - DockNodeUpdateWindowMenu()
|
||||
// - DockNodeBeginAmendTabBar()
|
||||
// - DockNodeEndAmendTabBar()
|
||||
// - DockNodeUpdateTabBar()
|
||||
// - DockNodeAddTabBar()
|
||||
// - DockNodeRemoveTabBar()
|
||||
@ -13231,7 +13233,8 @@ static ImGuiID ImGui::DockNodeUpdateWindowMenu(ImGuiDockNode* node, ImGuiTabBar*
|
||||
for (int tab_n = 0; tab_n < tab_bar->Tabs.Size; tab_n++)
|
||||
{
|
||||
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
|
||||
IM_ASSERT(tab->Window != NULL);
|
||||
if (tab->Window == NULL)
|
||||
continue;
|
||||
if (Selectable(tab->Window->Name, tab->ID == tab_bar->SelectedTabId))
|
||||
ret_tab_id = tab->ID;
|
||||
SameLine();
|
||||
@ -13243,6 +13246,26 @@ static ImGuiID ImGui::DockNodeUpdateWindowMenu(ImGuiDockNode* node, ImGuiTabBar*
|
||||
return ret_tab_id;
|
||||
}
|
||||
|
||||
// User helper to append/amend into a dock node tab bar. Most commonly used to add e.g. a "+" button.
|
||||
bool ImGui::DockNodeBeginAmendTabBar(ImGuiDockNode* node)
|
||||
{
|
||||
if (node->TabBar == NULL || node->HostWindow == NULL)
|
||||
return false;
|
||||
Begin(node->HostWindow->Name);
|
||||
PushOverrideID(node->ID);
|
||||
bool ret = BeginTabBarEx(node->TabBar, node->TabBar->BarRect, node->TabBar->Flags, node);
|
||||
IM_ASSERT(ret);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ImGui::DockNodeEndAmendTabBar()
|
||||
{
|
||||
EndTabBar();
|
||||
PopID();
|
||||
End();
|
||||
}
|
||||
|
||||
// Submit the tab bar corresponding to a dock node and various housekeeping details.
|
||||
static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_window)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -13446,7 +13469,14 @@ static void ImGui::DockNodeUpdateTabBar(ImGuiDockNode* node, ImGuiWindow* host_w
|
||||
if (g.HoveredId == 0 || g.HoveredId == title_bar_id || g.ActiveId == title_bar_id)
|
||||
{
|
||||
bool held;
|
||||
ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held);
|
||||
ButtonBehavior(title_bar_rect, title_bar_id, NULL, &held, ImGuiButtonFlags_AllowItemOverlap);
|
||||
if (g.HoveredId == title_bar_id)
|
||||
{
|
||||
// ImGuiButtonFlags_AllowItemOverlap + SetItemAllowOverlap() required for appending into dock node tab bar,
|
||||
// otherwise dragging window will steal HoveredId and amended tabs cannot get them.
|
||||
host_window->DC.LastItemId = title_bar_id;
|
||||
SetItemAllowOverlap();
|
||||
}
|
||||
if (held)
|
||||
{
|
||||
if (IsMouseClicked(0))
|
||||
@ -15847,13 +15877,13 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
const char* buf_end = buf + IM_ARRAYSIZE(buf);
|
||||
const bool is_active = (tab_bar->PrevFrameVisible >= ImGui::GetFrameCount() - 2);
|
||||
p += ImFormatString(p, buf_end - p, "Tab Bar 0x%08X (%d tabs)%s", tab_bar->ID, tab_bar->Tabs.Size, is_active ? "" : " *Inactive*");
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
|
||||
p += ImFormatString(p, buf_end - p, " { ");
|
||||
for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
|
||||
{
|
||||
p += ImFormatString(p, buf_end - p, " { ");
|
||||
for (int tab_n = 0; tab_n < ImMin(tab_bar->Tabs.Size, 3); tab_n++)
|
||||
p += ImFormatString(p, buf_end - p, "%s'%s'", tab_n > 0 ? ", " : "", tab_bar->Tabs[tab_n].Window->Name);
|
||||
p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } ");
|
||||
ImGuiTabItem* tab = &tab_bar->Tabs[tab_n];
|
||||
p += ImFormatString(p, buf_end - p, "%s'%s'", tab_n > 0 ? ", " : "", (tab->Window || tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???");
|
||||
}
|
||||
p += ImFormatString(p, buf_end - p, (tab_bar->Tabs.Size > 3) ? " ... }" : " } ");
|
||||
if (!is_active) { PushStyleColor(ImGuiCol_Text, GetStyleColorVec4(ImGuiCol_TextDisabled)); }
|
||||
bool open = ImGui::TreeNode(tab_bar, "%s", buf);
|
||||
if (!is_active) { PopStyleColor(); }
|
||||
@ -15872,7 +15902,7 @@ void ImGui::ShowMetricsWindow(bool* p_open)
|
||||
ImGui::PushID(tab);
|
||||
if (ImGui::SmallButton("<")) { TabBarQueueReorder(tab_bar, tab, -1); } ImGui::SameLine(0, 2);
|
||||
if (ImGui::SmallButton(">")) { TabBarQueueReorder(tab_bar, tab, +1); } ImGui::SameLine();
|
||||
ImGui::Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->Window || tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "", tab->Offset, tab->Width, tab->ContentWidth);
|
||||
ImGui::Text("%02d%c Tab 0x%08X '%s' Offset: %.1f, Width: %.1f/%.1f", tab_n, (tab->ID == tab_bar->SelectedTabId) ? '*' : ' ', tab->ID, (tab->Window || tab->NameOffset != -1) ? tab_bar->GetTabName(tab) : "???", tab->Offset, tab->Width, tab->ContentWidth);
|
||||
ImGui::PopID();
|
||||
}
|
||||
ImGui::TreePop();
|
||||
|
@ -2170,6 +2170,8 @@ namespace ImGui
|
||||
IMGUI_API void DockContextQueueUndockWindow(ImGuiContext* ctx, ImGuiWindow* window);
|
||||
IMGUI_API void DockContextQueueUndockNode(ImGuiContext* ctx, ImGuiDockNode* node);
|
||||
IMGUI_API bool DockContextCalcDropPosForDocking(ImGuiWindow* target, ImGuiDockNode* target_node, ImGuiWindow* payload, ImGuiDir split_dir, bool split_outer, ImVec2* out_pos);
|
||||
IMGUI_API bool DockNodeBeginAmendTabBar(ImGuiDockNode* node);
|
||||
IMGUI_API void DockNodeEndAmendTabBar();
|
||||
inline ImGuiDockNode* DockNodeGetRootNode(ImGuiDockNode* node) { while (node->ParentNode) node = node->ParentNode; return node; }
|
||||
inline int DockNodeGetDepth(const ImGuiDockNode* node) { int depth = 0; while (node->ParentNode) { node = node->ParentNode; depth++; } return depth; }
|
||||
inline ImGuiDockNode* GetWindowDockNode() { ImGuiContext& g = *GImGui; return g.CurrentWindow->DockNode; }
|
||||
|
@ -6824,7 +6824,7 @@ struct ImGuiTabBarSection
|
||||
namespace ImGui
|
||||
{
|
||||
static void TabBarLayout(ImGuiTabBar* tab_bar);
|
||||
static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label);
|
||||
static ImU32 TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window);
|
||||
static float TabBarCalcMaxTabWidth();
|
||||
static float TabBarScrollClamp(ImGuiTabBar* tab_bar, float scrolling);
|
||||
static void TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImGuiTabBarSection* sections);
|
||||
@ -6918,7 +6918,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
||||
|
||||
// Ensure correct ordering when toggling ImGuiTabBarFlags_Reorderable flag, or when a new tab was added while being not reorderable
|
||||
if ((flags & ImGuiTabBarFlags_Reorderable) != (tab_bar->Flags & ImGuiTabBarFlags_Reorderable) || (tab_bar->TabsAddedNew && !(flags & ImGuiTabBarFlags_Reorderable)))
|
||||
if (tab_bar->Tabs.Size > 1 && (flags & ImGuiTabBarFlags_DockNode) == 0)
|
||||
if (tab_bar->Tabs.Size > 1 && (flags & ImGuiTabBarFlags_DockNode) == 0) // FIXME: TabBar with DockNode can now be hybrid
|
||||
ImQsort(tab_bar->Tabs.Data, tab_bar->Tabs.Size, sizeof(ImGuiTabItem), TabItemComparerByBeginOrder);
|
||||
tab_bar->TabsAddedNew = false;
|
||||
|
||||
@ -7177,6 +7177,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
{
|
||||
ImGuiTabItem* tab = &tab_bar->Tabs[section_tab_index + tab_n];
|
||||
tab->Offset = tab_offset;
|
||||
tab->NameOffset = -1;
|
||||
tab_offset += tab->Width + (tab_n < section->TabCount - 1 ? g.Style.ItemInnerSpacing.x : 0.0f);
|
||||
}
|
||||
tab_bar->WidthAllTabs += ImMax(section->Width + section->Spacing, 0.0f);
|
||||
@ -7184,6 +7185,9 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
section_tab_index += section->TabCount;
|
||||
}
|
||||
|
||||
// Clear name buffers
|
||||
tab_bar->TabsNames.Buf.resize(0);
|
||||
|
||||
// If we have lost the selected tab, select the next most recently active one
|
||||
if (found_selected_tab_id == false)
|
||||
tab_bar->SelectedTabId = 0;
|
||||
@ -7220,21 +7224,18 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
||||
tab_bar->ScrollingRectMinX = tab_bar->BarRect.Min.x + sections[0].Width + sections[0].Spacing;
|
||||
tab_bar->ScrollingRectMaxX = tab_bar->BarRect.Max.x - sections[2].Width - sections[1].Spacing;
|
||||
|
||||
// Clear name buffers
|
||||
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
|
||||
tab_bar->TabsNames.Buf.resize(0);
|
||||
|
||||
// Actual layout in host window (we don't do it in BeginTabBar() so as not to waste an extra frame)
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
window->DC.CursorPos = tab_bar->BarRect.Min;
|
||||
ItemSize(ImVec2(tab_bar->WidthAllTabsIdeal, tab_bar->BarRect.GetHeight()), tab_bar->FramePadding.y);
|
||||
}
|
||||
|
||||
// Dockables uses Name/ID in the global namespace. Non-dockable items use the ID stack.
|
||||
static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label)
|
||||
// Dockable uses Name/ID in the global namespace. Non-dockable items use the ID stack.
|
||||
static ImU32 ImGui::TabBarCalcTabID(ImGuiTabBar* tab_bar, const char* label, ImGuiWindow* docked_window)
|
||||
{
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
|
||||
if (docked_window != NULL)
|
||||
{
|
||||
IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_DockNode);
|
||||
ImGuiID id = ImHashStr(label);
|
||||
KeepAliveID(id);
|
||||
return id;
|
||||
@ -7581,7 +7582,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
return false;
|
||||
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const ImGuiID id = TabBarCalcTabID(tab_bar, label);
|
||||
const ImGuiID id = TabBarCalcTabID(tab_bar, label, docked_window);
|
||||
|
||||
// If the user called us with *p_open == false, we early out and don't render.
|
||||
// We make a call to ItemAdd() so that attempts to use a contextual popup menu with an implicit ID won't use an older ID.
|
||||
@ -7631,9 +7632,10 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
||||
tab->Window = docked_window;
|
||||
|
||||
// Append name with zero-terminator
|
||||
if (tab_bar->Flags & ImGuiTabBarFlags_DockNode)
|
||||
// (regular tabs are permitted in a DockNode tab bar, but window tabs not permitted in a non-DockNode tab bar)
|
||||
if (tab->Window != NULL)
|
||||
{
|
||||
IM_ASSERT(tab->Window != NULL);
|
||||
IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_DockNode);
|
||||
tab->NameOffset = -1;
|
||||
}
|
||||
else
|
||||
@ -7851,7 +7853,7 @@ void ImGui::SetTabItemClosed(const char* label)
|
||||
if (is_within_manual_tab_bar)
|
||||
{
|
||||
ImGuiTabBar* tab_bar = g.CurrentTabBar;
|
||||
ImGuiID tab_id = TabBarCalcTabID(tab_bar, label);
|
||||
ImGuiID tab_id = TabBarCalcTabID(tab_bar, label, NULL);
|
||||
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
|
||||
tab->WantClose = true; // Will be processed by next call to TabBarLayout()
|
||||
}
|
||||
@ -7860,7 +7862,7 @@ void ImGui::SetTabItemClosed(const char* label)
|
||||
if (window->DockIsActive)
|
||||
if (ImGuiDockNode* node = window->DockNode)
|
||||
{
|
||||
ImGuiID tab_id = TabBarCalcTabID(node->TabBar, label);
|
||||
ImGuiID tab_id = TabBarCalcTabID(node->TabBar, label, window);
|
||||
TabBarRemoveTab(node->TabBar, tab_id);
|
||||
window->DockTabWantClose = true;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user