Extensions/EventExtensions.cs
using System;
using System.Linq;

namespace BetterUI.Extensions;

/// <summary>
/// Extensions for <see cref="Scene"/> and <see cref="Panel"/>.
/// </summary>
public static class EventExtensions
{
	/// <summary>
	/// Runs an event on all components of type T within the scene, that have been enabled.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="scene"></param>
	/// <param name="action">The action to run on each component</param>
	/// <param name="include">Whether to include components, panels, or all entities</param>
	public static void RunSceneEvent<T>( this Scene scene, Action<T> action,
		EventInclude include = EventInclude.ComponentAndPanel )
	{
		var components = scene.Components.GetAll( FindMode.EnabledInSelfAndDescendants ).ToList();

		foreach ( var c in components )
		{
			try
			{
				if ( include.HasFlag( EventInclude.Component ) && c is T t )
					action( t );

				if ( include.HasFlag( EventInclude.Panel ) && c is PanelComponent component )
					component.RunPanelEvent( action );
			}
			catch ( Exception e )
			{
				Log.Error( e, e.Message );
			}
		}
	}

	/// <summary>
	/// Runs an event on all components of type T within the panel, that have been enabled.
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="panel">The panel.</param>
	/// <param name="action">The action to run on each component</param>
	/// <param name="include">Whether to include components, panels, or all entities</param>
	public static void RunEvent<T>( this Panel panel, Action<T> action,
		EventInclude include = EventInclude.ComponentAndPanel )
	{
		panel.Scene.RunSceneEvent( action, include );
	}

	/// <summary>
	/// Runs an event on all components of type T within a panel
	/// </summary>
	/// <typeparam name="T"></typeparam>
	/// <param name="component"></param>
	/// <param name="action"></param>
	/// <exception cref="Exception"></exception>
	private static void RunPanelEvent<T>( this PanelComponent component, Action<T> action )
	{
		var panels = component.Panel.Descendants.OfType<T>().ToList();

		foreach ( var c in panels )
		{
			try
			{
				action( c );
			}
			catch ( Exception e )
			{
				Log.Error( e, e.Message );
			}
		}
	}
}