Skip to main content

LogWidget Class

Debug widget for displaying log output in a scrollable ImGui panel. More...

Declaration

class helios::ext::imgui::widgets::LogWidget { ... }

Base class

classImGuiWidget

Abstract base class for ImGui widgets rendered in debug overlays. More...

Public Constructors Index

LogWidget ()=default

Public Destructor Index

~LogWidget () override=default

Public Member Functions Index

voidaddLog (LogLevel level, const std::string &scope, const std::string &message)

Adds a log entry to the appropriate scope buffer(s). More...

voiddebug (const std::string &scope, const std::string &message)

Convenience method to add a debug-level log entry. More...

voidinfo (const std::string &scope, const std::string &message)

Convenience method to add an info-level log entry. More...

voidwarn (const std::string &scope, const std::string &message)

Convenience method to add a warning-level log entry. More...

voiderror (const std::string &scope, const std::string &message)

Convenience method to add an error-level log entry. More...

voidclear () noexcept

Clears all log entries from all buffers. More...

voidsetMaxEntries (std::size_t max) noexcept

Sets the maximum number of entries to retain per scope. More...

voidsetAutoScroll (bool enabled) noexcept

Enables or disables auto-scrolling to the latest entry. More...

voidsetFilterLevel (LogLevel level) noexcept

Sets the minimum log level to display. More...

voidsetScopeFilterCallback (std::function< void(const std::string &)> callback)

Sets a callback to be invoked when the scope filter changes. More...

std::size_tentryCount () const noexcept

Returns the current number of log entries in the active buffer. More...

voiddraw () override

Renders the log widget using ImGui. More...

Private Member Functions Index

voidcollectScope (const std::string &scope)

Adds a scope to the collection if not already present. More...

voidaddToBuffer (std::vector< LogEntry > &buffer, LogEntry entry)

Adds an entry to a specific buffer, trimming if necessary. More...

const std::vector< LogEntry > &activeBuffer () const

Returns the currently active buffer based on scope selection. More...

Private Member Attributes Index

std::unordered_map< std::string, std::vector< LogEntry > >scopeBuffers_

Per-scope log buffers. Key is scope name, value is entry vector. More...

std::size_tmaxEntries_ = 1000

Maximum number of entries to retain per scope buffer. More...

std::mutexbufferMutex_

Mutex for thread-safe access to the log buffers. More...

boolautoScroll_ = true

Whether to automatically scroll to the bottom on new entries. More...

boolprevAutoScroll_ = true

Previous autoScroll state to detect toggle events. More...

boolscrollUpOneEntry_ = false

Flag to nudge scroll up one entry when auto-scroll is disabled. More...

boolscrollToBottom_ = false

Flag to indicate that new content was added and scroll is needed. More...

boolwasAtBottom_ = true

Tracks if user was at bottom in the previous frame. More...

std::atomic< bool >acceptNewEntries_ {true}

Whether new entries are currently accepted into the buffer. More...

std::atomic< std::size_t >skippedEntries_ {0}

Counts how many log entries were skipped while logging was paused. More...

LogLevelfilterLevel_ = LogLevel::Debug

Minimum log level to display (filters out lower levels). More...

ImGuiTextFiltertextFilter_

Text filter for searching within log messages. More...

intfilterLevelIndex_ = 0

Current filter level selection index for the combo box. More...

std::vector< std::string >collectedScopes_

Collection of all unique scopes seen in log entries. More...

intselectedScopeIndex_ = -1

Currently selected scope index in the combo box (0 = "All", -1 = "None"). More...

std::stringactiveScopeFilter_

Currently active scope filter (empty = show all). More...

boolloggingDisabled_ = true

Whether logging is completely disabled (None selected). More...

std::function< void(const std::string &)>onScopeFilterChanged_

Callback function to notify external systems of scope filter changes. More...

Private Static Functions Index

static ImVec4colorForLevel (LogLevel level) noexcept

