InputTextMultiline with line numbers code example
Example: code for a text box in imgui
#define MAX(a, b) (((a) < (b)) ? (b) : (a))
#define INTERNAL static
struct MultilineScrollState
{
// Input.
float scrollRegionX;
float scrollX;
ImGuiStorage *storage;
// Output.
bool newScrollPositionAvailable;
float newScrollX;
};
INTERNAL int MultilineScrollCallback(ImGuiTextEditCallbackData *data)
{
MultilineScrollState *scrollState = (MultilineScrollState *)data->UserData;
ImGuiID cursorId = ImGui::GetID("cursor");
int oldCursorIndex = scrollState->storage->GetInt(cursorId, 0);
if (oldCursorIndex != data->CursorPos)
{
int begin = data->CursorPos;
while ((begin > 0) && (data->Buf[begin - 1] != '\n'))
{
--begin;
}
float cursorOffset = ImGui::CalcTextSize(data->Buf + begin, data->Buf + data->CursorPos).x;
float SCROLL_INCREMENT = scrollState->scrollRegionX * 0.25f;
if (cursorOffset < scrollState->scrollX)
{
scrollState->newScrollPositionAvailable = true;
scrollState->newScrollX = MAX(0.0f, cursorOffset - SCROLL_INCREMENT);
}
else if ((cursorOffset - scrollState->scrollRegionX) >= scrollState->scrollX)
{
scrollState->newScrollPositionAvailable = true;
scrollState->newScrollX = cursorOffset - scrollState->scrollRegionX + SCROLL_INCREMENT;
}
}
scrollState->storage->SetInt(cursorId, data->CursorPos);
return 0;
}
INTERNAL bool ImGuiInputTextMultiline(const char* label, char* buf, size_t buf_size, float height, ImGuiInputTextFlags flags = 0)
{
float scrollbarSize = ImGui::GetStyle().ScrollbarSize;
float labelWidth = ImGui::CalcTextSize(label).x + scrollbarSize;
float SCROLL_WIDTH = 2000.0f; // Very large scrolling width to allow for very long lines.
MultilineScrollState scrollState = {};
// Set up child region for horizontal scrolling of the text box.
ImGui::BeginChild(label, ImVec2(-labelWidth, height), false, ImGuiWindowFlags_HorizontalScrollbar);
scrollState.scrollRegionX = MAX(0.0f, ImGui::GetWindowWidth() - scrollbarSize);
scrollState.scrollX = ImGui::GetScrollX();
scrollState.storage = ImGui::GetStateStorage();
bool changed = ImGui::InputTextMultiline(label, buf, buf_size, ImVec2(SCROLL_WIDTH, MAX(0.0f, height - scrollbarSize)),
flags | ImGuiInputTextFlags_CallbackAlways, MultilineScrollCallback, &scrollState);
if (scrollState.newScrollPositionAvailable)
{
ImGui::SetScrollX(scrollState.newScrollX);
}
ImGui::EndChild();
ImGui::SameLine();
ImGui::Text(label);
return changed;
}