Exemple #1
0
        bool ExpandSelection(List <XObject> nodePath, XmlSpineParser spine, SnapshotSpan activeSpan, ref int index, ref SelectionLevel level)
        {
            if (index - 1 < 0)
            {
                return(false);
            }

            //if an index is selected, we may need to transition level rather than transitioning index
            if (index < nodePath.Count)
            {
                var current = nodePath[index];
                if (current is XElement element)
                {
                    switch (level)
                    {
                    case SelectionLevel.Self:
                        if (spine != null && !spine.AdvanceUntilClosed(element, activeSpan.Snapshot, 5000))
                        {
                            return(false);
                        }
                        if (!element.IsSelfClosing)
                        {
                            level = SelectionLevel.OuterElement;
                            return(true);
                        }
                        break;

                    case SelectionLevel.Content:
                        level = SelectionLevel.OuterElement;
                        return(true);

                    case SelectionLevel.Name:
                        level = SelectionLevel.Self;
                        return(true);

                    case SelectionLevel.Attributes:
                        level = SelectionLevel.Self;
                        return(true);
                    }
                }
                else if (current is XAttribute)
                {
                    switch (level)
                    {
                    case SelectionLevel.Name:
                    case SelectionLevel.Content:
                        level = SelectionLevel.Self;
                        return(true);
                    }
                }
                else if (level == SelectionLevel.Name)
                {
                    level = SelectionLevel.Self;
                    return(true);
                }
                else if (level == SelectionLevel.Document)
                {
                    return(false);
                }
            }

            //advance up the node path
            index--;
            var newNode = nodePath[index];

            //determine the starting selection level for the new node
            if (newNode is XDocument)
            {
                level = SelectionLevel.Document;
                return(true);
            }

            if (spine != null && !spine.AdvanceUntilEnded(newNode, activeSpan.Snapshot, 5000))
            {
                return(false);
            }

            bool ContainsSelection(TextSpan span) => activeSpan.Start >= span.Start && activeSpan.End <= span.End;

            if (ContainsSelection(newNode.Span))
            {
                if ((newNode as INamedXObject)?.NameSpan is TextSpan nr && ContainsSelection(nr))
                {
                    level = SelectionLevel.Name;
                    return(true);
                }
                if (newNode is XAttribute attribute)
                {
                    var valRegion = attribute.ValueSpan;
                    if (ContainsSelection(valRegion))
                    {
                        level = SelectionLevel.Content;
                        return(true);
                    }
                }
                if (newNode is XText)
                {
                    level = SelectionLevel.Content;
                    return(true);
                }
                if (newNode is XElement xElement && xElement.Attributes.Count > 1)
                {
                    if (xElement.GetAttributesSpan() is TextSpan attsSpan && ContainsSelection(attsSpan))
                    {
                        level = SelectionLevel.Attributes;
                        return(true);
                    }
                }
                level = SelectionLevel.Self;
                return(true);
            }

            if (spine != null && !spine.AdvanceUntilClosed(newNode, activeSpan.Snapshot, 5000))
            {
                return(false);
            }

            if (newNode is XElement el && el.ClosingTag != null)
            {
                if (el.IsSelfClosing)
                {
                    level = SelectionLevel.Self;
                    return(true);
                }
                if (ContainsSelection((TextSpan)el.InnerSpan))
                {
                    level = SelectionLevel.Content;
                    return(true);
                }
                level = SelectionLevel.OuterElement;
                return(true);
            }

            level = SelectionLevel.Self;
            return(true);
        }
 /// <summary>
 /// Advances the parser until the specified object is closed i.e. has a closing tag.
 /// </summary>
 /// <param name="parser">A spine parser. Its state will be modified.</param>
 /// <param name="ob">The object to complete</param>
 /// <param name="snapshot"></param>
 /// <param name="snapshot">The text snapshot corresponding to the parser.</param>
 /// <param name="maximumReadahead">Maximum number of characters to advance before giving up.</param>
 /// <returns>Whether the object was successfully completed</returns>
 public static bool AdvanceUntilClosed(this XmlSpineParser parser, XObject ob, ITextSnapshot snapshot, int maximumReadahead = DEFAULT_READAHEAD_LIMIT)
 => parser.AdvanceUntilClosed(ob, new SnapshotTextSource(snapshot), maximumReadahead);