Returns an ImVec4 color for the given log level. More...

static const char *labelForLevel (LogLevel level) noexcept

Returns a string label for the given log level. More...

static std::stringcurrentTimestamp () noexcept

Generates a simple timestamp string (HH:MM:SS.mmm). More...

Private Static Attributes Index

static constexpr const char *ALL_SCOPES_KEY = "__all__"

Key for the "all scopes" combined view. More...

static constexpr const char *NONE_SCOPES_KEY = "__none__"

Key for the "none" option that disables logging. More...

Description

Debug widget for displaying log output in a scrollable ImGui panel.

This widget maintains separate buffers for each log scope and renders them in a scrollable text area. It supports filtering by log level, clearing the buffer, and auto-scrolling to the latest messages.

Each scope has its own buffer with a maximum of 1000 entries, allowing efficient scope-based filtering without losing messages from other scopes.

info

This widget uses internal locking for adding log entries from multiple threads.

Definition at line 73 of file LogWidget.ixx.

Public Constructors

LogWidget()

helios::ext::imgui::widgets::LogWidget::LogWidget ()
default

Definition at line 282 of file LogWidget.ixx.

Public Destructor

~LogWidget()

helios::ext::imgui::widgets::LogWidget::~LogWidget ()
default

Definition at line 283 of file LogWidget.ixx.

Public Member Functions

addLog()

void helios::ext::imgui::widgets::LogWidget::addLog (LogLevel level, const std::string & scope, const std::string & message)
inline

Adds a log entry to the appropriate scope buffer(s).

Thread-safe. Adds to both the scope-specific buffer and the "all" buffer.

Definition at line 290 of file LogWidget.ixx.

290 void addLog(LogLevel level, const std::string& scope, const std::string& message) {
291 // If logging is completely disabled, skip
292 if (loggingDisabled_) {
293 return;
294 }
295
296 // If user scrolls up and AutoScroll is off, we do not accept new entries
297 // to make sure memory is not flooded with new log entries in the background.
298 if (!acceptNewEntries_.load(std::memory_order_relaxed)) {
299 skippedEntries_.fetch_add(1, std::memory_order_relaxed);
300 return;
301 }
302
303 std::lock_guard<std::mutex> lock(bufferMutex_);
304
305 // Collect unique scopes for the filter dropdown
306 collectScope(scope);
307
308 LogEntry entry;
309 entry.level = level;
310 entry.scope = scope;
311 entry.message = message;
312 entry.timestamp = currentTimestamp();
313
314 // Add to scope-specific buffer
315 addToBuffer(scopeBuffers_[scope], entry);
316
317 // Add to "all scopes" buffer
318 addToBuffer(scopeBuffers_[ALL_SCOPES_KEY], entry);
319
320 // Always signal new content - scroll decision happens in draw()
321 scrollToBottom_ = true;
322 }

References helios::ext::imgui::widgets::LogEntry::level, helios::ext::imgui::widgets::LogEntry::message, helios::ext::imgui::widgets::LogEntry::scope and helios::ext::imgui::widgets::LogEntry::timestamp.

Referenced by debug, error, info and warn.

clear()

void helios::ext::imgui::widgets::LogWidget::clear ()
inline noexcept

Clears all log entries from all buffers.

Definition at line 367 of file LogWidget.ixx.

367 void clear() noexcept {
368 std::lock_guard<std::mutex> lock(bufferMutex_);
369 scopeBuffers_.clear();
370 skippedEntries_.store(0, std::memory_order_relaxed);
371 }

Referenced by draw.

debug()

void helios::ext::imgui::widgets::LogWidget::debug (const std::string & scope, const std::string & message)
inline

Convenience method to add a debug-level log entry.

Parameters
scope

The source scope or module name.

message

The log message text.

Definition at line 330 of file LogWidget.ixx.

330 void debug(const std::string& scope, const std::string& message) {
331 addLog(LogLevel::Debug, scope, message);
332 }

