Log/Capture: Fixes for handling \n in strings. Improve the look of various widgets. Added LogSetNextTextDecoration helper. Fixup/amend dbaf74d75.

For now removed LogRenderedTextNewLine() - it is eventually desirable but currently carries too much ambiguities, so reverted until we have a better system and test suite.
This commit is contained in:
ocornut
2021-02-02 09:42:23 +01:00
parent dbaf74d758
commit 929563c3a7
6 changed files with 87 additions and 71 deletions

View File

@ -4944,6 +4944,7 @@ void ImGui::EndChild()
}
}
g.WithinEndChild = false;
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
}
// Helper to create a child window / scrolling region that looks like a normal widget frame.
@ -7572,7 +7573,7 @@ void ImGui::BeginGroup()
window->DC.CursorMaxPos = window->DC.CursorPos;
window->DC.CurrLineSize = ImVec2(0.0f, 0.0f);
if (g.LogEnabled)
LogRenderedTextNewLine();
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
}
void ImGui::EndGroup()
@ -7593,7 +7594,7 @@ void ImGui::EndGroup()
window->DC.CurrLineSize = group_data.BackupCurrLineSize;
window->DC.CurrLineTextBaseOffset = group_data.BackupCurrLineTextBaseOffset;
if (g.LogEnabled)
LogRenderedTextNewLine();
g.LogLinePosY = -FLT_MAX; // To enforce a carriage return
if (!group_data.EmitItem)
{
@ -9859,11 +9860,16 @@ void ImGui::LogText(const char* fmt, ...)
// Internal version that takes a position to decide on newline placement and pad items according to their depth.
// We split text into individual lines to add current tree level padding
// FIXME: This code is a little complicated perhaps, considering simplifying the whole system.
void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
{
ImGuiContext& g = *GImGui;
ImGuiWindow* window = g.CurrentWindow;
const char* prefix = g.LogNextPrefix;
const char* suffix = g.LogNextSuffix;
g.LogNextPrefix = g.LogNextSuffix = NULL;
if (!text_end)
text_end = FindRenderedTextEnd(text, text_end);
@ -9871,52 +9877,46 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
if (ref_pos)
g.LogLinePosY = ref_pos->y;
if (log_new_line)
{
LogText(IM_NEWLINE);
g.LogLineFirstItem = true;
}
const char* text_remaining = text;
if (g.LogDepthRef > window->DC.TreeDepth) // Re-adjust padding if we have popped out of our starting depth
if (prefix)
LogRenderedText(ref_pos, prefix, prefix + strlen(prefix)); // Calculate end ourself to ensure "##" are included here.
// Re-adjust padding if we have popped out of our starting depth
if (g.LogDepthRef > window->DC.TreeDepth)
g.LogDepthRef = window->DC.TreeDepth;
const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef);
const char* text_remaining = text;
for (;;)
{
// Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
// We don't add a trailing \n to allow a subsequent item on the same line to be captured.
// Split the string. Each new line (after a '\n') is followed by indentation corresponding to the current depth of our log entry.
// We don't add a trailing \n yet to allow a subsequent item on the same line to be captured.
const char* line_start = text_remaining;
const char* line_end = ImStreolRange(line_start, text_end);
const bool is_first_line = (line_start == text);
const bool is_last_line = (line_end == text_end);
if (!is_last_line || (line_start != line_end))
if (line_start != line_end || !is_last_line)
{
const int char_count = (int)(line_end - line_start);
if (log_new_line || !is_first_line)
LogText(IM_NEWLINE "%*s%.*s", tree_depth * 4, "", char_count, line_start);
else if (g.LogLineFirstItem)
LogText("%*s%.*s", tree_depth * 4, "", char_count, line_start);
else
LogText(" %.*s", char_count, line_start);
const int line_length = (int)(line_end - line_start);
const int indentation = g.LogLineFirstItem ? tree_depth * 4 : 1;
LogText("%*s%.*s", indentation, "", line_length, line_start);
g.LogLineFirstItem = false;
if (*line_end == '\n')
LogRenderedTextNewLine();
{
LogText(IM_NEWLINE);
g.LogLineFirstItem = true;
}
}
else if (log_new_line)
{
// An empty "" string at a different Y position should output a carriage return.
LogText(IM_NEWLINE);
break;
}
if (is_last_line)
break;
text_remaining = line_end + 1;
}
}
void ImGui::LogRenderedTextNewLine()
{
// To enforce Log carriage return
ImGuiContext& g = *GImGui;
g.LogLinePosY = -FLT_MAX;
if (suffix)
LogRenderedText(ref_pos, suffix, suffix + strlen(suffix));
}
// Start logging/capturing text output
@ -9929,12 +9929,21 @@ void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
IM_ASSERT(g.LogBuffer.empty());
g.LogEnabled = true;
g.LogType = type;
g.LogNextPrefix = g.LogNextSuffix = NULL;
g.LogDepthRef = window->DC.TreeDepth;
g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
g.LogLinePosY = FLT_MAX;
g.LogLineFirstItem = true;
}
// Important: doesn't copy underlying data, use carefully (prefix/suffix must be in scope at the time of the next LogRenderedText)
void ImGui::LogSetNextTextDecoration(const char* prefix, const char* suffix)
{
ImGuiContext& g = *GImGui;
g.LogNextPrefix = prefix;
g.LogNextSuffix = suffix;
}
void ImGui::LogToTTY(int auto_open_depth)
{
ImGuiContext& g = *GImGui;