コード例 #1
0
ファイル: TextContainer.cs プロジェクト: sjyanxin/WPFSource
        // Does a deep extract of all top-level TextElements between two positions. 
        // Returns the combined symbol count of all extracted elements.
        // Each extracted element (and its children) are moved into a private tree. 
        // This insures that outside references to the TextElement can still use
        // the TextElements freely, inserting or removing content, etc.
        //
        // Also calls AddLogicalChild on any top-level UIElements encountered. 
        private int CutTopLevelLogicalNodes(TextTreeNode containingNode, TextPointer startPosition, TextPointer endPosition, out int charCount)
        { 
            SplayTreeNode node; 
            SplayTreeNode nextNode;
            SplayTreeNode stopNode; 
            TextTreeTextElementNode elementNode;
            TextTreeObjectNode uiElementNode;
            char[] elementText;
            int symbolCount; 
            TextContainer tree;
            TextPointer newTreeStart; 
            DependencyObject logicalParent; 
            object currentLogicalChild;
 
            Invariant.Assert(startPosition.GetScopingNode() == endPosition.GetScopingNode(), "startPosition/endPosition not in same sibling tree!");

            node = startPosition.GetAdjacentSiblingNode(LogicalDirection.Forward);
            stopNode = endPosition.GetAdjacentSiblingNode(LogicalDirection.Forward); 

            symbolCount = 0; 
            charCount = 0; 

            logicalParent = containingNode.GetLogicalTreeNode(); 

            while (node != stopNode)
            {
                currentLogicalChild = null; 

                // Get the next node now, before we extract any TextElementNodes. 
                nextNode = node.GetNextNode(); 

                elementNode = node as TextTreeTextElementNode; 
                if (elementNode != null)
                {
                    // Grab the IMECharCount before we modify the node.
                    // This value depends on the node's current context. 
                    int imeCharCountInOriginalContainer = elementNode.IMECharCount;
 
                    // Cut and record the matching symbols. 
                    elementText = TextTreeText.CutText(_rootNode.RootTextBlock, elementNode.GetSymbolOffset(this.Generation), elementNode.SymbolCount);
 
                    // Rip the element out of its sibling tree.
                    // textElementNode.TextElement's TextElementNode will be updated
                    // with a deep copy of all contained nodes. We need a deep copy
                    // to ensure the new element/tree has no TextPointer references. 
                    ExtractElementFromSiblingTree(containingNode, elementNode, true /* deep */);
                    // Assert that the TextElement now points to a new TextElementNode, not the original one. 
                    Invariant.Assert(elementNode.TextElement.TextElementNode != elementNode); 
                    // We want to start referring to the copied node, update elementNode.
                    elementNode = elementNode.TextElement.TextElementNode; 

                    UpdateContainerSymbolCount(containingNode, -elementNode.SymbolCount, -imeCharCountInOriginalContainer);
                    NextGeneration(true /* deletedContent */);
 
                    // Stick it in a private tree so it's safe for the outside world to play with.
                    tree = new TextContainer(null, false /* plainTextOnly */); 
                    newTreeStart = tree.Start; 

                    tree.InsertElementToSiblingTree(newTreeStart, newTreeStart, elementNode); 
                    Invariant.Assert(elementText.Length == elementNode.SymbolCount);
                    tree.UpdateContainerSymbolCount(elementNode.GetContainingNode(), elementNode.SymbolCount, elementNode.IMECharCount);
                    tree.DemandCreateText();
                    TextTreeText.InsertText(tree.RootTextBlock, 1 /* symbolOffset */, elementText); 
                    tree.NextGeneration(false /* deletedContent */);
 
                    currentLogicalChild = elementNode.TextElement; 

                    // Keep a running total of how many symbols we've removed. 
                    symbolCount += elementNode.SymbolCount;
                    charCount += imeCharCountInOriginalContainer;
                }
                else 
                {
                    uiElementNode = node as TextTreeObjectNode; 
                    if (uiElementNode != null) 
                    {
                        currentLogicalChild = uiElementNode.EmbeddedElement; 
                    }
                }

                // Remove the child from the logical tree 
                LogicalTreeHelper.RemoveLogicalChild(logicalParent, currentLogicalChild);
 
                node = nextNode; 
            }
 
            if (symbolCount > 0)
            {
                startPosition.SyncToTreeGeneration();
                endPosition.SyncToTreeGeneration(); 
            }
 
            return symbolCount; 
        }