References addLog and helios::ext::imgui::widgets::Debug.

draw()

void helios::ext::imgui::widgets::LogWidget::draw ()
inline virtual

Renders the log widget using ImGui.

Definition at line 435 of file LogWidget.ixx.

435 void draw() override {
436 ImGui::SetNextWindowSize(ImVec2(600, 400), ImGuiCond_FirstUseEver);
437
438 // Window is dockable by default when ImGuiConfigFlags_DockingEnable is set
439 if (ImGui::Begin("Log Console", nullptr)) {
440
441 // Toolbar row
442 if (ImGui::Button("Clear")) {
443 clear();
444 }
445 ImGui::SameLine();
446
447 if (ImGui::Checkbox("Auto-Scroll", &autoScroll_)) {
448 // Detect transition from enabled to disabled
449 if (prevAutoScroll_ && !autoScroll_) {
450 scrollUpOneEntry_ = true;
451 }
452 }
453 prevAutoScroll_ = autoScroll_;
454 ImGui::SameLine();
455
456 // Level filter combo
457 const char* levelItems[] = { "Debug", "Info", "Warn", "Error" };
458 ImGui::SetNextItemWidth(80);
459 if (ImGui::Combo("Level", &filterLevelIndex_, levelItems, IM_ARRAYSIZE(levelItems))) {
460 filterLevel_ = static_cast<LogLevel>(filterLevelIndex_);
461 }
462 ImGui::SameLine();
463
464 // Scope filter combo
465 {
466 std::lock_guard<std::mutex> lock(bufferMutex_);
467
468 std::string scopePreview;
469 if (loggingDisabled_) {
470 scopePreview = "None";
471 } else if (selectedScopeIndex_ == 0) {
472 scopePreview = "All Scopes";
473 } else if (selectedScopeIndex_ <= static_cast<int>(collectedScopes_.size())) {
474 scopePreview = collectedScopes_[selectedScopeIndex_ - 1];
475 } else {
476 scopePreview = "All Scopes";
477 }
478
479 ImGui::SetNextItemWidth(150);
480 if (ImGui::BeginCombo("Scope", scopePreview.c_str())) {
481 // "None" option - disables logging completely
482 bool isNoneSelected = loggingDisabled_;
483 if (ImGui::Selectable("None", isNoneSelected)) {
484 loggingDisabled_ = true;
485 selectedScopeIndex_ = -1;
486 activeScopeFilter_.clear();
487 if (onScopeFilterChanged_) {
488 onScopeFilterChanged_(NONE_SCOPES_KEY);
489 }
490 }
491 if (isNoneSelected) {
492 ImGui::SetItemDefaultFocus();
493 }
494
495 // "All Scopes" option
496 bool isSelected = (!loggingDisabled_ && selectedScopeIndex_ == 0);
497 if (ImGui::Selectable("All Scopes", isSelected)) {
498 loggingDisabled_ = false;
499 selectedScopeIndex_ = 0;
500 activeScopeFilter_.clear();
501 if (onScopeFilterChanged_) {
502 onScopeFilterChanged_("");
503 }
504 }
505 if (isSelected) {
506 ImGui::SetItemDefaultFocus();
507 }
508
509 for (std::size_t i = 0; i < collectedScopes_.size(); ++i) {
510 isSelected = (!loggingDisabled_ && selectedScopeIndex_ == static_cast<int>(i + 1));
511 if (ImGui::Selectable(collectedScopes_[i].c_str(), isSelected)) {
512 loggingDisabled_ = false;
513 selectedScopeIndex_ = static_cast<int>(i + 1);
514 activeScopeFilter_ = collectedScopes_[i];
515 if (onScopeFilterChanged_) {
516 onScopeFilterChanged_(activeScopeFilter_);
517 }
518 }
519 if (isSelected) {
520 ImGui::SetItemDefaultFocus();
521 }
522 }
523 ImGui::EndCombo();
524 }
525 }
526 ImGui::SameLine();
527
528 textFilter_.Draw("Filter", 150);
529
530 ImGui::Separator();
531
532 // Log area
533 const float footerHeight =
534 ImGui::GetStyle().ItemSpacing.y + ImGui::GetFrameHeightWithSpacing();
535 if (ImGui::BeginChild("LogScrollRegion", ImVec2(0, -footerHeight),
536 ImGuiChildFlags_Borders,
537 ImGuiWindowFlags_HorizontalScrollbar)) {
538
539 // Copy active buffer
540 std::vector<LogEntry> bufferCopy;
541 bool hasNewContent = false;
542 {
543 std::lock_guard<std::mutex> lock(bufferMutex_);
544 bufferCopy = activeBuffer();
545 hasNewContent = scrollToBottom_;
546 scrollToBottom_ = false;
547 }
548
549 ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 1));
550
551 for (const auto& entry : bufferCopy) {
552 // Filter by level
553 if (static_cast<int>(entry.level) < static_cast<int>(filterLevel_)) {
554 continue;
555 }
556
557 // Build display string for text filter
558 // If a specific scope is selected, omit scope from display (already visible in combo)
559 std::string displayLine;
560 if (activeScopeFilter_.empty()) {
561 // "All Scopes" selected - show scope in each line
562 displayLine = entry.timestamp + " " +
563 labelForLevel(entry.level) + " [" +
564 entry.scope + "] " + entry.message;
565 } else {
566 // Specific scope filtered - omit scope from display
567 displayLine = entry.timestamp + " " +
568 labelForLevel(entry.level) + " " + entry.message;
569 }
570
571 // Apply text filter
572 if (!textFilter_.PassFilter(displayLine.c_str())) {
573 continue;
574 }
575
576 // Render with color
577 ImVec4 color = colorForLevel(entry.level);
578 ImGui::PushStyleColor(ImGuiCol_Text, color);
579 ImGui::TextUnformatted(displayLine.c_str());
580 ImGui::PopStyleColor();
581 }
582
583 ImGui::PopStyleVar();
584
585 // Scroll state
586 float scrollY = ImGui::GetScrollY();
587 float scrollMaxY = ImGui::GetScrollMaxY();
588 bool atBottomNow = (scrollMaxY <= 0.0f) || (scrollY >= scrollMaxY - 5.0f);
589
590 // Nudge scroll up when auto-scroll was just disabled
591 // This prevents showing that new entries are being added
592 if (scrollUpOneEntry_) {
593 // Calculate offset for 2 log entries
594 float lineHeight = ImGui::GetTextLineHeightWithSpacing();
595 float nudgeAmount = lineHeight * 2.0f;
596
597 // Set scroll position relative to maximum (scroll up from bottom)
598 float targetScrollY = scrollMaxY - nudgeAmount;
599 if (targetScrollY < 0.0f) targetScrollY = 0.0f;
600 ImGui::SetScrollY(targetScrollY);
601 scrollUpOneEntry_ = false;
602
603 // Update atBottomNow since we just scrolled
604 atBottomNow = false;
605 }
606 // Auto-scroll decision
607 else if (hasNewContent && (autoScroll_ || wasAtBottom_)) {
608 ImGui::SetScrollHereY(1.0f);
609 }
610
611 // Pause logging if:
612 // - AutoScroll is off AND user has not scrolled to lower bottom
613 bool pauseLogging = (!autoScroll_ && !atBottomNow);
614 acceptNewEntries_.store(!pauseLogging, std::memory_order_relaxed);
615 wasAtBottom_ = atBottomNow;
616 }
617 ImGui::EndChild();
618
619 // Footer
620 {
621 std::lock_guard<std::mutex> lock(bufferMutex_);
622 ImGui::Text("Entries: %zu / %zu", activeBuffer().size(), maxEntries_);
623 }
624
625 bool loggingPaused = !acceptNewEntries_.load(std::memory_order_relaxed);
626 auto skipped = skippedEntries_.load(std::memory_order_relaxed);
627
628 if (loggingPaused) {
629 ImGui::SameLine();
630 if (skipped > 0) {
631 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f),
632 "Logging paused (%zu entries skipped)", skipped);
633 } else {
634 ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Logging paused");
635 }
636 } else if (skipped > 0) {
637 ImGui::SameLine();
638 ImGui::TextColored(ImVec4(0.6f, 0.8f, 1.0f, 1.0f),
639 "%zu entries were skipped", skipped);
640 skippedEntries_.store(0, std::memory_order_relaxed);
641 }
642 }
643 ImGui::End();
644 }

