Imgui: Vertical text

Created on 18 Jun 2016  路  8Comments  路  Source: ocornut/imgui

I would like to use vertical tabs, similar to how blender ui does:

blender

Is there a way to render vertical text with imgui?

fontext

Most helpful comment

@guillaumechereau: good job :smiley: !

P.S. Your code is so compact that can be posted here:

#include <imgui_internal.h>
namespace ImGui {
    bool GoxTab(const char *text, bool *v)
    {
        ImFont *font = GImGui->Font;
        const ImFont::Glyph *glyph;
        char c;
        bool ret;
        ImGuiContext& g = *GImGui;
        const ImGuiStyle& style = g.Style;
        float pad = style.FramePadding.x;
        ImVec4 color;
        ImVec2 text_size = CalcTextSize(text);
        ImGuiWindow* window = GetCurrentWindow();
        ImVec2 pos = window->DC.CursorPos + ImVec2(pad, text_size.x + pad);

        const  ImU32 text_color = ImGui::ColorConvertFloat4ToU32(style.Colors[ImGuiCol_Text]);
        color = style.Colors[ImGuiCol_Button];
        if (*v) color = style.Colors[ImGuiCol_ButtonActive];
        ImGui::PushStyleColor(ImGuiCol_Button, color);
        ImGui::PushID(text);
        ret = ImGui::Button("", ImVec2(text_size.y + pad * 2,
                                       text_size.x + pad * 2));
        ImGui::PopStyleColor();
        while ((c = *text++)) {
            glyph = font->FindGlyph(c);
            if (!glyph) continue;

            window->DrawList->PrimReserve(6, 4);
            window->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->XAdvance;
        }
        ImGui::PopID();
        return ret;
}
} // namespace ImGui

I haven't tested it so far, but it seems very compact and useful.
Maybe it's good enough to be included in the original Dear ImGui ...

[Edit:] Added text_color from current style.

All 8 comments

Not at the moment, though you can use code based on ImFont::RenderChar() and render it yourself.
If you are going to create vertical tabs you'll need custom code anyway.

There was a request for rotated text which I always assumed was arbitrary-rotated text, but 90-degrees text is a little easier to handle.
https://github.com/ocornut/imgui/issues/422

This is exactly what I needed this feature for. (vertical tabs and maybe table headers)

@MrSmith33: I've just made a quick gist modifying the related ImDrawList methods to display vertical text. If you want you can use it as a starting point to build ImGui widgets on it (I'm not sure if I'll keep on developing it or not: I still have to understand if vertical text is useful for me or not...).

https://gist.github.com/Flix01/3e176c64540f51b99a4ec82cfaf759a5
imgui_vertical_text

I finally made a small custom tab widget for my program. It's actually quite easy to manage vertical tabs with the groupBegin and groupEnd functions:
tabs

The implementation code is here (GoxTab function):
https://github.com/guillaumechereau/goxel/blob/master/src/imgui_user.inl

@guillaumechereau: good job :smiley: !

P.S. Your code is so compact that can be posted here:

#include <imgui_internal.h>
namespace ImGui {
    bool GoxTab(const char *text, bool *v)
    {
        ImFont *font = GImGui->Font;
        const ImFont::Glyph *glyph;
        char c;
        bool ret;
        ImGuiContext& g = *GImGui;
        const ImGuiStyle& style = g.Style;
        float pad = style.FramePadding.x;
        ImVec4 color;
        ImVec2 text_size = CalcTextSize(text);
        ImGuiWindow* window = GetCurrentWindow();
        ImVec2 pos = window->DC.CursorPos + ImVec2(pad, text_size.x + pad);

        const  ImU32 text_color = ImGui::ColorConvertFloat4ToU32(style.Colors[ImGuiCol_Text]);
        color = style.Colors[ImGuiCol_Button];
        if (*v) color = style.Colors[ImGuiCol_ButtonActive];
        ImGui::PushStyleColor(ImGuiCol_Button, color);
        ImGui::PushID(text);
        ret = ImGui::Button("", ImVec2(text_size.y + pad * 2,
                                       text_size.x + pad * 2));
        ImGui::PopStyleColor();
        while ((c = *text++)) {
            glyph = font->FindGlyph(c);
            if (!glyph) continue;

            window->DrawList->PrimReserve(6, 4);
            window->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->XAdvance;
        }
        ImGui::PopID();
        return ret;
}
} // namespace ImGui

I haven't tested it so far, but it seems very compact and useful.
Maybe it's good enough to be included in the original Dear ImGui ...

[Edit:] Added text_color from current style.

Note that in my code the colour is fixed to white and the text scale is assumed to be equal to 1, a more generic version should get those values from the imgui context.

Note that in my code the colour is fixed to white.

I've just changed it in the snippet above.

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.

Also linking to #1286, #3032

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bogdaNNNN1 picture bogdaNNNN1  路  3Comments

bizehao picture bizehao  路  3Comments

mnemode2 picture mnemode2  路  3Comments

NPatch picture NPatch  路  3Comments

inflex picture inflex  路  3Comments