Skip to content

Commit 9c4948a

Browse files
committed
TabBar: Internals: added TabItemSpacing(). (ocornut#8349, ocornut#3291)
1 parent a05d547 commit 9c4948a

File tree

2 files changed

+74
-47
lines changed

2 files changed

+74
-47
lines changed

imgui_internal.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2612,6 +2612,8 @@ enum ImGuiTabItemFlagsPrivate_
26122612
ImGuiTabItemFlags_SectionMask_ = ImGuiTabItemFlags_Leading | ImGuiTabItemFlags_Trailing,
26132613
ImGuiTabItemFlags_NoCloseButton = 1 << 20, // Track whether p_open was set or not (we'll need this info on the next frame to recompute ContentWidth during layout)
26142614
ImGuiTabItemFlags_Button = 1 << 21, // Used by TabItemButton, change the tab item behavior to mimic a button
2615+
ImGuiTabItemFlags_Invisible = 1 << 22, // To reserve space e.g. with ImGuiTabItemFlags_Leading
2616+
//ImGuiTabItemFlags_Unsorted = 1 << 23, // [Docking] Trailing tabs with the _Unsorted flag will be sorted based on the DockOrder of their Window.
26152617
};
26162618

26172619
// Storage for one active tab item (sizeof() 40 bytes)
@@ -3378,6 +3380,7 @@ namespace ImGui
33783380
IMGUI_API void TabBarQueueReorderFromMousePos(ImGuiTabBar* tab_bar, ImGuiTabItem* tab, ImVec2 mouse_pos);
33793381
IMGUI_API bool TabBarProcessReorder(ImGuiTabBar* tab_bar);
33803382
IMGUI_API bool TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window);
3383+
IMGUI_API void TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float width);
33813384
IMGUI_API ImVec2 TabItemCalcSize(const char* label, bool has_close_button_or_unsaved_marker);
33823385
IMGUI_API ImVec2 TabItemCalcSize(ImGuiWindow* window);
33833386
IMGUI_API void TabItemBackground(ImDrawList* draw_list, const ImRect& bb, ImGuiTabItemFlags flags, ImU32 col);

imgui_widgets.cpp

Lines changed: 71 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -9925,7 +9925,7 @@ bool ImGui::BeginTabItem(const char* label, bool* p_open, ImGuiTabItemFlags f
99259925
IM_ASSERT_USER_ERROR(tab_bar, "Needs to be called between BeginTabBar() and EndTabBar()!");
99269926
return false;
99279927
}
9928-
IM_ASSERT(!(flags & ImGuiTabItemFlags_Button)); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead!
9928+
IM_ASSERT((flags & ImGuiTabItemFlags_Button) == 0); // BeginTabItem() Can't be used with button flags, use TabItemButton() instead!
99299929

99309930
bool ret = TabItemEx(tab_bar, label, p_open, flags, NULL);
99319931
if (ret && !(flags & ImGuiTabItemFlags_NoPushId))
@@ -9971,6 +9971,23 @@ bool ImGui::TabItemButton(const char* label, ImGuiTabItemFlags flags)
99719971
return TabItemEx(tab_bar, label, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder, NULL);
99729972
}
99739973