References clear, helios::ext::imgui::widgets::LogEntry::level, helios::ext::imgui::widgets::LogEntry::message, helios::ext::imgui::widgets::LogEntry::scope and helios::ext::imgui::widgets::LogEntry::timestamp.

entryCount()

std::size_t helios::ext::imgui::widgets::LogWidget::entryCount ()
inline nodiscard noexcept

Returns the current number of log entries in the active buffer.

Returns

The number of entries currently stored.

Definition at line 427 of file LogWidget.ixx.

427 [[nodiscard]] std::size_t entryCount() const noexcept {
428 std::lock_guard<std::mutex> lock(bufferMutex_);
429 return activeBuffer().size();
430 }

error()

void helios::ext::imgui::widgets::LogWidget::error (const std::string & scope, const std::string & message)
inline

Convenience method to add an error-level log entry.

Parameters
scope

The source scope or module name.

message

The log message text.

Definition at line 360 of file LogWidget.ixx.

360 void error(const std::string& scope, const std::string& message) {
361 addLog(LogLevel::Error, scope, message);
362 }

References addLog and helios::ext::imgui::widgets::Error.

info()

void helios::ext::imgui::widgets::LogWidget::info (const std::string & scope, const std::string & message)
inline

Convenience method to add an info-level log entry.

