initial commit
This commit is contained in:
@@ -0,0 +1,209 @@
|
||||
class_name LogBuffer extends RichTextLabel
|
||||
|
||||
## Enhanced message buffer with retroactive filtering capabilities
|
||||
## Stores all messages and applies filters dynamically without losing data
|
||||
|
||||
const LoggieConsoleSettings = preload("res://addons/loggie-console/resources/loggie_console_settings.gd")
|
||||
const DomainColorManager = preload("res://addons/loggie-console/scripts/domain_color_manager.gd")
|
||||
|
||||
# Signals
|
||||
signal filter_changed(visible_count: int, total_count: int)
|
||||
|
||||
# Internal message storage
|
||||
var _all_messages: Array[LogMessage] = []
|
||||
var _filtered_messages: Array[LogMessage] = []
|
||||
var _current_filters: FilterState
|
||||
|
||||
# Domain color manager reference
|
||||
var _color_manager: DomainColorManager
|
||||
|
||||
# Memory management constants
|
||||
const DEFAULT_MAX_MESSAGES: int = 5000
|
||||
const CLEANUP_PERCENTAGE: float = 0.2 # Remove 20% of messages when limit reached
|
||||
|
||||
# Memory management
|
||||
@export var max_messages: int = DEFAULT_MAX_MESSAGES
|
||||
|
||||
## Internal LogMessage class for storing complete message data
|
||||
class LogMessage:
|
||||
var msg: LoggieMsg
|
||||
var preprocessed_content: String
|
||||
var msg_type: LoggieEnums.MsgType
|
||||
var log_level: LoggieEnums.LogLevel
|
||||
var timestamp: float
|
||||
var enhanced_content: String
|
||||
|
||||
func _init(p_msg: LoggieMsg, p_content: String, p_type: LoggieEnums.MsgType, p_level: LoggieEnums.LogLevel) -> void:
|
||||
msg = p_msg
|
||||
preprocessed_content = p_content
|
||||
msg_type = p_type
|
||||
log_level = p_level
|
||||
timestamp = Time.get_unix_time_from_system()
|
||||
|
||||
## Filter state for retroactive filtering
|
||||
class FilterState:
|
||||
var enabled_domains: Array[String] = []
|
||||
var min_log_level: LoggieEnums.LogLevel = LoggieEnums.LogLevel.DEBUG
|
||||
var text_search: String = ""
|
||||
var show_stack_only: bool = false
|
||||
|
||||
func _init() -> void:
|
||||
# Initialize to show ERROR and above by default (lower numbers = higher priority)
|
||||
min_log_level = LoggieEnums.LogLevel.DEBUG
|
||||
|
||||
func _ready() -> void:
|
||||
_current_filters = FilterState.new()
|
||||
bbcode_enabled = true
|
||||
|
||||
## Set the domain color manager instance
|
||||
func set_color_manager(color_manager: DomainColorManager) -> void:
|
||||
_color_manager = color_manager
|
||||
|
||||
## Add a new log message to the buffer
|
||||
func add_message(msg: LoggieMsg, content: String, msg_type: LoggieEnums.MsgType, log_level: LoggieEnums.LogLevel) -> void:
|
||||
# Create and store the message
|
||||
var log_msg: LogMessage = LogMessage.new(msg, content, msg_type, log_level)
|
||||
log_msg.enhanced_content = _enhance_with_metadata(log_msg)
|
||||
|
||||
_all_messages.append(log_msg)
|
||||
|
||||
# Manage memory if needed
|
||||
_manage_memory()
|
||||
|
||||
# Apply current filters and rebuild display
|
||||
_reapply_filters()
|
||||
|
||||
## Set new filter state and reapply filters
|
||||
func set_filters(filter_state: FilterState) -> void:
|
||||
_current_filters = filter_state
|
||||
_reapply_filters()
|
||||
|
||||
## Set text search filter
|
||||
func set_text_search(search: String) -> void:
|
||||
if _current_filters.text_search == search:
|
||||
return
|
||||
|
||||
_current_filters.text_search = search
|
||||
_reapply_filters()
|
||||
|
||||
## Clear all messages
|
||||
func clear_all() -> void:
|
||||
_all_messages.clear()
|
||||
_filtered_messages.clear()
|
||||
text = ""
|
||||
clear()
|
||||
|
||||
# Emit updated counts
|
||||
filter_changed.emit(0, 0)
|
||||
|
||||
## Get current message counts
|
||||
func get_message_counts() -> Dictionary:
|
||||
return {
|
||||
"total": _all_messages.size(),
|
||||
"filtered": _filtered_messages.size()
|
||||
}
|
||||
|
||||
## Saves current buffer state to persistent settings resource
|
||||
## Param settings: The settings resource to populate with current state
|
||||
func save_settings_to_resource(settings: LoggieConsoleSettings) -> void:
|
||||
settings.filter_state.from_filter_state(_current_filters)
|
||||
settings.max_messages = max_messages
|
||||
|
||||
## Loads buffer state from persistent settings resource
|
||||
## Note: Does not immediately apply filters to avoid triggering reapply before messages exist
|
||||
## Param settings: The settings resource containing saved state
|
||||
func load_settings_from_resource(settings: LoggieConsoleSettings) -> void:
|
||||
if settings.filter_state:
|
||||
_current_filters = settings.filter_state.to_filter_state()
|
||||
max_messages = settings.max_messages
|
||||
|
||||
## Applies previously loaded filter state to existing messages
|
||||
## Call this after load_settings_from_resource() and message loading is complete
|
||||
func apply_loaded_filters() -> void:
|
||||
_reapply_filters()
|
||||
|
||||
|
||||
## Private methods
|
||||
|
||||
func _reapply_filters() -> void:
|
||||
_filtered_messages.clear()
|
||||
|
||||
for msg in _all_messages:
|
||||
if msg != null and _message_passes_filters(msg, _current_filters):
|
||||
_filtered_messages.append(msg)
|
||||
|
||||
_rebuild_display()
|
||||
|
||||
# Emit filter change signal
|
||||
filter_changed.emit(_filtered_messages.size(), _all_messages.size())
|
||||
|
||||
func _message_passes_filters(msg: LogMessage, filters: FilterState) -> bool:
|
||||
# Domain check - if no domains are enabled, show no messages
|
||||
if filters.enabled_domains.size() == 0:
|
||||
return false
|
||||
|
||||
# If domains are enabled, check if this message's domain is in the enabled list
|
||||
if not filters.enabled_domains.has(msg.msg.domain_name):
|
||||
return false
|
||||
|
||||
# Level check - show messages at or above the minimum level (lower numbers = higher priority)
|
||||
if msg.log_level > filters.min_log_level:
|
||||
return false
|
||||
|
||||
# Text search
|
||||
if not filters.text_search.is_empty():
|
||||
var search_lower: String = filters.text_search.to_lower()
|
||||
if not msg.preprocessed_content.to_lower().contains(search_lower):
|
||||
return false
|
||||
|
||||
# Stack filter
|
||||
if filters.show_stack_only and not msg.msg.appends_stack:
|
||||
return false
|
||||
|
||||
return true
|
||||
|
||||
func _rebuild_display() -> void:
|
||||
# Clear current display
|
||||
text = ""
|
||||
clear()
|
||||
|
||||
# Add all filtered messages
|
||||
for msg in _filtered_messages:
|
||||
text += msg.enhanced_content + "\n"
|
||||
|
||||
func _enhance_with_metadata(msg: LogMessage) -> String:
|
||||
var metadata_parts: Array[String] = []
|
||||
|
||||
metadata_parts.append("[color=%s]%s [/color]" % [Color.DIM_GRAY.to_html(false), Time.get_time_string_from_unix_time(int(msg.timestamp))])
|
||||
|
||||
if msg.msg.domain_name and not msg.msg.domain_name.is_empty():
|
||||
var domain_color_html: String = _color_manager.get_domain_color_html(msg.msg.domain_name)
|
||||
metadata_parts.append("[color=%s]%s[/color]" % [domain_color_html, msg.msg.domain_name])
|
||||
|
||||
if msg.msg.domain_name and not msg.msg.domain_name.is_empty():
|
||||
metadata_parts.append("[color=%s][%s] [/color]" % [_get_color_for_log_level(msg.log_level).to_html(false), LoggieEnums.LogLevel.keys()[msg.log_level]])
|
||||
|
||||
return "%s %s" % [" ".join(metadata_parts), msg.msg.content[0]]
|
||||
|
||||
func _get_color_for_log_level(level: LoggieEnums.LogLevel) -> Color:
|
||||
match level:
|
||||
LoggieEnums.LogLevel.ERROR:
|
||||
return Color.RED
|
||||
LoggieEnums.LogLevel.WARN:
|
||||
return Color.ORANGE
|
||||
LoggieEnums.LogLevel.NOTICE:
|
||||
return Color.GREEN
|
||||
LoggieEnums.LogLevel.INFO:
|
||||
return Color.WHITE
|
||||
LoggieEnums.LogLevel.DEBUG, _:
|
||||
return Color.AQUA
|
||||
|
||||
## Manages memory by removing oldest messages when buffer limit exceeded
|
||||
## Uses CLEANUP_PERCENTAGE constant to determine how many messages to remove
|
||||
func _manage_memory() -> void:
|
||||
if _all_messages.size() > max_messages:
|
||||
# Remove oldest messages based on cleanup percentage
|
||||
var remove_count: int = int(max_messages * CLEANUP_PERCENTAGE)
|
||||
_all_messages = _all_messages.slice(remove_count)
|
||||
# Note: This will cause filtered_messages indices to be invalid,
|
||||
# but _reapply_filters() will be called which rebuilds it
|
||||
Reference in New Issue
Block a user