mirror of
https://github.com/ocornut/imgui.git
synced 2024-11-24 05:19:02 +08:00
Refactor: Moved Text functions from imgui.cpp to imgui_widgets.cpp (#2036)
This commit is contained in:
parent
52c115fb2c
commit
3eaa063984
238
imgui.cpp
238
imgui.cpp
@ -7871,177 +7871,6 @@ ImGuiStorage* ImGui::GetStateStorage()
|
||||
return window->DC.StateStorage;
|
||||
}
|
||||
|
||||
void ImGui::TextV(const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
TextUnformatted(g.TempBuffer, text_end);
|
||||
}
|
||||
|
||||
void ImGui::Text(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_Text, col);
|
||||
TextV(fmt, args);
|
||||
PopStyleColor();
|
||||
}
|
||||
|
||||
void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextColoredV(col, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextDisabledV(const char* fmt, va_list args)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]);
|
||||
TextV(fmt, args);
|
||||
PopStyleColor();
|
||||
}
|
||||
|
||||
void ImGui::TextDisabled(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextDisabledV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextWrappedV(const char* fmt, va_list args)
|
||||
{
|
||||
bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position is one ia already set
|
||||
if (need_wrap) PushTextWrapPos(0.0f);
|
||||
TextV(fmt, args);
|
||||
if (need_wrap) PopTextWrapPos();
|
||||
}
|
||||
|
||||
void ImGui::TextWrapped(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextWrappedV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextUnformatted(const char* text, const char* text_end)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(text != NULL);
|
||||
const char* text_begin = text;
|
||||
if (text_end == NULL)
|
||||
text_end = text + strlen(text); // FIXME-OPT
|
||||
|
||||
const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
|
||||
const float wrap_pos_x = window->DC.TextWrapPos;
|
||||
const bool wrap_enabled = wrap_pos_x >= 0.0f;
|
||||
if (text_end - text > 2000 && !wrap_enabled)
|
||||
{
|
||||
// Long text!
|
||||
// Perform manual coarse clipping to optimize for long multi-line text
|
||||
// From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
|
||||
// We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
|
||||
const char* line = text;
|
||||
const float line_height = GetTextLineHeight();
|
||||
const ImRect clip_rect = window->ClipRect;
|
||||
ImVec2 text_size(0,0);
|
||||
|
||||
if (text_pos.y <= clip_rect.Max.y)
|
||||
{
|
||||
ImVec2 pos = text_pos;
|
||||
|
||||
// Lines to skip (can't skip when logging text)
|
||||
if (!g.LogEnabled)
|
||||
{
|
||||
int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
|
||||
if (lines_skippable > 0)
|
||||
{
|
||||
int lines_skipped = 0;
|
||||
while (line < text_end && lines_skipped < lines_skippable)
|
||||
{
|
||||
const char* line_end = strchr(line, '\n');
|
||||
if (!line_end)
|
||||
line_end = text_end;
|
||||
line = line_end + 1;
|
||||
lines_skipped++;
|
||||
}
|
||||
pos.y += lines_skipped * line_height;
|
||||
}
|
||||
}
|
||||
|
||||
// Lines to render
|
||||
if (line < text_end)
|
||||
{
|
||||
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
|
||||
while (line < text_end)
|
||||
{
|
||||
const char* line_end = strchr(line, '\n');
|
||||
if (IsClippedEx(line_rect, 0, false))
|
||||
break;
|
||||
|
||||
const ImVec2 line_size = CalcTextSize(line, line_end, false);
|
||||
text_size.x = ImMax(text_size.x, line_size.x);
|
||||
RenderText(pos, line, line_end, false);
|
||||
if (!line_end)
|
||||
line_end = text_end;
|
||||
line = line_end + 1;
|
||||
line_rect.Min.y += line_height;
|
||||
line_rect.Max.y += line_height;
|
||||
pos.y += line_height;
|
||||
}
|
||||
|
||||
// Count remaining lines
|
||||
int lines_skipped = 0;
|
||||
while (line < text_end)
|
||||
{
|
||||
const char* line_end = strchr(line, '\n');
|
||||
if (!line_end)
|
||||
line_end = text_end;
|
||||
line = line_end + 1;
|
||||
lines_skipped++;
|
||||
}
|
||||
pos.y += lines_skipped * line_height;
|
||||
}
|
||||
|
||||
text_size.y += (pos - text_pos).y;
|
||||
}
|
||||
|
||||
ImRect bb(text_pos, text_pos + text_size);
|
||||
ItemSize(bb);
|
||||
ItemAdd(bb, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
|
||||
const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
|
||||
|
||||
// Account of baseline offset
|
||||
ImRect bb(text_pos, text_pos + text_size);
|
||||
ItemSize(text_size);
|
||||
if (!ItemAdd(bb, 0))
|
||||
return;
|
||||
|
||||
// Render (we don't hide text after ## in this end-user function)
|
||||
RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::AlignTextToFramePadding()
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
@ -8053,40 +7882,6 @@ void ImGui::AlignTextToFramePadding()
|
||||
window->DC.CurrentLineTextBaseOffset = ImMax(window->DC.CurrentLineTextBaseOffset, g.Style.FramePadding.y);
|
||||
}
|
||||
|
||||
// Add a label+text combo aligned to other label+value widgets
|
||||
void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const float w = CalcItemWidth();
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
|
||||
const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, 0))
|
||||
return;
|
||||
|
||||
// Render
|
||||
const char* value_text_begin = &g.TempBuffer[0];
|
||||
const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
|
||||
}
|
||||
|
||||
void ImGui::LabelText(const char* label, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LabelTextV(label, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
bool ImGui::ButtonBehavior(const ImRect& bb, ImGuiID id, bool* out_hovered, bool* out_held, ImGuiButtonFlags flags)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
@ -8979,39 +8774,6 @@ void ImGui::Bullet()
|
||||
SameLine(0, style.FramePadding.x*2);
|
||||
}
|
||||
|
||||
// Text with a little bullet aligned to the typical tree node.
|
||||
void ImGui::BulletTextV(const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
const char* text_begin = g.TempBuffer;
|
||||
const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
|
||||
const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
|
||||
const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding
|
||||
ItemSize(bb);
|
||||
if (!ItemAdd(bb, 0))
|
||||
return;
|
||||
|
||||
// Render
|
||||
RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
|
||||
RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
|
||||
}
|
||||
|
||||
void ImGui::BulletText(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
BulletTextV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
static inline int DataTypeFormatString(char* buf, int buf_size, ImGuiDataType data_type, const void* data_ptr, const char* format)
|
||||
{
|
||||
if (data_type == ImGuiDataType_S32 || data_type == ImGuiDataType_U32) // Signedness doesn't matter when pushing the argument
|
||||
|
@ -55,6 +55,243 @@
|
||||
// - BulletTextV()
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
void ImGui::TextUnformatted(const char* text, const char* text_end)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
IM_ASSERT(text != NULL);
|
||||
const char* text_begin = text;
|
||||
if (text_end == NULL)
|
||||
text_end = text + strlen(text); // FIXME-OPT
|
||||
|
||||
const ImVec2 text_pos(window->DC.CursorPos.x, window->DC.CursorPos.y + window->DC.CurrentLineTextBaseOffset);
|
||||
const float wrap_pos_x = window->DC.TextWrapPos;
|
||||
const bool wrap_enabled = wrap_pos_x >= 0.0f;
|
||||
if (text_end - text > 2000 && !wrap_enabled)
|
||||
{
|
||||
// Long text!
|
||||
// Perform manual coarse clipping to optimize for long multi-line text
|
||||
// From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
|
||||
// We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
|
||||
const char* line = text;
|
||||
const float line_height = GetTextLineHeight();
|
||||
const ImRect clip_rect = window->ClipRect;
|
||||
ImVec2 text_size(0,0);
|
||||
|
||||
if (text_pos.y <= clip_rect.Max.y)
|
||||
{
|
||||
ImVec2 pos = text_pos;
|
||||
|
||||
// Lines to skip (can't skip when logging text)
|
||||
if (!g.LogEnabled)
|
||||
{
|
||||
int lines_skippable = (int)((clip_rect.Min.y - text_pos.y) / line_height);
|
||||
if (lines_skippable > 0)
|
||||
{
|
||||
int lines_skipped = 0;
|
||||
while (line < text_end && lines_skipped < lines_skippable)
|
||||
{
|
||||
const char* line_end = strchr(line, '\n');
|
||||
if (!line_end)
|
||||
line_end = text_end;
|
||||
line = line_end + 1;
|
||||
lines_skipped++;
|
||||
}
|
||||
pos.y += lines_skipped * line_height;
|
||||
}
|
||||
}
|
||||
|
||||
// Lines to render
|
||||
if (line < text_end)
|
||||
{
|
||||
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
|
||||
while (line < text_end)
|
||||
{
|
||||
const char* line_end = strchr(line, '\n');
|
||||
if (IsClippedEx(line_rect, 0, false))
|
||||
break;
|
||||
|
||||
const ImVec2 line_size = CalcTextSize(line, line_end, false);
|
||||
text_size.x = ImMax(text_size.x, line_size.x);
|
||||
RenderText(pos, line, line_end, false);
|
||||
if (!line_end)
|
||||
line_end = text_end;
|
||||
line = line_end + 1;
|
||||
line_rect.Min.y += line_height;
|
||||
line_rect.Max.y += line_height;
|
||||
pos.y += line_height;
|
||||
}
|
||||
|
||||
// Count remaining lines
|
||||
int lines_skipped = 0;
|
||||
while (line < text_end)
|
||||
{
|
||||
const char* line_end = strchr(line, '\n');
|
||||
if (!line_end)
|
||||
line_end = text_end;
|
||||
line = line_end + 1;
|
||||
lines_skipped++;
|
||||
}
|
||||
pos.y += lines_skipped * line_height;
|
||||
}
|
||||
|
||||
text_size.y += (pos - text_pos).y;
|
||||
}
|
||||
|
||||
ImRect bb(text_pos, text_pos + text_size);
|
||||
ItemSize(bb);
|
||||
ItemAdd(bb, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
const float wrap_width = wrap_enabled ? CalcWrapWidthForPos(window->DC.CursorPos, wrap_pos_x) : 0.0f;
|
||||
const ImVec2 text_size = CalcTextSize(text_begin, text_end, false, wrap_width);
|
||||
|
||||
// Account of baseline offset
|
||||
ImRect bb(text_pos, text_pos + text_size);
|
||||
ItemSize(text_size);
|
||||
if (!ItemAdd(bb, 0))
|
||||
return;
|
||||
|
||||
// Render (we don't hide text after ## in this end-user function)
|
||||
RenderTextWrapped(bb.Min, text_begin, text_end, wrap_width);
|
||||
}
|
||||
}
|
||||
|
||||
void ImGui::Text(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextV(const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const char* text_end = g.TempBuffer + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
TextUnformatted(g.TempBuffer, text_end);
|
||||
}
|
||||
|
||||
void ImGui::TextColored(const ImVec4& col, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextColoredV(col, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextColoredV(const ImVec4& col, const char* fmt, va_list args)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_Text, col);
|
||||
TextV(fmt, args);
|
||||
PopStyleColor();
|
||||
}
|
||||
|
||||
void ImGui::TextDisabled(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextDisabledV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextDisabledV(const char* fmt, va_list args)
|
||||
{
|
||||
PushStyleColor(ImGuiCol_Text, GImGui->Style.Colors[ImGuiCol_TextDisabled]);
|
||||
TextV(fmt, args);
|
||||
PopStyleColor();
|
||||
}
|
||||
|
||||
void ImGui::TextWrapped(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
TextWrappedV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void ImGui::TextWrappedV(const char* fmt, va_list args)
|
||||
{
|
||||
bool need_wrap = (GImGui->CurrentWindow->DC.TextWrapPos < 0.0f); // Keep existing wrap position is one ia already set
|
||||
if (need_wrap) PushTextWrapPos(0.0f);
|
||||
TextV(fmt, args);
|
||||
if (need_wrap) PopTextWrapPos();
|
||||
}
|
||||
|
||||
void ImGui::LabelText(const char* label, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LabelTextV(label, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Add a label+text combo aligned to other label+value widgets
|
||||
void ImGui::LabelTextV(const char* label, const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
const float w = CalcItemWidth();
|
||||
|
||||
const ImVec2 label_size = CalcTextSize(label, NULL, true);
|
||||
const ImRect value_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w, label_size.y + style.FramePadding.y*2));
|
||||
const ImRect total_bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(w + (label_size.x > 0.0f ? style.ItemInnerSpacing.x : 0.0f), style.FramePadding.y*2) + label_size);
|
||||
ItemSize(total_bb, style.FramePadding.y);
|
||||
if (!ItemAdd(total_bb, 0))
|
||||
return;
|
||||
|
||||
// Render
|
||||
const char* value_text_begin = &g.TempBuffer[0];
|
||||
const char* value_text_end = value_text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
RenderTextClipped(value_bb.Min, value_bb.Max, value_text_begin, value_text_end, NULL, ImVec2(0.0f,0.5f));
|
||||
if (label_size.x > 0.0f)
|
||||
RenderText(ImVec2(value_bb.Max.x + style.ItemInnerSpacing.x, value_bb.Min.y + style.FramePadding.y), label);
|
||||
}
|
||||
|
||||
void ImGui::BulletText(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
BulletTextV(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// Text with a little bullet aligned to the typical tree node.
|
||||
void ImGui::BulletTextV(const char* fmt, va_list args)
|
||||
{
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
if (window->SkipItems)
|
||||
return;
|
||||
|
||||
ImGuiContext& g = *GImGui;
|
||||
const ImGuiStyle& style = g.Style;
|
||||
|
||||
const char* text_begin = g.TempBuffer;
|
||||
const char* text_end = text_begin + ImFormatStringV(g.TempBuffer, IM_ARRAYSIZE(g.TempBuffer), fmt, args);
|
||||
const ImVec2 label_size = CalcTextSize(text_begin, text_end, false);
|
||||
const float text_base_offset_y = ImMax(0.0f, window->DC.CurrentLineTextBaseOffset); // Latch before ItemSize changes it
|
||||
const float line_height = ImMax(ImMin(window->DC.CurrentLineSize.y, g.FontSize + g.Style.FramePadding.y*2), g.FontSize);
|
||||
const ImRect bb(window->DC.CursorPos, window->DC.CursorPos + ImVec2(g.FontSize + (label_size.x > 0.0f ? (label_size.x + style.FramePadding.x*2) : 0.0f), ImMax(line_height, label_size.y))); // Empty text doesn't add padding
|
||||
ItemSize(bb);
|
||||
if (!ItemAdd(bb, 0))
|
||||
return;
|
||||
|
||||
// Render
|
||||
RenderBullet(bb.Min + ImVec2(style.FramePadding.x + g.FontSize*0.5f, line_height*0.5f));
|
||||
RenderText(bb.Min+ImVec2(g.FontSize + style.FramePadding.x*2, text_base_offset_y), text_begin, text_end, false);
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// WIDGETS: Main
|
||||
|
Loading…
Reference in New Issue
Block a user