Parameters
scope

The source scope or module name.

message

The log message text.

Definition at line 340 of file LogWidget.ixx.

340 void info(const std::string& scope, const std::string& message) {
341 addLog(LogLevel::Info, scope, message);
342 }

References addLog and helios::ext::imgui::widgets::Info.

setAutoScroll()

void helios::ext::imgui::widgets::LogWidget::setAutoScroll (bool enabled)
inline noexcept

Enables or disables auto-scrolling to the latest entry.

Parameters
enabled

True to enable auto-scroll.

Definition at line 396 of file LogWidget.ixx.

396 void setAutoScroll(bool enabled) noexcept {
397 autoScroll_ = enabled;
398 }

setFilterLevel()

void helios::ext::imgui::widgets::LogWidget::setFilterLevel (LogLevel level)
inline noexcept

Sets the minimum log level to display.

Parameters
level

Entries below this level are hidden.

Definition at line 405 of file LogWidget.ixx.

405 void setFilterLevel(LogLevel level) noexcept {
406 filterLevel_ = level;
407 filterLevelIndex_ = static_cast<int>(level);
408 }

setMaxEntries()

void helios::ext::imgui::widgets::LogWidget::setMaxEntries (std::size_t max)
inline noexcept

Sets the maximum number of entries to retain per scope.

Parameters
max

The maximum buffer size.

Definition at line 378 of file LogWidget.ixx.

378 void setMaxEntries(std::size_t max) noexcept {
379 std::lock_guard<std::mutex> lock(bufferMutex_);
380 maxEntries_ = max;
381 // Trim all existing buffers
382 for (auto& [scope, buffer] : scopeBuffers_) {
383 if (maxEntries_ > 0 && buffer.size() > maxEntries_) {
384 const std::size_t overflow = buffer.size() - maxEntries_;
385 buffer.erase(buffer.begin(),
386 buffer.begin() + static_cast<std::ptrdiff_t>(overflow));
387 }
388 }
389 }

