mirror of
https://github.com/Drezil/imgui.git
synced 2024-12-18 22:26:34 +00:00
Moved Logging/Capturing section above Docking to facilitate master<>docking merges.
This commit is contained in:
parent
6b43a314bf
commit
104294c7e4
402
imgui.cpp
402
imgui.cpp
@ -73,8 +73,8 @@ CODE
|
||||
// [SECTION] KEYBOARD/GAMEPAD NAVIGATION
|
||||
// [SECTION] COLUMNS
|
||||
// [SECTION] DRAG AND DROP
|
||||
// [SECTION] DOCKING
|
||||
// [SECTION] LOGGING/CAPTURING
|
||||
// [SECTION] DOCKING
|
||||
// [SECTION] SETTINGS
|
||||
// [SECTION] PLATFORM DEPENDENT HELPERS
|
||||
// [SECTION] METRICS/DEBUG WINDOW
|
||||
@ -10100,6 +10100,207 @@ void ImGui::EndDragDropTarget()
|
||||
g.DragDropWithinSourceOrTarget = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] LOGGING/CAPTURING
|
||||
//-----------------------------------------------------------------------------
|
||||
// All text output from the interface can be captured into tty/file/clipboard.
|
||||
// By default, tree nodes are automatically opened during logging.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Pass text data straight to log (without being displayed)
|
||||
void ImGui::LogText(const char* fmt, ...)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (!g.LogEnabled)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if (g.LogFile)
|
||||
vfprintf(g.LogFile, fmt, args);
|
||||
else
|
||||
g.LogBuffer.appendfv(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// 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
|
||||
void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
if (!text_end)
|
||||
text_end = FindRenderedTextEnd(text, text_end);
|
||||
|
||||
const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + 1);
|
||||
if (ref_pos)
|
||||
g.LogLinePosY = ref_pos->y;
|
||||
if (log_new_line)
|
||||
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
|
||||
g.LogDepthRef = window->DC.TreeDepth;
|
||||
const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef);
|
||||
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.
|
||||
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))
|
||||
{
|
||||
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);
|
||||
g.LogLineFirstItem = false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Start logging/capturing text output
|
||||
void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_ASSERT(g.LogEnabled == false);
|
||||
IM_ASSERT(g.LogFile == NULL);
|
||||
IM_ASSERT(g.LogBuffer.empty());
|
||||
g.LogEnabled = true;
|
||||
g.LogType = type;
|
||||
g.LogDepthRef = window->DC.TreeDepth;
|
||||
g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
|
||||
g.LogLinePosY = FLT_MAX;
|
||||
g.LogLineFirstItem = true;
|
||||
}
|
||||
|
||||
void ImGui::LogToTTY(int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
LogBegin(ImGuiLogType_TTY, auto_open_depth);
|
||||
g.LogFile = stdout;
|
||||
}
|
||||
|
||||
// Start logging/capturing text output to given file
|
||||
void ImGui::LogToFile(int auto_open_depth, const char* filename)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
|
||||
// FIXME: We could probably open the file in text mode "at", however note that clipboard/buffer logging will still
|
||||
// be subject to outputting OS-incompatible carriage return if within strings the user doesn't use IM_NEWLINE.
|
||||
// By opening the file in binary mode "ab" we have consistent output everywhere.
|
||||
if (!filename)
|
||||
filename = g.IO.LogFilename;
|
||||
if (!filename || !filename[0])
|
||||
return;
|
||||
FILE* f = ImFileOpen(filename, "ab");
|
||||
if (f == NULL)
|
||||
{
|
||||
IM_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
LogBegin(ImGuiLogType_File, auto_open_depth);
|
||||
g.LogFile = f;
|
||||
}
|
||||
|
||||
// Start logging/capturing text output to clipboard
|
||||
void ImGui::LogToClipboard(int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
|
||||
}
|
||||
|
||||
void ImGui::LogToBuffer(int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
LogBegin(ImGuiLogType_Buffer, auto_open_depth);
|
||||
}
|
||||
|
||||
void ImGui::LogFinish()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (!g.LogEnabled)
|
||||
return;
|
||||
|
||||
LogText(IM_NEWLINE);
|
||||
switch (g.LogType)
|
||||
{
|
||||
case ImGuiLogType_TTY:
|
||||
fflush(g.LogFile);
|
||||
break;
|
||||
case ImGuiLogType_File:
|
||||
fclose(g.LogFile);
|
||||
break;
|
||||
case ImGuiLogType_Buffer:
|
||||
break;
|
||||
case ImGuiLogType_Clipboard:
|
||||
if (!g.LogBuffer.empty())
|
||||
SetClipboardText(g.LogBuffer.begin());
|
||||
break;
|
||||
case ImGuiLogType_None:
|
||||
IM_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
g.LogEnabled = false;
|
||||
g.LogType = ImGuiLogType_None;
|
||||
g.LogFile = NULL;
|
||||
g.LogBuffer.clear();
|
||||
}
|
||||
|
||||
// Helper to display logging buttons
|
||||
// FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!)
|
||||
void ImGui::LogButtons()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
PushID("LogButtons");
|
||||
const bool log_to_tty = Button("Log To TTY"); SameLine();
|
||||
const bool log_to_file = Button("Log To File"); SameLine();
|
||||
const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
|
||||
PushItemWidth(80.0f);
|
||||
PushAllowKeyboardFocus(false);
|
||||
SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL);
|
||||
PopAllowKeyboardFocus();
|
||||
PopItemWidth();
|
||||
PopID();
|
||||
|
||||
// Start logging at the end of the function so that the buttons don't appear in the log
|
||||
if (log_to_tty)
|
||||
LogToTTY();
|
||||
if (log_to_file)
|
||||
LogToFile();
|
||||
if (log_to_clipboard)
|
||||
LogToClipboard();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] DOCKING
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -13194,205 +13395,6 @@ static void ImGui::DockSettingsHandler_WriteAll(ImGuiContext* ctx, ImGuiSettings
|
||||
buf->appendf("\n");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] LOGGING/CAPTURING
|
||||
//-----------------------------------------------------------------------------
|
||||
// All text output from the interface can be captured into tty/file/clipboard.
|
||||
// By default, tree nodes are automatically opened during logging.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// Pass text data straight to log (without being displayed)
|
||||
void ImGui::LogText(const char* fmt, ...)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (!g.LogEnabled)
|
||||
return;
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if (g.LogFile)
|
||||
vfprintf(g.LogFile, fmt, args);
|
||||
else
|
||||
g.LogBuffer.appendfv(fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// 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
|
||||
void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char* text_end)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
|
||||
if (!text_end)
|
||||
text_end = FindRenderedTextEnd(text, text_end);
|
||||
|
||||
const bool log_new_line = ref_pos && (ref_pos->y > g.LogLinePosY + 1);
|
||||
if (ref_pos)
|
||||
g.LogLinePosY = ref_pos->y;
|
||||
if (log_new_line)
|
||||
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
|
||||
g.LogDepthRef = window->DC.TreeDepth;
|
||||
const int tree_depth = (window->DC.TreeDepth - g.LogDepthRef);
|
||||
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.
|
||||
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))
|
||||
{
|
||||
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);
|
||||
g.LogLineFirstItem = false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Start logging/capturing text output
|
||||
void ImGui::LogBegin(ImGuiLogType type, int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
ImGuiWindow* window = g.CurrentWindow;
|
||||
IM_ASSERT(g.LogEnabled == false);
|
||||
IM_ASSERT(g.LogFile == NULL);
|
||||
IM_ASSERT(g.LogBuffer.empty());
|
||||
g.LogEnabled = true;
|
||||
g.LogType = type;
|
||||
g.LogDepthRef = window->DC.TreeDepth;
|
||||
g.LogDepthToExpand = ((auto_open_depth >= 0) ? auto_open_depth : g.LogDepthToExpandDefault);
|
||||
g.LogLinePosY = FLT_MAX;
|
||||
g.LogLineFirstItem = true;
|
||||
}
|
||||
|
||||
void ImGui::LogToTTY(int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
LogBegin(ImGuiLogType_TTY, auto_open_depth);
|
||||
g.LogFile = stdout;
|
||||
}
|
||||
|
||||
// Start logging/capturing text output to given file
|
||||
void ImGui::LogToFile(int auto_open_depth, const char* filename)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
|
||||
// FIXME: We could probably open the file in text mode "at", however note that clipboard/buffer logging will still
|
||||
// be subject to outputting OS-incompatible carriage return if within strings the user doesn't use IM_NEWLINE.
|
||||
// By opening the file in binary mode "ab" we have consistent output everywhere.
|
||||
if (!filename)
|
||||
filename = g.IO.LogFilename;
|
||||
if (!filename || !filename[0])
|
||||
return;
|
||||
FILE* f = ImFileOpen(filename, "ab");
|
||||
if (f == NULL)
|
||||
{
|
||||
IM_ASSERT(0);
|
||||
return;
|
||||
}
|
||||
|
||||
LogBegin(ImGuiLogType_File, auto_open_depth);
|
||||
g.LogFile = f;
|
||||
}
|
||||
|
||||
// Start logging/capturing text output to clipboard
|
||||
void ImGui::LogToClipboard(int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
LogBegin(ImGuiLogType_Clipboard, auto_open_depth);
|
||||
}
|
||||
|
||||
void ImGui::LogToBuffer(int auto_open_depth)
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (g.LogEnabled)
|
||||
return;
|
||||
LogBegin(ImGuiLogType_Buffer, auto_open_depth);
|
||||
}
|
||||
|
||||
void ImGui::LogFinish()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
if (!g.LogEnabled)
|
||||
return;
|
||||
|
||||
LogText(IM_NEWLINE);
|
||||
switch (g.LogType)
|
||||
{
|
||||
case ImGuiLogType_TTY:
|
||||
fflush(g.LogFile);
|
||||
break;
|
||||
case ImGuiLogType_File:
|
||||
fclose(g.LogFile);
|
||||
break;
|
||||
case ImGuiLogType_Buffer:
|
||||
break;
|
||||
case ImGuiLogType_Clipboard:
|
||||
if (!g.LogBuffer.empty())
|
||||
SetClipboardText(g.LogBuffer.begin());
|
||||
break;
|
||||
case ImGuiLogType_None:
|
||||
IM_ASSERT(0);
|
||||
break;
|
||||
}
|
||||
|
||||
g.LogEnabled = false;
|
||||
g.LogType = ImGuiLogType_None;
|
||||
g.LogFile = NULL;
|
||||
g.LogBuffer.clear();
|
||||
}
|
||||
|
||||
// Helper to display logging buttons
|
||||
// FIXME-OBSOLETE: We should probably obsolete this and let the user have their own helper (this is one of the oldest function alive!)
|
||||
void ImGui::LogButtons()
|
||||
{
|
||||
ImGuiContext& g = *GImGui;
|
||||
|
||||
PushID("LogButtons");
|
||||
const bool log_to_tty = Button("Log To TTY"); SameLine();
|
||||
const bool log_to_file = Button("Log To File"); SameLine();
|
||||
const bool log_to_clipboard = Button("Log To Clipboard"); SameLine();
|
||||
PushItemWidth(80.0f);
|
||||
PushAllowKeyboardFocus(false);
|
||||
SliderInt("Default Depth", &g.LogDepthToExpandDefault, 0, 9, NULL);
|
||||
PopAllowKeyboardFocus();
|
||||
PopItemWidth();
|
||||
PopID();
|
||||
|
||||
// Start logging at the end of the function so that the buttons don't appear in the log
|
||||
if (log_to_tty)
|
||||
LogToTTY();
|
||||
if (log_to_file)
|
||||
LogToFile();
|
||||
if (log_to_clipboard)
|
||||
LogToClipboard();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// [SECTION] SETTINGS
|
||||
|
Loading…
Reference in New Issue
Block a user