class_name DomainSelector extends MenuButton ## Standalone domain selector component for filtering log messages by domain ## Provides clean interface with proper signal-based communication 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 domains_changed(enabled_domains: Array[String]) # Properties var _enabled_domains: Array[String] = [] var _all_domains: Array[String] = [] var _domain_popup: PopupMenu var _color_manager: DomainColorManager # Constants const ALL_ITEM_ID = 0 const SEPARATOR_ID = 1 const DOMAIN_ID_OFFSET = 2 func _ready() -> void: _domain_popup = get_popup() _domain_popup.id_pressed.connect(_on_domain_selected) _initialize_empty_state() ## Set the domain color manager instance func set_color_manager(color_manager: DomainColorManager) -> void: _color_manager = color_manager ## Initialize the selector with available domains func set_domains(domains: Array[String]) -> void: _all_domains = domains.duplicate() _enabled_domains = domains.duplicate() _rebuild_popup() _update_button_text() domains_changed.emit(_enabled_domains) ## Initialize the selector with all domains, but only enable selected ones ## Console domains appear normally but are unselected by default func set_domains_with_console_unselected(all_domains: Array[String], enabled_domains: Array[String], console_domains: Array[String]) -> void: _all_domains = all_domains.duplicate() _enabled_domains = enabled_domains.duplicate() _rebuild_popup_with_console_unselected(console_domains) _update_button_text() domains_changed.emit(_enabled_domains) ## Add a new domain to the selector (for dynamic discovery) func add_domain(domain_name: String) -> void: if domain_name.is_empty() or _all_domains.has(domain_name): return _all_domains.append(domain_name) _enabled_domains.append(domain_name) # Add new item to popup with color icon var display_name = _get_domain_display_name(domain_name) var color_icon = _create_domain_color_icon(domain_name) var item_id = _get_domain_item_id(_all_domains.size() - 1) _domain_popup.add_check_item(display_name, item_id) _domain_popup.set_item_icon(item_id, color_icon) _domain_popup.set_item_checked(item_id, true) _update_all_checkbox() _update_button_text() domains_changed.emit(_enabled_domains) ## Get currently enabled domains func get_enabled_domains() -> Array[String]: return _enabled_domains.duplicate() ## Check if a domain is enabled func is_domain_enabled(domain_name: String) -> bool: return _enabled_domains.has(domain_name) ## Private methods ## Create colored icon for domain display in popup func _create_domain_color_icon(domain_name: String, size: int = 12) -> ImageTexture: var color: Color = Color.WHITE # Default color if _color_manager: color = _color_manager.get_domain_color(domain_name) # Create a small colored square image var image = Image.create(size, size, false, Image.FORMAT_RGBA8) image.fill(color) # Convert to texture var texture: ImageTexture = ImageTexture.create_from_image(image) return texture ## Get display name for domain (without color formatting) func _get_domain_display_name(domain_name: String) -> String: return domain_name if not domain_name.is_empty() else "(default)" func _initialize_empty_state() -> void: _domain_popup.clear() _domain_popup.add_item("No domains available") _domain_popup.set_item_disabled(0, true) text = "Domains: None" func _rebuild_popup() -> void: _domain_popup.clear() # Add "All" toggle _domain_popup.add_check_item("All", ALL_ITEM_ID) _domain_popup.set_item_checked(ALL_ITEM_ID, _enabled_domains.size() == _all_domains.size()) # Add separator _domain_popup.add_separator() # Add individual domain items with color icons for i in range(_all_domains.size()): var domain_name = _all_domains[i] var display_name = _get_domain_display_name(domain_name) var color_icon = _create_domain_color_icon(domain_name) var item_id = _get_domain_item_id(i) _domain_popup.add_check_item(display_name, item_id) _domain_popup.set_item_icon(item_id, color_icon) _domain_popup.set_item_checked(item_id, _enabled_domains.has(domain_name)) ## Builds popup with console domain unselected by default (no separator) func _rebuild_popup_with_console_unselected(console_domains: Array[String]) -> void: _domain_popup.clear() # Add "All" toggle (only for non-console domains) _domain_popup.add_check_item("All", ALL_ITEM_ID) var non_console_domains = [] for domain in _all_domains: if not console_domains.has(domain): non_console_domains.append(domain) _domain_popup.set_item_checked(ALL_ITEM_ID, _enabled_domains.size() == non_console_domains.size()) # Add separator _domain_popup.add_separator() # Add all domain items in order with color icons for i in range(_all_domains.size()): var domain_name = _all_domains[i] var display_name: String # Use friendly name for console domain if console_domains.has(domain_name): display_name = "LoggieConsole" # Simplified name for console domain else: display_name = domain_name if not domain_name.is_empty() else "(default)" # Create color icon for the domain var color_icon = _create_domain_color_icon(domain_name) var item_id = _get_domain_item_id(i) _domain_popup.add_check_item(display_name, item_id) _domain_popup.set_item_icon(item_id, color_icon) _domain_popup.set_item_checked(item_id, _enabled_domains.has(domain_name)) func _on_domain_selected(id: int) -> void: if id == ALL_ITEM_ID: _toggle_all_domains() else: _toggle_individual_domain(id) _update_all_checkbox() _update_button_text() domains_changed.emit(_enabled_domains) func _toggle_all_domains() -> void: var current_all_state = _domain_popup.is_item_checked(ALL_ITEM_ID) var new_all_state = not current_all_state # Update all checkbox _domain_popup.set_item_checked(ALL_ITEM_ID, new_all_state) # Update all domain checkboxes and enabled list _enabled_domains.clear() for i in range(_all_domains.size()): var item_id = _get_domain_item_id(i) _domain_popup.set_item_checked(item_id, new_all_state) if new_all_state: _enabled_domains.append(_all_domains[i]) func _toggle_individual_domain(id: int) -> void: var domain_index = _get_domain_index_from_id(id) if domain_index < 0 or domain_index >= _all_domains.size(): Loggie.msg("Invalid domain index %d for ID %d" % [domain_index, id]).domain(LoggieConsoleConstants.DOMAIN).warn() return var domain_name = _all_domains[domain_index] var current_state = _domain_popup.is_item_checked(id) var new_state = not current_state # Update checkbox _domain_popup.set_item_checked(id, new_state) # Update enabled domains list if new_state and not _enabled_domains.has(domain_name): _enabled_domains.append(domain_name) elif not new_state and _enabled_domains.has(domain_name): _enabled_domains.erase(domain_name) func _update_all_checkbox() -> void: var all_enabled = _enabled_domains.size() == _all_domains.size() _domain_popup.set_item_checked(ALL_ITEM_ID, all_enabled) func _update_button_text() -> void: var enabled_count = _enabled_domains.size() var total_count = _all_domains.size() if total_count == 0: text = "Domains: None" elif enabled_count == total_count: text = "Domains: All" elif enabled_count == 0: text = "Domains: None" elif enabled_count == 1: var domain_name = _enabled_domains[0] var display_name = _get_domain_display_name(domain_name) text = "Domains: " + display_name else: text = "Domains: %d selected" % enabled_count func _get_domain_item_id(domain_index: int) -> int: return DOMAIN_ID_OFFSET + domain_index func _get_domain_index_from_id(item_id: int) -> int: return item_id - DOMAIN_ID_OFFSET ## Saves current domain selection state to persistent settings ## Param settings: The settings resource to populate with current domain state func save_settings_to_resource(settings: LoggieConsoleSettings) -> void: settings.enabled_domains = _enabled_domains.duplicate() settings.all_known_domains = _all_domains.duplicate() ## Loads domain selection state from persistent settings and rebuilds UI ## Automatically validates that enabled domains still exist in the known domains list ## Param settings: The settings resource containing saved domain state func load_settings_from_resource(settings: LoggieConsoleSettings) -> void: _all_domains = settings.all_known_domains.duplicate() _enabled_domains = settings.enabled_domains.duplicate() # Remove any enabled domains that no longer exist in all_domains var valid_enabled_domains: Array[String] = [] for domain in _enabled_domains: if _all_domains.has(domain): valid_enabled_domains.append(domain) _enabled_domains = valid_enabled_domains # Rebuild UI to reflect loaded state if _all_domains.size() > 0: _rebuild_popup() _update_button_text() else: _initialize_empty_state()