// 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; } } }