setScopeFilterCallback()

void helios::ext::imgui::widgets::LogWidget::setScopeFilterCallback (std::function< void(const std::string &)> callback)
inline

Sets a callback to be invoked when the scope filter changes.

The callback receives the selected scope string, or an empty string when "All" is selected. Use this to integrate with LogManager::setScopeFilter().

Parameters
callback

Function to call on scope filter change.

Definition at line 418 of file LogWidget.ixx.

418 void setScopeFilterCallback(std::function<void(const std::string&)> callback) {
419 onScopeFilterChanged_ = std::move(callback);
420 }

warn()

void helios::ext::imgui::widgets::LogWidget::warn (const std::string & scope, const std::string & message)
inline

Convenience method to add a warning-level log entry.

Parameters
scope

The source scope or module name.

message

The log message text.

Definition at line 350 of file LogWidget.ixx.

350 void warn(const std::string& scope, const std::string& message) {
351 addLog(LogLevel::Warn, scope, message);
352 }

References addLog and helios::ext::imgui::widgets::Warn.

Private Member Functions

activeBuffer()

const std::vector< LogEntry > & helios::ext::imgui::widgets::LogWidget::activeBuffer ()
inline nodiscard

Returns the currently active buffer based on scope selection.

Definition at line 208 of file LogWidget.ixx.

208 [[nodiscard]] const std::vector<LogEntry>& activeBuffer() const {
209 if (activeScopeFilter_.empty()) {
210 auto it = scopeBuffers_.find(ALL_SCOPES_KEY);
211 if (it != scopeBuffers_.end()) {
212 return it->second;
213 }
214 } else {
215 auto it = scopeBuffers_.find(activeScopeFilter_);
216 if (it != scopeBuffers_.end()) {
217 return it->second;
218 }
219 }
220 static const std::vector<LogEntry> empty;
221 return empty;
222 }

addToBuffer()

void helios::ext::imgui::widgets::LogWidget::addToBuffer (std::vector< LogEntry > & buffer, LogEntry entry)
inline

Adds an entry to a specific buffer, trimming if necessary.

Definition at line 196 of file LogWidget.ixx.

196 void addToBuffer(std::vector<LogEntry>& buffer, LogEntry entry) {
197 buffer.push_back(std::move(entry));
198 if (maxEntries_ > 0 && buffer.size() > maxEntries_) {
199 const std::size_t overflow = buffer.size() - maxEntries_;
200 buffer.erase(buffer.begin(),
201 buffer.begin() + static_cast<std::ptrdiff_t>(overflow));
202 }
203 }

collectScope()

void helios::ext::imgui::widgets::LogWidget::collectScope (const std::string & scope)
inline

Adds a scope to the collection if not already present.

Parameters
scope

The scope to add.

Definition at line 186 of file LogWidget.ixx.

186 void collectScope(const std::string& scope) {
187 for (const auto& existing : collectedScopes_) {
188 if (existing == scope) return;
189 }
190 collectedScopes_.push_back(scope);
191 }

Private Member Attributes

acceptNewEntries_

std::atomic<bool> helios::ext::imgui::widgets::LogWidget::acceptNewEntries_ {true}

Whether new entries are currently accepted into the buffer.

Definition at line 131 of file LogWidget.ixx.

131 std::atomic<bool> acceptNewEntries_{true};

activeScopeFilter_

std::string helios::ext::imgui::widgets::LogWidget::activeScopeFilter_

Currently active scope filter (empty = show all).

Definition at line 166 of file LogWidget.ixx.

166 std::string activeScopeFilter_;

autoScroll_

bool helios::ext::imgui::widgets::LogWidget::autoScroll_ = true

Whether to automatically scroll to the bottom on new entries.

Definition at line 106 of file LogWidget.ixx.

