using Sandbox.Html;
namespace Sandbox.UI;
///
/// This is a tree renderer for panels. If we ever use razor on other ui we'll want to make a copy of
/// this class and do the specific things to that.
///
public partial class PanelRenderTreeBuilder : Microsoft.AspNetCore.Components.Rendering.RenderTreeBuilder
{
///
/// Add markup to the current element
///
public override void AddMarkupContent( int sequence, string markupContent )
{
// Quick ignore for empty strings
if ( string.IsNullOrWhiteSpace( markupContent ) )
return;
var parent = CurrentScope.Element ?? Parent;
var scope = CurrentScope;
scope.Sequence = sequence;
scope.Loop = CurrentBlock.Increment( sequence );
scope.Hash = HashCode.Combine( scope.Loop, scope.Sequence );
var block = GetBlock( scope.Hash );
// already created - these are static so won't ever need changing
// but make sure they haven't been deleted and make sure their child order is correct
if ( block.MarkupPanels != null && block.MarkupPanels.All( x => x.IsValid ) )
{
foreach ( var panel in block.MarkupPanels )
{
Assert.True( panel.Parent == parent );
parent.SetChildIndex( panel, CurrentScope.ChildIndex );
CurrentScope.ChildIndex++;
}
return;
}
// Make sure we don't reach this point every again
block.MarkupPanels = new List();
// Don't create an element if it's just newlines and whitespace
if ( markupContent.All( x => char.IsWhiteSpace( x ) || x == '\n' || x == '\r' ) )
return;
FlushContent();
var root = Sandbox.Html.Node.Parse( markupContent );
if ( root.NodeType == Sandbox.Html.NodeType.Document )
{
foreach ( var e in root.ChildNodes )
{
var panel = CreateNodeMarkup( e, parent );
if ( panel != null )
{
block.MarkupPanels.Add( panel );
parent.SetChildIndex( panel, CurrentScope.ChildIndex );
panel.SourceFile = sourceFile;
panel.SourceLine = sourceLine;
CurrentScope.ChildIndex++;
}
}
}
return;
}
Panel CreateNodeMarkup( Sandbox.Html.Node node, Panel parent )
{
if ( node.NodeType == Sandbox.Html.NodeType.Element )
{
var panel = Game.TypeLibrary.Create( node.Name, false ) ?? new Panel();
panel.ElementName = node.Name;
panel.Parent = parent;
panel.SourceFile = sourceFile;
panel.SourceLine = sourceLine;
string slot = null;
foreach ( var attr in node.Attributes )
{
if ( attr.Name == "slot" )
{
slot = attr.Value;
continue;
}
panel.SetProperty( attr.Name, attr.Value );
}
foreach ( var e in node.ChildNodes )
{
CreateNodeMarkup( e, panel );
}
if ( slot != null )
{
panel.Parent?.OnTemplateSlot( node, slot, panel );
}
return panel;
}
if ( node is TextNode textNode )
{
// Don't bother with empty content
var content = textNode.InnerHtml;
if ( string.IsNullOrWhiteSpace( content ) )
return null;
if ( parent is Label )
{
parent.SetContent( content );
return null;
}
else
{
var panel = Game.TypeLibrary.Create( "label", false ) ?? new Panel();
panel.Parent = parent;
panel.SetContent( content );
return panel;
}
}
return null;
}
}