|
@@ -7282,11 +7282,17 @@ bool ImGui::MenuItem(const char* label, const char* shortcut, bool* p_selected,
|
|
// - TabBarCalcTabID() [Internal]
|
|
// - TabBarCalcTabID() [Internal]
|
|
// - TabBarCalcMaxTabWidth() [Internal]
|
|
// - TabBarCalcMaxTabWidth() [Internal]
|
|
// - TabBarFindTabById() [Internal]
|
|
// - TabBarFindTabById() [Internal]
|
|
|
|
+// - TabBarFindTabByOrder() [Internal]
|
|
|
|
+// - TabBarGetCurrentTab() [Internal]
|
|
|
|
+// - TabBarGetTabName() [Internal]
|
|
// - TabBarRemoveTab() [Internal]
|
|
// - TabBarRemoveTab() [Internal]
|
|
// - TabBarCloseTab() [Internal]
|
|
// - TabBarCloseTab() [Internal]
|
|
// - TabBarScrollClamp() [Internal]
|
|
// - TabBarScrollClamp() [Internal]
|
|
// - TabBarScrollToTab() [Internal]
|
|
// - TabBarScrollToTab() [Internal]
|
|
-// - TabBarQueueChangeTabOrder() [Internal]
|
|
|
|
|
|
+// - TabBarQueueFocus() [Internal]
|
|
|
|
+// - TabBarQueueReorder() [Internal]
|
|
|
|
+// - TabBarProcessReorderFromMousePos() [Internal]
|
|
|
|
+// - TabBarProcessReorder() [Internal]
|
|
// - TabBarScrollingButtons() [Internal]
|
|
// - TabBarScrollingButtons() [Internal]
|
|
// - TabBarTabListPopupButton() [Internal]
|
|
// - TabBarTabListPopupButton() [Internal]
|
|
//-------------------------------------------------------------------------
|
|
//-------------------------------------------------------------------------
|
|
@@ -7411,6 +7417,7 @@ bool ImGui::BeginTabBarEx(ImGuiTabBar* tab_bar, const ImRect& tab_bar_bb, ImG
|
|
tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
|
|
tab_bar->ItemSpacingY = g.Style.ItemSpacing.y;
|
|
tab_bar->FramePadding = g.Style.FramePadding;
|
|
tab_bar->FramePadding = g.Style.FramePadding;
|
|
tab_bar->TabsActiveCount = 0;
|
|
tab_bar->TabsActiveCount = 0;
|
|
|
|
+ tab_bar->LastTabItemIdx = -1;
|
|
tab_bar->BeginCount = 1;
|
|
tab_bar->BeginCount = 1;
|
|
|
|
|
|
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
|
|
// Set cursor pos in a way which only be used in the off-chance the user erroneously submits item before BeginTabItem(): items will overlap
|
|
@@ -7459,6 +7466,7 @@ void ImGui::EndTabBar()
|
|
if (tab_bar->BeginCount > 1)
|
|
if (tab_bar->BeginCount > 1)
|
|
window->DC.CursorPos = tab_bar->BackupCursorPos;
|
|
window->DC.CursorPos = tab_bar->BackupCursorPos;
|
|
|
|
|
|
|
|
+ tab_bar->LastTabItemIdx = -1;
|
|
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
|
|
if ((tab_bar->Flags & ImGuiTabBarFlags_DockNode) == 0)
|
|
PopID();
|
|
PopID();
|
|
|
|
|
|
@@ -7568,7 +7576,7 @@ static void ImGui::TabBarLayout(ImGuiTabBar* tab_bar)
|
|
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
|
|
// Refresh tab width immediately, otherwise changes of style e.g. style.FramePadding.x would noticeably lag in the tab bar.
|
|
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
|
|
// Additionally, when using TabBarAddTab() to manipulate tab bar order we occasionally insert new tabs that don't have a width yet,
|
|
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
|
|
// and we cannot wait for the next BeginTabItem() call. We cannot compute this width within TabBarAddTab() because font size depends on the active window.
|
|
- const char* tab_name = tab_bar->GetTabName(tab);
|
|
|
|
|
|
+ const char* tab_name = TabBarGetTabName(tab_bar, tab);
|
|
const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument);
|
|
const bool has_close_button_or_unsaved_marker = (tab->Flags & ImGuiTabItemFlags_NoCloseButton) == 0 || (tab->Flags & ImGuiTabItemFlags_UnsavedDocument);
|
|
tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x;
|
|
tab->ContentWidth = (tab->RequestedWidth >= 0.0f) ? tab->RequestedWidth : TabItemCalcSize(tab_name, has_close_button_or_unsaved_marker).x;
|
|
|
|
|
|
@@ -7729,7 +7737,28 @@ ImGuiTabItem* ImGui::TabBarFindTabByID(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
|
return NULL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
-// The *TabId fields be already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
|
|
|
|
|
|
+// Order = visible order, not submission order! (which is tab->BeginOrder)
|
|
|
|
+ImGuiTabItem* ImGui::TabBarFindTabByOrder(ImGuiTabBar* tab_bar, int order)
|
|
|
|
+{
|
|
|
|
+ if (order < 0 || order >= tab_bar->Tabs.Size)
|
|
|
|
+ return NULL;
|
|
|
|
+ return &tab_bar->Tabs[order];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+ImGuiTabItem* ImGui::TabBarGetCurrentTab(ImGuiTabBar* tab_bar)
|
|
|
|
+{
|
|
|
|
+ if (tab_bar->LastTabItemIdx <= 0 || tab_bar->LastTabItemIdx >= tab_bar->Tabs.Size)
|
|
|
|
+ return NULL;
|
|
|
|
+ return &tab_bar->Tabs[tab_bar->LastTabItemIdx];
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+const char* ImGui::TabBarGetTabName(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
|
|
|
+{
|
|
|
|
+ IM_ASSERT(tab->NameOffset != -1 && tab->NameOffset < tab_bar->TabsNames.Buf.Size);
|
|
|
|
+ return tab_bar->TabsNames.Buf.Data + tab->NameOffset;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+// The *TabId fields are already set by the docking system _before_ the actual TabItem was created, so we clear them regardless.
|
|
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
|
void ImGui::TabBarRemoveTab(ImGuiTabBar* tab_bar, ImGuiID tab_id)
|
|
{
|
|
{
|
|
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
|
|
if (ImGuiTabItem* tab = TabBarFindTabByID(tab_bar, tab_id))
|
|
@@ -7760,7 +7789,7 @@ void ImGui::TabBarCloseTab(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
|
{
|
|
{
|
|
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
|
|
// Actually select before expecting closure attempt (on an UnsavedDocument tab user is expect to e.g. show a popup)
|
|
if (tab_bar->VisibleTabId != tab->ID)
|
|
if (tab_bar->VisibleTabId != tab->ID)
|
|
- tab_bar->NextSelectedTabId = tab->ID;
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -7781,7 +7810,7 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
|
|
|
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
|
|
float margin = g.FontSize * 1.0f; // When to scroll to make Tab N+1 visible always make a bit of N visible to suggest more scrolling area (since we don't have a scrollbar)
|
|
- int order = tab_bar->GetTabOrder(tab);
|
|
|
|
|
|
+ int order = TabBarGetTabOrder(tab_bar, tab);
|
|
|
|
|
|
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
|
// Scrolling happens only in the central section (leading/trailing sections are not scrolling)
|
|
// FIXME: This is all confusing.
|
|
// FIXME: This is all confusing.
|
|
@@ -7805,7 +7834,12 @@ static void ImGui::TabBarScrollToTab(ImGuiTabBar* tab_bar, ImGuiID tab_id, ImGui
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, int offset)
|
|
|
|
|
|
+void ImGui::TabBarQueueFocus(ImGuiTabBar* tab_bar, ImGuiTabItem* tab)
|
|
|
|
+{
|
|
|
|
+ tab_bar->NextSelectedTabId = tab->ID;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, int offset)
|
|
{
|
|
{
|
|
IM_ASSERT(offset != 0);
|
|
IM_ASSERT(offset != 0);
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
@@ -7813,7 +7847,7 @@ void ImGui::TabBarQueueReorder(ImGuiTabBar* tab_bar, const ImGuiTabItem* tab, in
|
|
tab_bar->ReorderRequestOffset = (ImS16)offset;
|
|
tab_bar->ReorderRequestOffset = (ImS16)offset;
|
|
}
|
|
}
|
|
|
|
|
|
-void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, const ImGuiTabItem* src_tab, ImVec2 mouse_pos)
|
|
|
|
|
|
+void ImGui::TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* src_tab, ImVec2 mouse_pos)
|
|
{
|
|
{
|
|
ImGuiContext& g = *GImGui;
|
|
ImGuiContext& g = *GImGui;
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
IM_ASSERT(tab_bar->ReorderRequestTabId == 0);
|
|
@@ -7856,7 +7890,7 @@ bool ImGui::TabBarProcessReorder(ImGuiTabBar* tab_bar)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
|
//IM_ASSERT(tab_bar->Flags & ImGuiTabBarFlags_Reorderable); // <- this may happen when using debug tools
|
|
- int tab2_order = tab_bar->GetTabOrder(tab1) + tab_bar->ReorderRequestOffset;
|
|
|
|
|
|
+ int tab2_order = TabBarGetTabOrder(tab_bar, tab1) + tab_bar->ReorderRequestOffset;
|
|
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
|
if (tab2_order < 0 || tab2_order >= tab_bar->Tabs.Size)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
@@ -7916,7 +7950,7 @@ static ImGuiTabItem* ImGui::TabBarScrollingButtons(ImGuiTabBar* tab_bar)
|
|
if (select_dir != 0)
|
|
if (select_dir != 0)
|
|
if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
|
|
if (ImGuiTabItem* tab_item = TabBarFindTabByID(tab_bar, tab_bar->SelectedTabId))
|
|
{
|
|
{
|
|
- int selected_order = tab_bar->GetTabOrder(tab_item);
|
|
|
|
|
|
+ int selected_order = TabBarGetTabOrder(tab_bar, tab_item);
|
|
int target_order = selected_order + select_dir;
|
|
int target_order = selected_order + select_dir;
|
|
|
|
|
|
// Skip tab item buttons until another tab item is found or end is reached
|
|
// Skip tab item buttons until another tab item is found or end is reached
|
|
@@ -7968,7 +8002,7 @@ static ImGuiTabItem* ImGui::TabBarTabListPopupButton(ImGuiTabBar* tab_bar)
|
|
if (tab->Flags & ImGuiTabItemFlags_Button)
|
|
if (tab->Flags & ImGuiTabItemFlags_Button)
|
|
continue;
|
|
continue;
|
|
|
|
|
|
- const char* tab_name = tab_bar->GetTabName(tab);
|
|
|
|
|
|
+ const char* tab_name = TabBarGetTabName(tab_bar, tab);
|
|
if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
|
|
if (Selectable(tab_name, tab_bar->SelectedTabId == tab->ID))
|
|
tab_to_select = tab;
|
|
tab_to_select = tab;
|
|
}
|
|
}
|
|
@@ -8132,9 +8166,9 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|
{
|
|
{
|
|
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
|
|
if (tab_appearing && (tab_bar->Flags & ImGuiTabBarFlags_AutoSelectNewTabs) && tab_bar->NextSelectedTabId == 0)
|
|
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
|
|
if (!tab_bar_appearing || tab_bar->SelectedTabId == 0)
|
|
- tab_bar->NextSelectedTabId = id; // New tabs gets activated
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab); // New tabs gets activated
|
|
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
|
|
if ((flags & ImGuiTabItemFlags_SetSelected) && (tab_bar->SelectedTabId != id)) // _SetSelected can only be passed on explicit tab bar
|
|
- tab_bar->NextSelectedTabId = id;
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
}
|
|
}
|
|
|
|
|
|
// Lock visibility
|
|
// Lock visibility
|
|
@@ -8198,7 +8232,7 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
|
|
bool hovered, held;
|
|
bool hovered, held;
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
|
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
|
|
if (pressed && !is_tab_button)
|
|
if (pressed && !is_tab_button)
|
|
- tab_bar->NextSelectedTabId = id;
|
|
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
|
|
|
|
// Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
|
|
// Allow the close button to overlap unless we are dragging (in which case we don't want any overlapping tabs to be hovered)
|
|
if (g.ActiveId != id)
|
|
if (g.ActiveId != id)
|
|
@@ -8239,9 +8273,8 @@ 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.
|
|
// 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);
|
|
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
|
|
- if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)))
|
|
|
|
- if (!is_tab_button)
|
|
|
|
- tab_bar->NextSelectedTabId = id;
|
|
|
|
|
|
+ if (hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button)
|
|
|
|
+ TabBarQueueFocus(tab_bar, tab);
|
|
|
|
|
|
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
|
|
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
|
|
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
|
|
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
|