9974+
void ImGui::TabItemSpacing(const char* str_id, ImGuiTabItemFlags flags, float width)
9975+
{
9976+
ImGuiContext& g = *GImGui;
9977+
ImGuiWindow* window = g.CurrentWindow;
9978+
if (window->SkipItems)
9979+
return;
9980+
9981+
ImGuiTabBar* tab_bar = g.CurrentTabBar;
9982+
if (tab_bar == NULL)
9983+
{
9984+
IM_ASSERT_USER_ERROR(tab_bar != NULL, "Needs to be called between BeginTabBar() and EndTabBar()!");
9985+
return;
9986+
}
9987+
SetNextItemWidth(width);
9988+
TabItemEx(tab_bar, str_id, NULL, flags | ImGuiTabItemFlags_Button | ImGuiTabItemFlags_NoReorder | ImGuiTabItemFlags_Invisible, NULL);
9989+
}
9990+
99749991
bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open, ImGuiTabItemFlags flags, ImGuiWindow* docked_window)
99759992
{
99769993
// Layout whole tab bar if not already done
@@ -10116,8 +10133,11 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
1011610133
ImGuiButtonFlags button_flags = ((is_tab_button ? ImGuiButtonFlags_PressedOnClickRelease : ImGuiButtonFlags_PressedOnClick) | ImGuiButtonFlags_AllowOverlap);
1011710134
if (g.DragDropActive)
1011810135
button_flags |= ImGuiButtonFlags_PressedOnDragDropHold;
10119-
bool hovered, held;
10120-
bool pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
10136+
bool hovered, held, pressed;
10137+
if (flags & ImGuiTabItemFlags_Invisible)
10138+
hovered = held = pressed = false;
10139+
else
10140+
pressed = ButtonBehavior(bb, id, &hovered, &held, button_flags);
1012110141
if (pressed && !is_tab_button)
1012210142
TabBarQueueFocus(tab_bar, tab);
1012310143

@@ -10149,62 +10169,66 @@ bool ImGui::TabItemEx(ImGuiTabBar* tab_bar, const char* label, bool* p_open,
1014910169
#endif
1015010170

1015110171
// Render tab shape
10152-
ImDrawList* display_draw_list = window->DrawList;
10153-
const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabDimmed));
10154-
TabItemBackground(display_draw_list, bb, flags, tab_col);
10155-
if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f)
10156-
{
10157-
// Might be moved to TabItemBackground() ?
10158-
ImVec2 tl = bb.GetTL() + ImVec2(0, 1.0f * g.CurrentDpiScale);
10159-
ImVec2 tr = bb.GetTR() + ImVec2(0, 1.0f * g.CurrentDpiScale);
10160-
ImU32 overline_col = GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline);
10161-
if (style.TabRounding > 0.0f)
10162-
{
10163-
float rounding = style.TabRounding;
10164-
display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9);
10165-
display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11);
10166-
display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize);
10167-
}
10168-
else
10172+
const bool is_visible = (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) && !(flags & ImGuiTabItemFlags_Invisible);
10173+
if (is_visible)
10174+
{
10175+
ImDrawList* display_draw_list = window->DrawList;
10176+
const ImU32 tab_col = GetColorU32((held || hovered) ? ImGuiCol_TabHovered : tab_contents_visible ? (tab_bar_focused ? ImGuiCol_TabSelected : ImGuiCol_TabDimmedSelected) : (tab_bar_focused ? ImGuiCol_Tab : ImGuiCol_TabDimmed));
10177+
TabItemBackground(display_draw_list, bb, flags, tab_col);
10178+
if (tab_contents_visible && (tab_bar->Flags & ImGuiTabBarFlags_DrawSelectedOverline) && style.TabBarOverlineSize > 0.0f)
1016910179
{
10170-
display_draw_list->AddLine(tl - ImVec2(0.5f, 0.5f), tr - ImVec2(0.5f, 0.5f), overline_col, style.TabBarOverlineSize);
10180+
// Might be moved to TabItemBackground() ?
10181+
ImVec2 tl = bb.GetTL() + ImVec2(0, 1.0f * g.CurrentDpiScale);
10182+
ImVec2 tr = bb.GetTR() + ImVec2(0, 1.0f * g.CurrentDpiScale);
10183+
ImU32 overline_col = GetColorU32(tab_bar_focused ? ImGuiCol_TabSelectedOverline : ImGuiCol_TabDimmedSelectedOverline);
10184+
if (style.TabRounding > 0.0f)
10185+
{
10186+
float rounding = style.TabRounding;
10187+
display_draw_list->PathArcToFast(tl + ImVec2(+rounding, +rounding), rounding, 7, 9);
10188+
display_draw_list->PathArcToFast(tr + ImVec2(-rounding, +rounding), rounding, 9, 11);
10189+
display_draw_list->PathStroke(overline_col, 0, style.TabBarOverlineSize);
10190+
}
10191+
else
10192+
{
10193+
display_draw_list->AddLine(tl - ImVec2(0.5f, 0.5f), tr - ImVec2(0.5f, 0.5f), overline_col, style.TabBarOverlineSize);
10194+
}
1017110195
}
10172-
}
10173-
RenderNavCursor(bb, id);
10196+
RenderNavCursor(bb, id);
1017410197