106 bool autoScroll_ = true;

bufferMutex_

std::mutex helios::ext::imgui::widgets::LogWidget::bufferMutex_
mutable

Mutex for thread-safe access to the log buffers.

Definition at line 101 of file LogWidget.ixx.

101 mutable std::mutex bufferMutex_;

collectedScopes_

std::vector<std::string> helios::ext::imgui::widgets::LogWidget::collectedScopes_

Collection of all unique scopes seen in log entries.

Definition at line 156 of file LogWidget.ixx.

156 std::vector<std::string> collectedScopes_;

filterLevel_

LogLevel helios::ext::imgui::widgets::LogWidget::filterLevel_ = LogLevel::Debug

Minimum log level to display (filters out lower levels).

Definition at line 141 of file LogWidget.ixx.

141 LogLevel filterLevel_ = LogLevel::Debug;

filterLevelIndex_

int helios::ext::imgui::widgets::LogWidget::filterLevelIndex_ = 0

Current filter level selection index for the combo box.

Definition at line 151 of file LogWidget.ixx.

151 int filterLevelIndex_ = 0;

loggingDisabled_

bool helios::ext::imgui::widgets::LogWidget::loggingDisabled_ = true

Whether logging is completely disabled (None selected).

Definition at line 171 of file LogWidget.ixx.

171 bool loggingDisabled_ = true;

maxEntries_

std::size_t helios::ext::imgui::widgets::LogWidget::maxEntries_ = 1000

Maximum number of entries to retain per scope buffer.

Definition at line 96 of file LogWidget.ixx.

96 std::size_t maxEntries_ = 1000;

onScopeFilterChanged_

std::function<void(const std::string&)> helios::ext::imgui::widgets::LogWidget::onScopeFilterChanged_

Callback function to notify external systems of scope filter changes.

Called when user selects a scope in the combo box. Signature: void(const std::string& scope) where empty string means "all".

Definition at line 179 of file LogWidget.ixx.

179 std::function<void(const std::string&)> onScopeFilterChanged_;

prevAutoScroll_

bool helios::ext::imgui::widgets::LogWidget::prevAutoScroll_ = true

Previous autoScroll state to detect toggle events.

Definition at line 111 of file LogWidget.ixx.

111 bool prevAutoScroll_ = true;

scopeBuffers_

std::unordered_map<std::string, std::vector<LogEntry> > helios::ext::imgui::widgets::LogWidget::scopeBuffers_

Per-scope log buffers. Key is scope name, value is entry vector.

Special key "__all__" contains all entries (for "All Scopes" view).

Definition at line 91 of file LogWidget.ixx.

91 std::unordered_map<std::string, std::vector<LogEntry>> scopeBuffers_;

scrollToBottom_

bool helios::ext::imgui::widgets::LogWidget::scrollToBottom_ = false

Flag to indicate that new content was added and scroll is needed.

Definition at line 121 of file LogWidget.ixx.

121 bool scrollToBottom_ = false;

scrollUpOneEntry_

bool helios::ext::imgui::widgets::LogWidget::scrollUpOneEntry_ = false

Flag to nudge scroll up one entry when auto-scroll is disabled.

Definition at line 116 of file LogWidget.ixx.

116 bool scrollUpOneEntry_ = false;

selectedScopeIndex_

int helios::ext::imgui::widgets::LogWidget::selectedScopeIndex_ = -1

Currently selected scope index in the combo box (0 = "All", -1 = "None").

Definition at line 161 of file LogWidget.ixx.

161 int selectedScopeIndex_ = -1;

skippedEntries_

std::atomic<std::size_t> helios::ext::imgui::widgets::LogWidget::skippedEntries_ {0}

Counts how many log entries were skipped while logging was paused.

Definition at line 136 of file LogWidget.ixx.

136 std::atomic<std::size_t> skippedEntries_{0};

textFilter_

ImGuiTextFilter helios::ext::imgui::widgets::LogWidget::textFilter_

