mirror of
				https://github.com/ocornut/imgui.git
				synced 2025-10-26 12:27:30 +00:00 
			
		
		
		
	Log depth padding relative to start depth. Tree node and headers looking better when logged to text. Added LogText().
This commit is contained in:
		
							
								
								
									
										85
									
								
								imgui.cpp
									
									
									
									
									
								
							
							
						
						
									
										85
									
								
								imgui.cpp
									
									
									
									
									
								
							| @@ -861,6 +861,7 @@ struct ImGuiState | |||||||
|     bool                    LogEnabled; |     bool                    LogEnabled; | ||||||
|     FILE*                   LogFile; |     FILE*                   LogFile; | ||||||
|     ImGuiTextBuffer*        LogClipboard;                       // pointer so our GImGui static constructor doesn't call heap allocators. |     ImGuiTextBuffer*        LogClipboard;                       // pointer so our GImGui static constructor doesn't call heap allocators. | ||||||
|  |     int                     LogStartDepth; | ||||||
|     int                     LogAutoExpandMaxDepth; |     int                     LogAutoExpandMaxDepth; | ||||||
|  |  | ||||||
|     ImGuiState() |     ImGuiState() | ||||||
| @@ -887,6 +888,7 @@ struct ImGuiState | |||||||
|         PrivateClipboard = NULL; |         PrivateClipboard = NULL; | ||||||
|         LogEnabled = false; |         LogEnabled = false; | ||||||
|         LogFile = NULL; |         LogFile = NULL; | ||||||
|  |         LogStartDepth = 0; | ||||||
|         LogAutoExpandMaxDepth = 2; |         LogAutoExpandMaxDepth = 2; | ||||||
|         LogClipboard = NULL; |         LogClipboard = NULL; | ||||||
|     } |     } | ||||||
| @@ -1158,23 +1160,24 @@ bool ImGuiTextFilter::PassFilter(const char* val) const | |||||||
| //----------------------------------------------------------------------------- | //----------------------------------------------------------------------------- | ||||||
|  |  | ||||||
| // Helper: Text buffer for logging/accumulating text | // Helper: Text buffer for logging/accumulating text | ||||||
| void ImGuiTextBuffer::append(const char* fmt, ...) | void ImGuiTextBuffer::appendv(const char* fmt, va_list args) | ||||||
| { | { | ||||||
|     va_list args; |     int len = vsnprintf(NULL, 0, fmt, args);         // FIXME-OPT: could do a first pass write attempt, likely successful on first pass. | ||||||
|     va_start(args, fmt); |  | ||||||
|     int len = vsnprintf(NULL, 0, fmt, args); |  | ||||||
|     va_end(args); |  | ||||||
|     if (len <= 0) |     if (len <= 0) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     const size_t write_off = Buf.size(); |     const size_t write_off = Buf.size(); | ||||||
|     if (write_off + (size_t)len >= Buf.capacity()) |     if (write_off + (size_t)len >= Buf.capacity()) | ||||||
|         Buf.reserve(Buf.capacity() * 2); |         Buf.reserve(Buf.capacity() * 2); | ||||||
|  |  | ||||||
|     Buf.resize(write_off + (size_t)len); |     Buf.resize(write_off + (size_t)len); | ||||||
|  |  | ||||||
|     va_start(args, fmt); |  | ||||||
|     ImFormatStringV(&Buf[write_off] - 1, (size_t)len+1, fmt, args); |     ImFormatStringV(&Buf[write_off] - 1, (size_t)len+1, fmt, args); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void ImGuiTextBuffer::append(const char* fmt, ...) | ||||||
|  | { | ||||||
|  |     va_list args; | ||||||
|  |     va_start(args, fmt); | ||||||
|  |     appendv(fmt, args); | ||||||
|     va_end(args); |     va_end(args); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1764,7 +1767,27 @@ static const char*  FindTextDisplayEnd(const char* text, const char* text_end = | |||||||
|     return text_display_end; |     return text_display_end; | ||||||
| } | } | ||||||
|  |  | ||||||
| // Log ImGui display into text output (tty or file or clipboard) | // Pass text data straight to log (without being displayed) | ||||||
|  | void ImGui::LogText(const char* fmt, ...) | ||||||
|  | { | ||||||
|  |     ImGuiState& g = GImGui; | ||||||
|  |     if (!g.LogEnabled) | ||||||
|  |         return; | ||||||
|  |  | ||||||
|  |     va_list args; | ||||||
|  |     va_start(args, fmt); | ||||||
|  |     if (g.LogFile) | ||||||
|  |     { | ||||||
|  |         vfprintf(g.LogFile, fmt, args); | ||||||
|  |     } | ||||||
|  |     else | ||||||
|  |     { | ||||||
|  |         g.LogClipboard->appendv(fmt, args); | ||||||
|  |     } | ||||||
|  |     va_end(args); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Internal version that takes a position to decide on newline placement and pad items according to their depth. | ||||||
| static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end) | static void LogText(const ImVec2& ref_pos, const char* text, const char* text_end) | ||||||
| { | { | ||||||
|     ImGuiState& g = GImGui; |     ImGuiState& g = GImGui; | ||||||
| @@ -1777,7 +1800,9 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* text_en | |||||||
|     window->DC.LogLineHeight = ref_pos.y; |     window->DC.LogLineHeight = ref_pos.y; | ||||||
|  |  | ||||||
|     const char* text_remaining = text; |     const char* text_remaining = text; | ||||||
|     const int tree_depth = window->DC.TreeDepth; |     if (g.LogStartDepth > window->DC.TreeDepth)  // Re-adjust padding if we have popped out of our starting depth | ||||||
|  |         g.LogStartDepth = window->DC.TreeDepth; | ||||||
|  |     const int tree_depth = (window->DC.TreeDepth - g.LogStartDepth); | ||||||
|     while (true) |     while (true) | ||||||
|     { |     { | ||||||
|         const char* line_end = text_remaining; |         const char* line_end = text_remaining; | ||||||
| @@ -1799,20 +1824,10 @@ static void LogText(const ImVec2& ref_pos, const char* text, const char* text_en | |||||||
|         if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0)) |         if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0)) | ||||||
|         { |         { | ||||||
|             const int char_count = (int)(line_end - text_remaining); |             const int char_count = (int)(line_end - text_remaining); | ||||||
|             if (g.LogFile) |  | ||||||
|             { |  | ||||||
|             if (log_new_line || !is_first_line) |             if (log_new_line || !is_first_line) | ||||||
|                     fprintf(g.LogFile, "\n%*s%.*s", tree_depth*4, "", char_count, text_remaining); |                 ImGui::LogText("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining); | ||||||
|             else |             else | ||||||
|                     fprintf(g.LogFile, " %.*s", char_count, text_remaining); |                 ImGui::LogText(" %.*s", char_count, text_remaining); | ||||||
|             } |  | ||||||
|             else |  | ||||||
|             { |  | ||||||
|                 if (log_new_line || !is_first_line) |  | ||||||
|                     g.LogClipboard->append("\n%*s%.*s", tree_depth*4, "", char_count, text_remaining); |  | ||||||
|                 else |  | ||||||
|                     g.LogClipboard->append(" %.*s", char_count, text_remaining); |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         if (is_last_line) |         if (is_last_line) | ||||||
| @@ -3434,10 +3449,13 @@ static bool CloseWindowButton(bool* p_opened) | |||||||
| void ImGui::LogToTTY(int max_depth) | void ImGui::LogToTTY(int max_depth) | ||||||
| { | { | ||||||
|     ImGuiState& g = GImGui; |     ImGuiState& g = GImGui; | ||||||
|  |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|     if (g.LogEnabled) |     if (g.LogEnabled) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     g.LogEnabled = true; |     g.LogEnabled = true; | ||||||
|     g.LogFile = stdout; |     g.LogFile = stdout; | ||||||
|  |     g.LogStartDepth = window->DC.TreeDepth; | ||||||
|     if (max_depth >= 0) |     if (max_depth >= 0) | ||||||
|         g.LogAutoExpandMaxDepth = max_depth; |         g.LogAutoExpandMaxDepth = max_depth; | ||||||
| } | } | ||||||
| @@ -3446,12 +3464,15 @@ void ImGui::LogToTTY(int max_depth) | |||||||
| void ImGui::LogToFile(int max_depth, const char* filename) | void ImGui::LogToFile(int max_depth, const char* filename) | ||||||
| { | { | ||||||
|     ImGuiState& g = GImGui; |     ImGuiState& g = GImGui; | ||||||
|  |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|     if (g.LogEnabled) |     if (g.LogEnabled) | ||||||
|         return; |         return; | ||||||
|     if (!filename) |     if (!filename) | ||||||
|         filename = g.IO.LogFilename; |         filename = g.IO.LogFilename; | ||||||
|  |  | ||||||
|     g.LogEnabled = true; |     g.LogEnabled = true; | ||||||
|     g.LogFile = fopen(filename, "at"); |     g.LogFile = fopen(filename, "at"); | ||||||
|  |     g.LogStartDepth = window->DC.TreeDepth; | ||||||
|     if (max_depth >= 0) |     if (max_depth >= 0) | ||||||
|         g.LogAutoExpandMaxDepth = max_depth; |         g.LogAutoExpandMaxDepth = max_depth; | ||||||
| } | } | ||||||
| @@ -3459,11 +3480,14 @@ void ImGui::LogToFile(int max_depth, const char* filename) | |||||||
| // Start logging ImGui output to clipboard | // Start logging ImGui output to clipboard | ||||||
| void ImGui::LogToClipboard(int max_depth) | void ImGui::LogToClipboard(int max_depth) | ||||||
| { | { | ||||||
|  |     ImGuiWindow* window = GetCurrentWindow(); | ||||||
|     ImGuiState& g = GImGui; |     ImGuiState& g = GImGui; | ||||||
|     if (g.LogEnabled) |     if (g.LogEnabled) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|     g.LogEnabled = true; |     g.LogEnabled = true; | ||||||
|     g.LogFile = NULL; |     g.LogFile = NULL; | ||||||
|  |     g.LogStartDepth = window->DC.TreeDepth; | ||||||
|     if (max_depth >= 0) |     if (max_depth >= 0) | ||||||
|         g.LogAutoExpandMaxDepth = max_depth; |         g.LogAutoExpandMaxDepth = max_depth; | ||||||
| } | } | ||||||
| @@ -3473,10 +3497,11 @@ void ImGui::LogFinish() | |||||||
|     ImGuiState& g = GImGui; |     ImGuiState& g = GImGui; | ||||||
|     if (!g.LogEnabled) |     if (!g.LogEnabled) | ||||||
|         return; |         return; | ||||||
|  |  | ||||||
|  |     ImGui::LogText("\n"); | ||||||
|     g.LogEnabled = false; |     g.LogEnabled = false; | ||||||
|     if (g.LogFile != NULL) |     if (g.LogFile != NULL) | ||||||
|     { |     { | ||||||
|         fprintf(g.LogFile, "\n"); |  | ||||||
|         if (g.LogFile == stdout) |         if (g.LogFile == stdout) | ||||||
|             fflush(g.LogFile); |             fflush(g.LogFile); | ||||||
|         else |         else | ||||||
| @@ -3485,7 +3510,6 @@ void ImGui::LogFinish() | |||||||
|     } |     } | ||||||
|     if (g.LogClipboard->size() > 1) |     if (g.LogClipboard->size() > 1) | ||||||
|     { |     { | ||||||
|         g.LogClipboard->append("\n"); |  | ||||||
|         if (g.IO.SetClipboardTextFn) |         if (g.IO.SetClipboardTextFn) | ||||||
|             g.IO.SetClipboardTextFn(g.LogClipboard->begin()); |             g.IO.SetClipboardTextFn(g.LogClipboard->begin()); | ||||||
|         g.LogClipboard->clear(); |         g.LogClipboard->clear(); | ||||||
| @@ -3591,7 +3615,18 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, const bool d | |||||||
|         // Framed type |         // Framed type | ||||||
|         RenderFrame(bb.Min, bb.Max, col, true); |         RenderFrame(bb.Min, bb.Max, col, true); | ||||||
|         RenderCollapseTriangle(bb.Min + style.FramePadding, opened, 1.0f, true); |         RenderCollapseTriangle(bb.Min + style.FramePadding, opened, 1.0f, true); | ||||||
|  |         if (g.LogEnabled) | ||||||
|  |         { | ||||||
|  |             // NB: '##' is normally used to hide text (as a library-wide feature), so we need to specify the text range to make sure the ## aren't stripped out here. | ||||||
|  |             const char log_prefix[] = "\n##"; | ||||||
|  |             LogText(bb.Min + style.FramePadding, log_prefix, log_prefix+3); | ||||||
|  |         } | ||||||
|         RenderText(bb.Min + style.FramePadding + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label); |         RenderText(bb.Min + style.FramePadding + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label); | ||||||
|  |         if (g.LogEnabled) | ||||||
|  |         { | ||||||
|  |             const char log_suffix[] = "##"; | ||||||
|  |             LogText(bb.Min + style.FramePadding, log_suffix, log_suffix+2); | ||||||
|  |         } | ||||||
|     } |     } | ||||||
|     else |     else | ||||||
|     { |     { | ||||||
| @@ -3599,6 +3634,8 @@ bool ImGui::CollapsingHeader(const char* label, const char* str_id, const bool d | |||||||
|         if ((held && hovered) || hovered) |         if ((held && hovered) || hovered) | ||||||
|             RenderFrame(bb.Min, bb.Max, col, false); |             RenderFrame(bb.Min, bb.Max, col, false); | ||||||
|         RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, window->FontSize()*0.15f), opened, 0.70f, false); |         RenderCollapseTriangle(bb.Min + ImVec2(style.FramePadding.x, window->FontSize()*0.15f), opened, 0.70f, false); | ||||||
|  |         if (g.LogEnabled) | ||||||
|  |             LogText(bb.Min, ">"); | ||||||
|         RenderText(bb.Min + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label); |         RenderText(bb.Min + ImVec2(window->FontSize() + style.FramePadding.x*2,0), label); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								imgui.h
									
									
									
									
									
								
							| @@ -286,6 +286,7 @@ namespace ImGui | |||||||
|     IMGUI_API void          LogToClipboard(int max_depth = -1);                                 // start logging to OS clipboard |     IMGUI_API void          LogToClipboard(int max_depth = -1);                                 // start logging to OS clipboard | ||||||
|     IMGUI_API void          LogFinish();                                                        // stop logging (close file, etc.) |     IMGUI_API void          LogFinish();                                                        // stop logging (close file, etc.) | ||||||
|     IMGUI_API void          LogButtons();                                                       // helper to display buttons for logging to tty/file/clipboard |     IMGUI_API void          LogButtons();                                                       // helper to display buttons for logging to tty/file/clipboard | ||||||
|  |     IMGUI_API void          LogText(const char* fmt, ...);                                      // pass text data straight to log (without being displayed) | ||||||
|  |  | ||||||
|     // Utilities |     // Utilities | ||||||
|     IMGUI_API bool          IsItemHovered();                                                    // was the last item active area hovered by mouse? |     IMGUI_API bool          IsItemHovered();                                                    // was the last item active area hovered by mouse? | ||||||
| @@ -605,6 +606,7 @@ struct ImGuiTextBuffer | |||||||
|     bool                empty() { return Buf.empty(); } |     bool                empty() { return Buf.empty(); } | ||||||
|     void                clear() { Buf.clear(); Buf.push_back(0); } |     void                clear() { Buf.clear(); Buf.push_back(0); } | ||||||
|     IMGUI_API void      append(const char* fmt, ...); |     IMGUI_API void      append(const char* fmt, ...); | ||||||
|  |     IMGUI_API void      appendv(const char* fmt, va_list args); | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Helper: Key->value storage | // Helper: Key->value storage | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 ocornut
					ocornut