internal void ApplyEdits(int componentId, ArrayBuilderSegment <RenderTreeEdit> edits, ArrayRange <RenderTreeFrame> referenceFrames, RenderBatch batch)
        {
            Renderer.Dispatcher.AssertAccess();

            if (edits.Count == 0)
            {
                // TODO: Without this check there's a NullRef in ArrayBuilderSegment? Possibly a Blazor bug?
                return;
            }

            foreach (var edit in edits)
            {
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                    ApplyPrependFrame(batch, componentId, edit.SiblingIndex, referenceFrames.Array, edit.ReferenceFrameIndex);
                    break;

                case RenderTreeEditType.RemoveFrame:
                    ApplyRemoveFrame(edit.SiblingIndex);
                    break;

                case RenderTreeEditType.SetAttribute:
                    ApplySetAttribute(ref referenceFrames.Array[edit.ReferenceFrameIndex]);
                    break;

                case RenderTreeEditType.RemoveAttribute:
                    // TODO: See whether siblingIndex is needed here
                    ApplyRemoveAttribute(edit.RemovedAttributeName);
                    break;

                case RenderTreeEditType.UpdateText:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                case RenderTreeEditType.StepIn:
                {
                    // TODO: Need to implement this. For now it seems safe to ignore.
                    break;
                }

                case RenderTreeEditType.StepOut:
                {
                    // TODO: Need to implement this. For now it seems safe to ignore.
                    break;
                }

                case RenderTreeEditType.UpdateMarkup:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                case RenderTreeEditType.PermutationListEntry:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                case RenderTreeEditType.PermutationListEnd:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                default:
                    throw new NotImplementedException($"Invalid edit type: {edit.Type}");
                }
            }
        }
Example #2
0
 internal RenderTreeDiff(
     int componentId,
     ArrayBuilderSegment <RenderTreeEdit> entries)
 {
     ComponentId = componentId;
     Edits       = entries;
 }
Example #3
0
        private void UpdateComponent(RenderBatch batch, int componentId, ArrayBuilderSegment <RenderTreeEdit> edits)
        {
            if (!Components.TryGetValue(componentId, out var component))
            {
                component = new ComponentNode(componentId);
                Components.Add(componentId, component);
            }

            ApplyEdits(batch, component, 0, edits);
        }
Example #4
0
        private void ApplyEdits(RenderBatch batch, ContainerNode parent, int childIndex, ArrayBuilderSegment <RenderTreeEdit> edits)
        {
            var currentDepth             = 0;
            var childIndexAtCurrentDepth = childIndex;
            var permutations             = new List <PermutationListEntry>();

            for (var editIndex = edits.Offset; editIndex < edits.Offset + edits.Count; editIndex++)
            {
                var edit = edits.Array[editIndex];
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    InsertFrame(batch, parent, childIndexAtCurrentDepth + siblingIndex, batch.ReferenceFrames.Array, frame, edit.ReferenceFrameIndex);
                    break;
                }

                case RenderTreeEditType.RemoveFrame:
                {
                    var siblingIndex = edit.SiblingIndex;
                    parent.RemoveLogicalChild(childIndexAtCurrentDepth + siblingIndex);
                    break;
                }

                case RenderTreeEditType.SetAttribute:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    var node         = parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    if (node is ElementNode element)
                    {
                        ApplyAttribute(batch, element, frame);
                    }
                    else
                    {
                        throw new Exception("Cannot set attribute on non-element child");
                    }
                    break;
                }

                case RenderTreeEditType.RemoveAttribute:
                {
                    // Note that we don't have to dispose the info we track about event handlers here, because the
                    // disposed event handler IDs are delivered separately (in the 'disposedEventHandlerIds' array)
                    var siblingIndex = edit.SiblingIndex;
                    var node         = parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    if (node is ElementNode element)
                    {
                        var attributeName = edit.RemovedAttributeName;

                        // First try to remove any special property we use for this attribute
                        if (!TryApplySpecialProperty(batch, element, attributeName, default))
                        {
                            // If that's not applicable, it's a regular DOM attribute so remove that
                            element.RemoveAttribute(attributeName);
                        }
                    }
                    else
                    {
                        throw new Exception("Cannot remove attribute from non-element child");
                    }
                    break;
                }

                case RenderTreeEditType.UpdateText:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    var node         = parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    if (node is TextNode textNode)
                    {
                        textNode.TextContent = frame.TextContent;
                    }
                    else
                    {
                        throw new Exception("Cannot set text content on non-text child");
                    }
                    break;
                }


                case RenderTreeEditType.UpdateMarkup:
                {
                    var frame        = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    var siblingIndex = edit.SiblingIndex;
                    parent.RemoveLogicalChild(childIndexAtCurrentDepth + siblingIndex);
                    InsertMarkup(parent, childIndexAtCurrentDepth + siblingIndex, frame);
                    break;
                }

                case RenderTreeEditType.StepIn:
                {
                    var siblingIndex = edit.SiblingIndex;
                    parent = (ContainerNode)parent.Children[childIndexAtCurrentDepth + siblingIndex];
                    currentDepth++;
                    childIndexAtCurrentDepth = 0;
                    break;
                }

                case RenderTreeEditType.StepOut:
                {
                    parent = parent.Parent;
                    currentDepth--;
                    childIndexAtCurrentDepth = currentDepth == 0 ? childIndex : 0;         // The childIndex is only ever nonzero at zero depth
                    break;
                }

                case RenderTreeEditType.PermutationListEntry:
                {
                    permutations.Add(new PermutationListEntry(childIndexAtCurrentDepth + edit.SiblingIndex, childIndexAtCurrentDepth + edit.MoveToSiblingIndex));
                    break;
                }

                case RenderTreeEditType.PermutationListEnd:
                {
                    throw new NotSupportedException();
                    //permuteLogicalChildren(parent, permutations!);
                    //permutations.Clear();
                    //break;
                }

                default:
                {
                    throw new Exception($"Unknown edit type: '{edit.Type}'");
                }
                }
            }
        }
Example #5
0
        internal void ApplyEdits(int componentId, ArrayBuilderSegment <RenderTreeEdit> edits, ArrayRange <RenderTreeFrame> referenceFrames, RenderBatch batch, HashSet <int> processedComponentIds)
        {
            Renderer.Dispatcher.AssertAccess();

            foreach (var edit in edits)
            {
                switch (edit.Type)
                {
                case RenderTreeEditType.PrependFrame:
                    ApplyPrependFrame(batch, componentId, edit.SiblingIndex, referenceFrames.Array, edit.ReferenceFrameIndex, processedComponentIds);
                    break;

                case RenderTreeEditType.RemoveFrame:
                    ApplyRemoveFrame(edit.SiblingIndex);
                    break;

                case RenderTreeEditType.SetAttribute:
                    ApplySetAttribute(ref referenceFrames.Array[edit.ReferenceFrameIndex]);
                    break;

                case RenderTreeEditType.RemoveAttribute:
                    // TODO: See whether siblingIndex is needed here
                    ApplyRemoveAttribute(edit.RemovedAttributeName);
                    break;

                case RenderTreeEditType.UpdateText:
                {
                    var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    if (_targetElement is IHandleChildContentText handleChildContentText)
                    {
                        handleChildContentText.HandleText(edit.SiblingIndex, frame.TextContent);
                    }
                    else if (!string.IsNullOrWhiteSpace(frame.TextContent))
                    {
                        throw new Exception("Cannot set text content on child that doesn't handle inner text content.");
                    }
                    break;
                }

                case RenderTreeEditType.StepIn:
                {
                    // TODO: Need to implement this. For now it seems safe to ignore.
                    break;
                }

                case RenderTreeEditType.StepOut:
                {
                    // TODO: Need to implement this. For now it seems safe to ignore.
                    break;
                }

                case RenderTreeEditType.UpdateMarkup:
                {
                    var frame = batch.ReferenceFrames.Array[edit.ReferenceFrameIndex];
                    if (_targetElement is IHandleChildContentText handleChildContentText)
                    {
                        handleChildContentText.HandleText(edit.SiblingIndex, frame.MarkupContent);
                    }
                    else if (!string.IsNullOrWhiteSpace(frame.MarkupContent))
                    {
                        throw new Exception("Cannot set markup content on child that doesn't handle inner text content.");
                    }
                    break;
                }

                case RenderTreeEditType.PermutationListEntry:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                case RenderTreeEditType.PermutationListEnd:
                    throw new NotImplementedException($"Not supported edit type: {edit.Type}");

                default:
                    throw new NotImplementedException($"Invalid edit type: {edit.Type}");
                }
            }
        }