Vertical Tab
How can we implement vertical tab? Blender's panel looks great (please see the icon tabs on the very left) -

Current tab bar implementation does not support vertical tabs. It is possible to implement this, but you would have to do it manually, using BeginChild()/EndChild(), Button() and ImDrawList for rendering of custom shapes.
- Render a dark rect as a background for tab selector buttons.
- Render all buttons in a column using
SetCursorPos() - Render a child with contents of selected tab on the right.
This is overly simplified list, but you should get the general idea.
As Rokas mentioned you can reimplement a simplified version of a vertical tab yourself. In particular the style you showed in that picture, using icon, is also much easier to implement manually than "rotated tabs":

Either way it be nice if this was also supported vertical tab bars. I didn't implement vertical tabs yet, one of the reason being that I was expecting to use rotated text which we don't have yet (aiming for a text refactor in the upcoming semester).
We could imagine that the BeginTabBar() api could allow two distinct options for vertical tabs: rotated tabs with rotated text, and stacked tabs with fixed-width text like in your picture.
FYI (copied from #705)
The code in #3067 has another function to draw 90 rotated text: https://github.com/mahilab/mahi-gui/blob/master/src/Mahi/Gui/imgui_plot.cpp
/// Draws vertical text. The position is the bottom left of the text rect.
inline void AddTextVertical(ImDrawList* DrawList, const char *text, ImVec2 pos, ImU32 text_color) {
pos.x = IM_ROUND(pos.x);
pos.y = IM_ROUND(pos.y);
ImFont *font = GImGui->Font;
const ImFontGlyph *glyph;
char c;
ImGuiContext& g = *GImGui;
ImVec2 text_size = CalcTextSize(text);
while ((c = *text++)) {
glyph = font->FindGlyph(c);
if (!glyph) continue;
DrawList->PrimReserve(6, 4);
DrawList->PrimQuadUV(
pos + ImVec2(glyph->Y0, -glyph->X0),
pos + ImVec2(glyph->Y0, -glyph->X1),
pos + ImVec2(glyph->Y1, -glyph->X1),
pos + ImVec2(glyph->Y1, -glyph->X0),
ImVec2(glyph->U0, glyph->V0),
ImVec2(glyph->U1, glyph->V0),
ImVec2(glyph->U1, glyph->V1),
ImVec2(glyph->U0, glyph->V1),
text_color);
pos.y -= glyph->AdvanceX;
}
}
If you don't need clipping, wrapping etc. it's fairly easy to write it. We will aim to support full-featured rotated text in a new low-level text rendering API this year.
(After you made this post I started trying to implement vertical tab and ended up with the conclusion that it would be more natural to implement once we finish work on the WorkRect system to "claim" space from any direction, instead of the current top-to-bottom focused system.)
We will aim to support full-featured rotated text in a new low-level text rendering API this year.
Is there any progress?
I also need this
I was able to replicate this with a child with table with 1 column for the buttons, and a child window for the tab content next to it, which looks like this:
I use Java bindings for ImGui, here's the Kotlin code:
fun show() = ImGuiExt.groupWithoutSpacing {
if (ImGui.beginChild("TabButtons", 40F, 0F, false, WINDOW_UNDECORATED or ImGuiWindowFlags.NoBackground)) {
ImGui.sameLine(8F)
val tabCount = 5
if (ImGui.beginTable("TabButtonsTable", 1, ImGuiTableFlags.None, 32F, 32F)) {
repeat(tabCount) {
ImGui.tableNextRow()
ImGui.tableNextColumn()
ImGui.pushID("EditorTab$it")
val selected = selectedTab == it
if (selected) {
ImGui.pushStyleColor(ImGuiCol.Button, buttonActiveBackground)
ImGui.pushStyleColor(ImGuiCol.Border, buttonActiveBorderColor)
} else {
ImGui.pushStyleColor(ImGuiCol.Button, buttonBackground)
ImGui.pushStyleColor(ImGuiCol.Border, buttonBorderColor)
}
ImGui.pushStyleVar(ImGuiStyleVar.FrameBorderSize, 2F)
if (ImGui.button("Tab 1", 32F, 32F)) {
selectedTab = it
}
ImGui.popStyleVar()
ImGui.popStyleColor(2)
ImGui.popID()
}
ImGui.endTable()
}
ImGui.endChild()
}
ImGui.sameLine()
ImGuiExt.groupWithSpacing {
ImGui.pushStyleColor(ImGuiCol.ChildBg, tabContentBackgroundColor)
ImGui.pushStyleColor(ImGuiCol.Border, tabContentBackgroundColor)
if (ImGui.beginChild("TabContent", WIDTH - 40F, 0F, true, WINDOW_UNDECORATED)) {
ImGui.popStyleColor(2)
when (selectedTab) {
0 -> {
MapTilePropertyTable.show()
}
1 -> {
ImGui.text("Tab 2")
}
}
ImGui.endChild()
}
}
}
Some of my extension functions :)
fun groupWithSpacing(x: Float = 8F, y: Float = 4F, block: () -> Unit) {
ImGui.pushStyleVar(ImGuiStyleVar.ItemSpacing, x, y)
ImGui.beginGroup()
block()
ImGui.popStyleVar()
ImGui.endGroup()
}
fun groupWithoutSpacing(block: () -> Unit) {
ImGui.pushStyleVar(ImGuiStyleVar.ItemSpacing, 0F, 0F)
ImGui.beginGroup()
block()
ImGui.popStyleVar()
ImGui.endGroup()
}