Ejemplo n.º 1
0
        // ReSharper disable once NotNullMemberIsNotInitialized
        public MarkupNodeReference(MarkupCollection owner, IMarkupDescriptor descriptor, IMarkupData associatedData)
        {
            Owner          = owner;
            Descriptor     = descriptor;
            AssociatedData = associatedData;

            Markup = new Markup(this);
        }
        /// <summary> Marks the given range to have the given markup and data. </summary>
        /// <exception cref="ArgumentOutOfRangeException"> Thrown when one or more arguments are outside
        ///  the required range. </exception>
        /// <param name="range"> The range of text to mark. </param>
        /// <param name="descriptor"> The type of markup to apply to the range. </param>
        /// <param name="markupData"> The markup data to store with the markup. </param>
        public Markup MarkRange(Range range, IMarkupDescriptor descriptor, IMarkupData markupData)
        {
            if (range.StartIndex < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(range));
            }
            if (range.EndIndex > _owner.Length)
            {
                throw new ArgumentOutOfRangeException(nameof(range));
            }

            var newFragment = new MarkupNodeReference(this, descriptor, markupData)
            {
                Length = range.Length
            };

            int previousNodeAbsoluteIndex;
            var previousNode = GetClosestNodeBefore(range.StartIndex, out previousNodeAbsoluteIndex);
            LinkedListNode <MarkupNodeReference> node;

            if (previousNode == null)
            {
                var nextNode = _subFragments.First;

                if (nextNode != null)
                {
                    // because we're at the beginning, the offset of the next fragment was an absolute index, thus
                    // we now convert it to a relative index by offsetting our start index.
                    nextNode.Value.RelativeOffsetSinceLastNode -= range.StartIndex;
                }

                node = _subFragments.AddFirst(newFragment);
                newFragment.RelativeOffsetSinceLastNode = range.StartIndex;
            }
            else
            {
                var nextNode = previousNode.Next;

                // fix up the next node's relative offset if need be
                if (nextNode != null)
                {
                    var nextFragment            = nextNode.Value;
                    int absoluteIndexOfNextNode = nextFragment.RelativeOffsetSinceLastNode + previousNodeAbsoluteIndex;

                    nextFragment.RelativeOffsetSinceLastNode = absoluteIndexOfNextNode - range.StartIndex;
                }

                newFragment.RelativeOffsetSinceLastNode = range.StartIndex - previousNodeAbsoluteIndex;

                node = _subFragments.AddAfter(previousNode, newFragment);
            }

            newFragment.Node = node;
            ChangeIndex      = ChangeIndex.Next();

            return(newFragment.Markup);
        }