Exemple #1
0
/// <summary>
/// Gets the common ancestor of this item and one other.
/// </summary>
/// <param name="otherNode">
/// The other node.
/// </param>
/// <returns>
/// The common ancestor.
/// </returns>
        public XamlNode GetCommonAncestor(XamlNode otherNode)
        {
            logger.Trace("Entered GetCommonAncestor()");
            return((from ancestor in this.Ancestors
                    from othersAncestor in otherNode.Ancestors
                    where ancestor == othersAncestor
                    select ancestor).FirstOrDefault());
        }
Exemple #2
0
 /// <summary>
 ///     Gets the common ancestor of this item and one other.
 /// </summary>
 /// <param name="otherNode">
 ///     The other node.
 /// </param>
 /// <returns>
 ///     The common ancestor.
 /// </returns>
 public XamlNode GetCommonAncestor(XamlNode otherNode)
 {
     foreach (var ancestor in this.Ancestors)
     {
         foreach (var othersAncestor in otherNode.Ancestors)
         {
             if (ancestor == othersAncestor)
             {
                 return(ancestor);
             }
         }
     }
     return(null);
 }
Exemple #3
0
        /// <summary>
        ///     A TextSelection extension method that select parent.
        /// </summary>
        /// <param name="selection">
        ///     The target to act on.
        /// </param>
        /// <returns>
        ///     true if it succeeds, otherwise false.
        /// </returns>
        public static bool SelectParent(this TextSelection selection)
        {
            EditorPoints ep = selection.GetEditorPoints();

            XamlNode[] nodes = _rootNode.GetSelectedNodes(ep);
            if (nodes == null || nodes == null)
            {
                return(false);
            }
            XamlNode parent = nodes[0].Parent;

            selection.SetSelection(parent.BottomPoint + 1, parent.TopPoint + 1);
            return(true);
        }
Exemple #4
0
        /// <summary>
        /// Access set to private to prevent usage from outside. Called only by
        /// XamlNode constructors.
        /// </summary>
        /// <exception cref="ArgumentException">
        /// Thrown when one or more arguments have unsupported or illegal values.
        /// </exception>
        /// <exception cref="ApplicationException">
        /// Thrown when an Application error condition occurs.
        /// </exception>
        /// <param name="newStartTag">
        /// The new start tag.
        /// </param>
        /// <param name="parent">
        /// The parent.
        /// </param>
        private XamlNode(XamlTag newStartTag, XamlNode parent)
        {
            logger.Trace("Entered XamlNode()");
            if (newStartTag.TagType == XamlTagType.Unknown)
            {
                throw new ArgumentException("The startingTag given is invalid.",
                                            "newStartTag");
            }
            if (newStartTag.TagType == XamlTagType.Ending)
            {
                throw new ArgumentException("And ending tag was given instead of a starting tag.",
                                            "newStartTag");
            }

            this.startTag = newStartTag;
            this.parent   = parent;
            if (newStartTag.TagType == XamlTagType.SelfClosing)
            {
                // Self closing tags have no children or separate closing tags.
                this.endTag = newStartTag;
                return;
            }

            while (tagMatchesEnumerator.MoveNext())
            {
                var childTag = new XamlTag(tagMatchesEnumerator.Current);
                if (childTag.TagType == XamlTagType.Ending)
                {
                    if (childTag.Name != this.Name)
                    {
                        throw new ArgumentException(
                                  string.Format("Expected \"{0}\" for end tag, but encountered \"{1}.\"",
                                                this.Name,
                                                childTag.Name));
                    }
                    this.endTag = childTag;
                    return;
                }
                var childNode = new XamlNode(childTag, this)
                {
                    DocumentText = this.documentText
                };
                this.ChildrenContainer.AddLast(childNode);
            }

// the end of tags represent the end of xaml tags. Since this builds a
// child, it should never reach this point.
            throw new ApplicationException("Premature end of tags encountered.");
        }
Exemple #5
0
        /// <summary>
        ///     This method should return a tupple with two nodes without fail (if
        ///     it is called through the root node). The
        ///     first node should be the node in which the topPoint falls, if it
        ///     falls within one of it's tags, after the last tag of its last child,
        ///     if it has no children. The second node should be the node in
        ///     which the bottom point falls, if it falls within one of its tags,
        ///     before the first tag of its first child, or if it has no children.
        /// </summary>
        /// <param name="topPoint">
        ///     The top point.
        /// </param>
        /// <param name="bottomPoint">
        ///     The bottom point.
        /// </param>
        /// <returns>
        ///     The first last nodes between points.
        /// </returns>
        public Tuple <XamlNode, XamlNode> GetFirstLastNodesBetweenPoints(int topPoint, int bottomPoint)
        {
            if (topPoint == bottomPoint)
            {
                XamlNode node = this.GetNodeWithOffset(topPoint);
                return(new Tuple <XamlNode, XamlNode>(node, node));
            }

            PositionAndNode pan1 = this.GetTopPointPositionAndNode(topPoint);
            PositionAndNode pan2 = this.GetBottomPointPositionAndNode(bottomPoint);

            if (pan1.Node.Parent != pan2.Node.Parent)
            {
                XamlNode parent = pan1.Node.GetCommonAncestor(pan2.Node);
                XamlNode node1  = parent.GetChildNodeWithOffset(topPoint);
                XamlNode node2  = parent.GetChildNodeWithOffset(bottomPoint);
                return(new Tuple <XamlNode, XamlNode>(node1, node2));
            }
            return(new Tuple <XamlNode, XamlNode>(pan1.Node, pan2.Node));
        }
