Refactor: Moved Text functions from imgui.cpp to imgui_widgets.cpp (#2036)
diff --git a/imgui.cpp b/imgui.cpp
index e2a4c4d..1025951 100644
--- a/imgui.cpp
+++ b/imgui.cpp
@@ -7871,177 +7871,6 @@
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 @@
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 @@
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
diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp
index 538b905..5ea5c3b 100644
--- a/imgui_widgets.cpp
+++ b/imgui_widgets.cpp
@@ -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