Code/SectionOutlet.razor.cs
using System;
using System.Collections.Generic;
using System.Linq;
using Sandbox.Diagnostics;
namespace BetterUI;
/// <summary>
/// A panel that acts as an outlet for sections.
/// </summary>
/// <remarks>
/// The <see cref="SectionOutlet"/> is a panel that can be used as a placeholder for
/// sections that are defined elsewhere in code. It is used in conjunction with the
/// <see cref="SectionContent"/> panel to define sections of content that can be
/// rendered in multiple places in the UI.
/// </remarks>
public sealed partial class SectionOutlet : Panel
{
/// <summary>
/// The name of the section to render.
/// </summary>
public string SectionName { get; set; } = null!;
protected override void OnAfterTreeRender( bool firstTime )
{
Assert.NotNull( SectionName, "SectionName must be set" );
IterateChildren( FindRootPanel().Descendants );
}
/// <summary>
/// Iterates over the provided panels and sets the child content
/// for each section outlet that matches the section name.
/// </summary>
/// <param name="panels">The panels to iterate over.</param>
private void IterateChildren( IEnumerable<Panel> panels )
{
foreach ( var panel in panels )
{
var sections = FindSectionOutlets( panel );
foreach ( var section in sections )
section.ChildContent = ChildContent;
}
}
/// <summary>
/// Finds all section outlets within the panel that match the section name.
/// </summary>
/// <param name="panel">The panel to search within.</param>
/// <returns>A list of matching section outlets.</returns>
private List<SectionContent> FindSectionOutlets( Panel panel ) =>
panel.Descendants.OfType<SectionContent>().Where( x => x.SectionName == SectionName ).ToList();
protected override int BuildHash() => HashCode.Combine( SectionName );
}