Exemple #6
0
        private static EditorPoints GetEditorPoints(TextSelection sel, bool handleExceptions = true)
        {
            EditorPoints ep = sel.GetEditorPoints();

            try
            {
                if (_documentText == ep.DocumentText)
                {
                    return(ep);
                }

                _documentText = ep.DocumentText;
                _rootNode     = new XamlNode(_documentText);
                return(ep);
            }
            catch
            {
                ep.RestoreSelectedText(sel);
                return(EditorPoints.GetInvalidEditorPoints());
            }
        }
Exemple #7
0
        /// <summary>
        ///     A TextSelection extension method that selects a single node.
        /// </summary>
        /// <param name="selection">
        ///     The target to act on.
        /// </param>
        /// <returns>
        ///     true if it succeeds, otherwise false.
        /// </returns>
        public static bool SelectNode(this TextSelection selection)
        {
            // Works only when the selected text is empty.
            if (!selection.IsEmpty)
            {
                return(false);
            }

            // This has to be done here primarily to prime the data
            // needed by called methods. Othwerwise we could just
            // reference the offsets directly.
            EditorPoints ep   = GetEditorPoints(selection);
            XamlNode     node = _rootNode.GetNodeWithOffset(ep.ActivePoint - 1);

            if (node == null)
            {
                return(false);
            }
            selection.SetSelection(node.BottomPoint + 1, node.TopPoint + 1);
            return(true);
        }
Exemple #8
0
        /// <summary>
        ///     Gets node with offset.
        /// </summary>
        /// <param name="offset">
        ///     The document point.
        /// </param>
        /// <returns>
        ///     The node with offset.
        /// </returns>
        public XamlNode GetNodeWithOffset(int offset)
        {
            if (offset <= this.TopPoint || offset >= this.BottomPoint)
            {
                // documentPoint is not in this node or its children.
                return(null);
            }

            foreach (var child in this.ChildrenContainer)
            {
                XamlNode descendant = child.GetNodeWithOffset(offset);
                if (descendant == null)
                {
                    continue;
                }

                // documentPoint is within this child.
                return(descendant);
            }

            // documentPoint is within this node, but not in any of its
            // children.
            return(this);
        }
Exemple #9
0
 /// <summary>
 /// Initializes a new instance of the PositionAndNode class.
 /// </summary>
 /// <param name="node">
 /// The node.
 /// </param>
 /// <param name="positionIndex">
 /// Zero-based index of the position.
 /// </param>
 public PositionAndNode(XamlNode node, int positionIndex)
 {
     logger.Trace("Entered PositionAndNode()");
     this.Node          = node;
     this.PositionIndex = positionIndex;
 }
Exemple #10
0
        /// <summary>
        ///     Initializes a new instance of the XamlNode class. used to create a
        ///     root node.
        /// </summary>
        /// <exception cref="ApplicationException">
        ///     Thrown when an Application error condition occurs.
        /// </exception>
        /// <param name="documentText">
        ///     The document text.
        /// </param>
        /// <remarks>
        ///     Create the root node of a xaml file with this constructor. All other
        ///     child nodes will be created as a result.
        /// </remarks>
        public XamlNode(string documentText)
        {
            // The document to be parsed for building a XamlNode tree.
            this._documentText = documentText;
            this._isRoot       = true;

            // This object holds a sorted list of Match objects that correspond
            // to each tag in the document.
            _sortedTagMatches = new SortedSet <Match>(new XamlTagMatchComparer());
            MatchCollection matches = Regex.Matches(documentText,
                                                    XmlHelpers.STARTTAG_PATTERN,
                                                    RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline
                                                    | RegexOptions.IgnoreCase);

            foreach (Match item in matches)
            {
                _sortedTagMatches.Add(item);
            }
            matches = Regex.Matches(documentText,
                                    XmlHelpers.ENDTAG_PATTERN,
                                    RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline
                                    | RegexOptions.IgnoreCase);
            foreach (Match item in matches)
            {
                _sortedTagMatches.Add(item);
            }

            // the _sortedTagMatches collection is complete. That is now used
            // to build out the tree starting with this node, the root node.
            _tagMatchesEnumerator = _sortedTagMatches.GetEnumerator();
            if (_tagMatchesEnumerator.MoveNext())
            {
                this._startTag = new XamlTag(_tagMatchesEnumerator.Current);
                if (this._startTag.TagType != XamlTagType.Starting)
                {
                    throw new ApplicationException("Starting tag expected.");
                }
            }
            else
            {
                throw new ApplicationException("Unable to enumerate Xaml tags.");
            }

            // Except for this node's end tag, the only thing it will see in
            // this loop are its children node. The child nodes work similarly,
            // so by the time they return, the nodes that belong to the children
            // will be consumed.
            while (_tagMatchesEnumerator.MoveNext())
            {
                var childTag = new XamlTag(_tagMatchesEnumerator.Current);
                if (childTag.TagType == XamlTagType.Unknown)
                {
                    throw new ApplicationException("Unknown tag type encountered.");
                }
                if (childTag.TagType == XamlTagType.Ending)
                {
                    this._endTag = childTag;

                    // This is the end of the root node, so this should be the end
                    // of the xaml tags.
                    if (_tagMatchesEnumerator.MoveNext())
                    {
                        throw new ApplicationException("Closing tag encountered before last tag.");
                    }
                    break;
                }
                var childNode = new XamlNode(childTag, this)
                {
                    DocumentText = this._documentText
                };
                this.ChildrenContainer.AddLast(childNode);
            }

            _tagMatchesEnumerator.Dispose();
            _sortedTagMatches = null;
        }