10175-
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
10176-
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
10177-
if (tab_bar->SelectedTabId != tab->ID && hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button)
10178-
TabBarQueueFocus(tab_bar, tab);
10198+
// Select with right mouse button. This is so the common idiom for context menu automatically highlight the current widget.
10199+
const bool hovered_unblocked = IsItemHovered(ImGuiHoveredFlags_AllowWhenBlockedByPopup);
10200+
if (tab_bar->SelectedTabId != tab->ID && hovered_unblocked && (IsMouseClicked(1) || IsMouseReleased(1)) && !is_tab_button)
10201+
TabBarQueueFocus(tab_bar, tab);
1017910202

10180-
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
10181-
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
10203+
if (tab_bar->Flags & ImGuiTabBarFlags_NoCloseWithMiddleMouseButton)
10204+
flags |= ImGuiTabItemFlags_NoCloseWithMiddleMouseButton;
1018210205

10183-
// Render tab label, process close button
10184-
const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0;
10185-
bool just_closed;
10186-
bool text_clipped;
10187-
TabItemLabelAndCloseButton(display_draw_list, bb, tab_just_unsaved ? (flags & ~ImGuiTabItemFlags_UnsavedDocument) : flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped);
10188-
if (just_closed && p_open != NULL)
10189-
{
10190-
*p_open = false;
10191-
TabBarCloseTab(tab_bar, tab);
10206+
// Render tab label, process close button
10207+
const ImGuiID close_button_id = p_open ? GetIDWithSeed("#CLOSE", NULL, id) : 0;
10208+
bool just_closed;
10209+
bool text_clipped;
10210+
TabItemLabelAndCloseButton(display_draw_list, bb, tab_just_unsaved ? (flags & ~ImGuiTabItemFlags_UnsavedDocument) : flags, tab_bar->FramePadding, label, id, close_button_id, tab_contents_visible, &just_closed, &text_clipped);
10211+
if (just_closed && p_open != NULL)
10212+
{
10213+
*p_open = false;
10214+
TabBarCloseTab(tab_bar, tab);
10215+
}
10216+
10217+
// Tooltip
10218+
// (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok)
10219+
// (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores)
10220+
// FIXME: This is a mess.
10221+
// FIXME: We may want disabled tab to still display the tooltip?
10222+
if (text_clipped && g.HoveredId == id && !held)
10223+
if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
10224+
SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
1019210225
}
1019310226

1019410227
// Restore main window position so user can draw there
1019510228
if (want_clip_rect)
1019610229
PopClipRect();
1019710230
window->DC.CursorPos = backup_main_cursor_pos;
1019810231

10199-
// Tooltip
10200-
// (Won't work over the close button because ItemOverlap systems messes up with HoveredIdTimer-> seems ok)
10201-
// (We test IsItemHovered() to discard e.g. when another item is active or drag and drop over the tab bar, which g.HoveredId ignores)
10202-
// FIXME: This is a mess.
10203-
// FIXME: We may want disabled tab to still display the tooltip?
10204-
if (text_clipped && g.HoveredId == id && !held)
10205-
if (!(tab_bar->Flags & ImGuiTabBarFlags_NoTooltip) && !(tab->Flags & ImGuiTabItemFlags_NoTooltip))
10206-
SetItemTooltip("%.*s", (int)(FindRenderedTextEnd(label) - label), label);
10207-
1020810232
IM_ASSERT(!is_tab_button || !(tab_bar->SelectedTabId == tab->ID && is_tab_button)); // TabItemButton should not be selected
1020910233
if (is_tab_button)
1021010234
return pressed;

0 commit comments

Comments
 (0)