Skip to content

Instantly share code, notes, and snippets.

@petrihakkinen
Created June 7, 2024 13:53
Show Gist options
  • Save petrihakkinen/c2462974ad41f72a54d9aaf2d62b2536 to your computer and use it in GitHub Desktop.
Save petrihakkinen/c2462974ad41f72a54d9aaf2d62b2536 to your computer and use it in GitHub Desktop.
ImGui InputText with right aligned text (when text wider than widget)
bool InputTextRightAligned(const char* label, const char* text, size_t length, ImGuiInputTextFlags flags, ImGuiInputTextCallback pCallback, void* pUserData)
{
const ImGuiContext& g = *ImGui::GetCurrentContext();
const ImGuiStyle& style = ImGui::GetStyle();
ImGuiWindow& window = *ImGui::GetCurrentWindow();
ImGuiID id = window.GetID(label);
bool active = g.ActiveId == id;
ImVec2 labelSize = ImGui::CalcTextSize(label, nullptr, true);
ImVec2 frameSize = ImGui::CalcItemSize(ImVec2(0, 0), CalcItemWidth(), labelSize.y + style.FramePadding.y * 2.0f);
ImRect frame(window.DC.CursorPos, window.DC.CursorPos + frameSize);
ImVec2 textPos = frame.Min + style.FramePadding; // left aligned
// right align text
ImVec2 textSize = ImGui::CalcTextSize(text);
textPos.x = std::min(frame.Max.x - style.FramePadding.x - textSize.x, textPos.x);
bool modified = ImGui::InputText(label, text, length, flags, pCallback, pUserData);
// overdraw text with right aligned text when widget not active
if(!active)
{
ImDrawList& drawList = *ImGui::GetWindowDrawList();
ImVec4 clipRect(frame.Min.x, frame.Min.y, frame.Max.x, frame.Max.y);
drawList.AddRectFilled(frame.Min, frame.Max, ImColor(style.Colors[ImGuiCol_FrameBg]));
drawList.AddText(nullptr, 0.0f, textPos, ImColor(ImGui::GetStyle().Colors[ImGuiCol_Text]), text, nullptr, 0.0f, &clipRect);
}
// fix cursor position and scrolling when the widget becomes active
if(!active && ImGui::IsItemActive())
{
ImGuiInputTextState* state = ImGui::GetInputTextState(id);
if(state)
{
const ImGuiIO& io = ImGui::GetIO();
float cursorOffsetX = io.MousePos.x - textPos.x;
int cursor = 0;
int length = strlen(text);
while(cursor < length)
{
if(ImGui::CalcTextSize(text, text + cursor + 1).x > cursorOffsetX)
break;
cursor++;
}
state->Stb.cursor = cursor;
state->Stb.select_start = cursor;
state->Stb.select_end = cursor;
state->ScrollX = std::max(frame.Min.x + style.FramePadding.x - textPos.x, 0.0f);
}
}
return modified;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment