Ejemplo n.º 1
0
        private void InsertElement(RenderBatch batch, ContainerNode parent, int childIndex, ArraySegment <RenderTreeFrame> frames, RenderTreeFrame frame, int frameIndex)
        {
            // Note: we don't handle SVG here
            var newElement = new ElementNode(frame.ElementName);

            parent.InsertLogicalChild(newElement, childIndex);

            // Apply attributes
            for (var i = frameIndex + 1; i < frameIndex + frame.ElementSubtreeLength; i++)
            {
                var descendantFrame = batch.ReferenceFrames.Array[i];
                if (descendantFrame.FrameType == RenderTreeFrameType.Attribute)
                {
                    ApplyAttribute(batch, newElement, descendantFrame);
                }
                else
                {
                    // As soon as we see a non-attribute child, all the subsequent child frames are
                    // not attributes, so bail out and insert the remnants recursively
                    InsertFrameRange(batch, newElement, 0, frames, i, frameIndex + frame.ElementSubtreeLength);
                    break;
                }
            }
        }
Ejemplo n.º 2
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}'");
                }
                }
            }
        }