// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using Microsoft.AspNetCore.Blazor.Browser.Interop;
using Microsoft.AspNetCore.Blazor.Components;
using Microsoft.AspNetCore.Blazor.Rendering;
using Microsoft.AspNetCore.Blazor.RenderTree;
using System;
using System.Collections.Generic;
namespace Microsoft.AspNetCore.Blazor.Browser.Rendering
{
///
/// Provides mechanisms for rendering instances in a
/// web browser, dispatching events to them, and refreshing the UI as required.
///
public class BrowserRenderer : Renderer, IDisposable
{
private readonly int _browserRendererId;
// Ensures the explicitly-added components aren't GCed, because the browser
// will still send events referencing them by ID. We only need to store the
// top-level components, because the associated ComponentState will reference
// all the reachable descendant components of each.
private IList _rootComponents = new List();
///
/// Constructs an instance of .
///
public BrowserRenderer()
{
_browserRendererId = BrowserRendererRegistry.Add(this);
}
internal void DispatchBrowserEvent(int componentId, int renderTreeIndex, UIEventArgs eventArgs)
=> DispatchEvent(componentId, renderTreeIndex, eventArgs);
internal void RenderComponentInternal(int componentId)
=> RenderComponent(componentId);
///
/// Associates the with the ,
/// causing it to be displayed in the specified DOM element.
///
/// A CSS selector that uniquely identifies a DOM element.
/// The .
public void AddComponent(string domElementSelector, IComponent component)
{
var componentId = AssignComponentId(component);
RegisteredFunction.InvokeUnmarshalled(
"attachComponentToElement",
_browserRendererId,
domElementSelector,
componentId);
_rootComponents.Add(component);
RenderComponent(componentId);
}
///
/// Disposes the instance.
///
public void Dispose()
{
BrowserRendererRegistry.TryRemove(_browserRendererId);
}
///
protected override void UpdateDisplay(
int componentId,
RenderTreeDiff renderTreeDiff)
{
RegisteredFunction.InvokeUnmarshalled(
"renderRenderTree",
new RenderComponentArgs
{
BrowserRendererId = _browserRendererId,
ComponentId = componentId,
RenderTreeEdits = renderTreeDiff.Edits.Array,
RenderTreeEditsLength = renderTreeDiff.Edits.Count,
RenderTree = renderTreeDiff.CurrentState.Array
});
}
// Encapsulates the data we pass to the JS rendering function
private struct RenderComponentArgs
{
// Important: If you edit this struct, keep it in sync with RenderComponentArgs.ts
public int BrowserRendererId;
public int ComponentId;
public RenderTreeEdit[] RenderTreeEdits;
public int RenderTreeEditsLength;
public RenderTreeNode[] RenderTree;
}
}
}