Text filter for searching within log messages.

Definition at line 146 of file LogWidget.ixx.

146 ImGuiTextFilter textFilter_;

wasAtBottom_

bool helios::ext::imgui::widgets::LogWidget::wasAtBottom_ = true

Tracks if user was at bottom in the previous frame.

Definition at line 126 of file LogWidget.ixx.

126 bool wasAtBottom_ = true;

Private Static Functions

colorForLevel()

ImVec4 helios::ext::imgui::widgets::LogWidget::colorForLevel (LogLevel level)
inline nodiscard noexcept static

Returns an ImVec4 color for the given log level.

Parameters
level

The log level to get a color for.

Returns

The color corresponding to the log level.

Definition at line 231 of file LogWidget.ixx.

231 [[nodiscard]] static ImVec4 colorForLevel(LogLevel level) noexcept {
232 switch (level) {
233 case LogLevel::Debug: return ImVec4(0.6f, 0.6f, 0.6f, 1.0f); // Gray
234 case LogLevel::Info: return ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White
235 case LogLevel::Warn: return ImVec4(1.0f, 0.8f, 0.0f, 1.0f); // Yellow
236 case LogLevel::Error: return ImVec4(1.0f, 0.3f, 0.3f, 1.0f); // Red
237 default: return ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
238 }
239 }

currentTimestamp()

std::string helios::ext::imgui::widgets::LogWidget::currentTimestamp ()
inline nodiscard noexcept static

Generates a simple timestamp string (HH:MM:SS.mmm).

Returns

The current time formatted as "HH:MM:SS.mmm".

Definition at line 263 of file LogWidget.ixx.

263 [[nodiscard]] static std::string currentTimestamp() noexcept {
264 auto now = std::chrono::system_clock::now();
265 auto time_t_now = std::chrono::system_clock::to_time_t(now);
266 auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(
267 now.time_since_epoch()) % 1000;
268
269 std::tm tm_buf{};
270#ifdef _WIN32
271 localtime_s(&tm_buf, &time_t_now);
272#else
273 localtime_r(&time_t_now, &tm_buf);
274#endif
275 std::ostringstream oss;
276 oss << std::put_time(&tm_buf, "%H:%M:%S")
277 << '.' << std::setfill('0') << std::setw(3) << ms.count();
278 return oss.str();
279 }

labelForLevel()

const char * helios::ext::imgui::widgets::LogWidget::labelForLevel (LogLevel level)
inline nodiscard noexcept static

Returns a string label for the given log level.

Parameters
level

The log level to get a label for.

Returns

The label string (e.g., "[DEBUG]", "[INFO]").

Definition at line 248 of file LogWidget.ixx.

248 [[nodiscard]] static const char* labelForLevel(LogLevel level) noexcept {
249 switch (level) {
250 case LogLevel::Debug: return "[DEBUG]";
251 case LogLevel::Info: return "[INFO] ";
252 case LogLevel::Warn: return "[WARN] ";
253 case LogLevel::Error: return "[ERROR]";
254 default: return "[?????]";
255 }
256 }

Private Static Attributes

ALL_SCOPES_KEY

const char* helios::ext::imgui::widgets::LogWidget::ALL_SCOPES_KEY = "__all__"
constexpr static

Key for the "all scopes" combined view.

Definition at line 79 of file LogWidget.ixx.

79 static constexpr const char* ALL_SCOPES_KEY = "__all__";

NONE_SCOPES_KEY

const char* helios::ext::imgui::widgets::LogWidget::NONE_SCOPES_KEY = "__none__"
constexpr static

Key for the "none" option that disables logging.

Definition at line 84 of file LogWidget.ixx.

84 static constexpr const char* NONE_SCOPES_KEY = "__none__";

The documentation for this class was generated from the following file:


Generated via doxygen2docusaurus 2.0.0 by Doxygen 1.15.0.