Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / TextTreeNode.cs / 1305600 / TextTreeNode.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Base class for all nodes in the TextContainer. // // // History: // 02/18/2004 : [....] - Created // //--------------------------------------------------------------------------- using System; using MS.Internal; namespace System.Windows.Documents { #if INT_EDGE_REF_COUNT // A container for position reference counts on a node edge. // Since typically a node won't have any references, we // lazy allocate an EdgeReferenceCounts only when necessary // to save a little space on tree nodes. internal class EdgeReferenceCounts { internal int BeforeStartReferenceCount { get { return _beforeStartReferenceCount; } set { _beforeStartReferenceCount = value; } } internal virtual int AfterStartReferenceCount { get { return 0; } set { Invariant.Assert(false, "Text/Object nodes have no AfterStart edge!"); } } internal virtual int BeforeEndReferenceCount { get { return 0; } set { Invariant.Assert(false, "Text/Object nodes have no BeforeEnd edge!"); } } internal int AfterEndReferenceCount { get { return _afterEndReferenceCount; } set { _afterEndReferenceCount = value; } } private int _beforeStartReferenceCount; private int _afterEndReferenceCount; } // Element reference counts adds AfterStart/BeforeEnd counts. internal class ElementEdgeReferenceCounts : EdgeReferenceCounts { internal override int AfterStartReferenceCount { get { return _afterStartReferenceCount; } set { _afterStartReferenceCount = value; } } internal override int BeforeEndReferenceCount { get { return _beforeEndReferenceCount; } set { _beforeEndReferenceCount = value; } } private int _afterStartReferenceCount; private int _beforeEndReferenceCount; } #endif // INT_EDGE_REF_COUNT // This is the base class for all TextContainer nodes. It contains no state, // but has several abstract properties to derived class state. // // The vast majority of tree manipulations work with TextTreeNode rather // than derived classes. All splay tree balancing code lives in this class. // // Nodes in the TextContainer live within two hierarchies. Sibling nodes are // stored in splay trees, a type of balanced binary tree. Some nodes, // the TextTreeRootNode and TextTreeTextElementNodes, "contain" other nodes // which are themselves roots of splay trees. So an individual node is // always in a splay tree along with its siblings, and it may contain // a splay tree of its own children. // // For example, // //Hi! Fancy // // becomes // // [TextTreeRootNode] // || // [TextTreeTextElementNode] // || \ // || \ // || \ // [TextTreeTextNode "Hi!"] [TextTreeTextElementNode] // || // [TextTreeTextElementNode] // / || \ // / || \ // / || \ // / || \ // / || \ // / || \ // [TextTreeTextNode "Fancy "] [TextTreeTextNode "text"] [TextTreeTextNode "."] // // "||" is a link from tree to tree, "|" is a link between nodes in a single tree. // // The splay tree algorithm relies on a balancing operation, Splay(), performed // after each node access. It's very important to continue splaying the tree // as nodes are accessed, or we'll have an unbalanced binary tree. If you're // trying to figure out why the tree perf has regressed and you see deep trees, // read up on the splay tree algorithm in your reference book of choice and // then consider whether or not Splay() is being called appropriately from any // new code. internal abstract class TextTreeNode : SplayTreeNode { //----------------------------------------------------- // // Protected Methods // //----------------------------------------------------- #region Protected Methods #if INT_EDGE_REF_COUNT // Sets the count of TextPositions referencing the node's left // edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected static void SetBeforeStartReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { edgeReferenceCounts.BeforeStartReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new EdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = value; } } // Sets the count of TextPositions referencing the node's AfterStart edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected void SetAfterStartReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { EdgeReferenceCounts originalCounts; if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { if (!(edgeReferenceCounts is ElementEdgeReferenceCounts)) { // We need a slightly bigger object, which tracks the inner edges. Invariant.Assert(this is TextTreeTextElementNode, "Non-element nodes should never have inner edge references!"); originalCounts = edgeReferenceCounts; edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = originalCounts.BeforeStartReferenceCount; edgeReferenceCounts.AfterEndReferenceCount = originalCounts.AfterEndReferenceCount; } edgeReferenceCounts.AfterStartReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.AfterStartReferenceCount = value; } } // Sets the count of TextPositions referencing the node's BeforeEnd edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected void SetBeforeEndReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { EdgeReferenceCounts originalCounts; if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.AfterEndReferenceCount == 0) { edgeReferenceCounts = null; } else { if (!(edgeReferenceCounts is ElementEdgeReferenceCounts)) { // We need a slightly bigger object, which tracks the inner edges. Invariant.Assert(this is TextTreeTextElementNode, "Non-element nodes should never have inner edge references!"); originalCounts = edgeReferenceCounts; edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeStartReferenceCount = originalCounts.BeforeStartReferenceCount; edgeReferenceCounts.AfterEndReferenceCount = originalCounts.AfterEndReferenceCount; } edgeReferenceCounts.BeforeEndReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new ElementEdgeReferenceCounts(); edgeReferenceCounts.BeforeEndReferenceCount = value; } } // Sets the count of TextPositions referencing the node's right // edge. // Since nodes don't usually have any references, we demand allocate // storage when needed. protected static void SetAfterEndReferenceCount(ref EdgeReferenceCounts edgeReferenceCounts, int value) { if (edgeReferenceCounts != null) { if (value == 0 && edgeReferenceCounts.BeforeStartReferenceCount == 0 && edgeReferenceCounts.AfterStartReferenceCount == 0 && edgeReferenceCounts.BeforeEndReferenceCount == 0) { edgeReferenceCounts = null; } else { edgeReferenceCounts.AfterEndReferenceCount = value; } } else if (value != 0) { edgeReferenceCounts = new EdgeReferenceCounts(); edgeReferenceCounts.AfterEndReferenceCount = value; } } #endif // INT_EDGE_REF_COUNT #endregion Protected Methods //------------------------------------------------------ // // Internal Methods // //----------------------------------------------------- #region Internal Methods // Returns a shallow copy of this node. // The clone is a local root with no children. internal abstract TextTreeNode Clone(); // Returns the TextContainer containing this node. internal TextContainer GetTextTree() { SplayTreeNode node; SplayTreeNode containingNode; node = this; while (true) { containingNode = node.GetContainingNode(); if (containingNode == null) break; node = containingNode; } return ((TextTreeRootNode)node).TextContainer; } // Returns the closest DependencyObject scoping a given node. // This includes the node itself and TextContainer.Parent. internal DependencyObject GetDependencyParent() { SplayTreeNode node; DependencyObject parent; SplayTreeNode containingNode; TextTreeTextElementNode elementNode; node = this; while (true) { elementNode = node as TextTreeTextElementNode; if (elementNode != null) { parent = elementNode.TextElement; Invariant.Assert(parent != null, "TextElementNode has null TextElement!"); break; } containingNode = node.GetContainingNode(); if (containingNode == null) { parent = ((TextTreeRootNode)node).TextContainer.Parent; // This may be null. break; } node = containingNode; } return parent; } // Returns the closest Logical Tree Node to a given node, including the // node itself and TextContainer.Parent. internal DependencyObject GetLogicalTreeNode() { TextTreeObjectNode objectNode; TextTreeTextElementNode textElementNode; SplayTreeNode node; SplayTreeNode containingNode; DependencyObject logicalTreeNode; objectNode = this as TextTreeObjectNode; if (objectNode != null) { if (objectNode.EmbeddedElement is FrameworkElement) { return objectNode.EmbeddedElement; } } node = this; while (true) { textElementNode = node as TextTreeTextElementNode; if (textElementNode != null) { logicalTreeNode = textElementNode.TextElement; break; } containingNode = node.GetContainingNode(); if (containingNode == null) { logicalTreeNode = ((TextTreeRootNode)node).TextContainer.Parent; break; } node = containingNode; } return logicalTreeNode; } // Returns the TextPointerContext of the node. // If node is TextTreeTextElementNode, this method returns ElementStart // if direction == Forward, otherwise ElementEnd if direction == Backward. internal abstract TextPointerContext GetPointerContext(LogicalDirection direction); // Increments the reference count of TextPositions referencing a // particular edge of this node. // // If this node is a TextTreeTextNode, the increment may split the node // and the return value is guaranteed to be the node containing the referenced // edge (which may be a new node). Otherwise this method always returns // the original node. internal TextTreeNode IncrementReferenceCount(ElementEdge edge) { return IncrementReferenceCount(edge, +1); } internal virtual TextTreeNode IncrementReferenceCount(ElementEdge edge, bool delta) { return IncrementReferenceCount(edge, delta ? 1 : 0); } // Increments the reference count of TextPositions referencing a // particular edge of this node. // // If this node is a TextTreeTextNode, the increment may split the node // and the return value is guaranteed to be the node containing the referenced // edge (which may be a new node). Otherwise this method always returns // the original node. internal virtual TextTreeNode IncrementReferenceCount(ElementEdge edge, int delta) { Invariant.Assert(delta >= 0); if (delta > 0) { switch (edge) { case ElementEdge.BeforeStart: this.BeforeStartReferenceCount = true; break; case ElementEdge.AfterStart: this.AfterStartReferenceCount = true; break; case ElementEdge.BeforeEnd: this.BeforeEndReferenceCount = true; break; case ElementEdge.AfterEnd: this.AfterEndReferenceCount = true; break; default: Invariant.Assert(false, "Bad ElementEdge value!"); break; } } return this; } // Decrements the reference count of TextPositions referencing this // node. // // Be careful! If this node is a TextTreeTextNode, the decrement may // cause a merge, and this node may be removed from the tree. internal virtual void DecrementReferenceCount(ElementEdge edge) { #if INT_EDGE_REF_COUNT switch (edge) { case ElementEdge.BeforeStart: this.BeforeStartReferenceCount--; Invariant.Assert(this.BeforeStartReferenceCount >= 0, "Bad BeforeStart ref count!"); break; case ElementEdge.AfterStart: this.AfterStartReferenceCount--; Invariant.Assert(this.AfterStartReferenceCount >= 0, "Bad AfterStart ref count!"); break; case ElementEdge.BeforeEnd: this.BeforeEndReferenceCount--; Invariant.Assert(this.BeforeEndReferenceCount >= 0, "Bad BeforeEnd ref count!"); break; case ElementEdge.AfterEnd: this.AfterEndReferenceCount--; Invariant.Assert(this.AfterEndReferenceCount >= 0, "Bad AfterEnd ref count!"); break; default: Invariant.Assert(false, "Bad ElementEdge value!"); break; } #endif // INT_EDGE_REF_COUNT } // Inserts a node at a specified position. internal void InsertAtPosition(TextPointer position) { InsertAtNode(position.Node, position.Edge); } internal ElementEdge GetEdgeFromOffsetNoBias(int nodeOffset) { return GetEdgeFromOffset(nodeOffset, LogicalDirection.Forward); } internal ElementEdge GetEdgeFromOffset(int nodeOffset, LogicalDirection bias) { ElementEdge edge; if (this.SymbolCount == 0) { // If we're pointing at a zero-width TextTreeTextNode, we need to make // sure we get the right edge -- nodeOffset doesn't convey enough information // for GetEdgeFromOffset to compute a correct value. edge = (bias == LogicalDirection.Forward) ? ElementEdge.AfterEnd : ElementEdge.BeforeStart; } else if (nodeOffset == 0) { edge = ElementEdge.BeforeStart; } else if (nodeOffset == this.SymbolCount) { edge = ElementEdge.AfterEnd; } else if (nodeOffset == 1) { edge = ElementEdge.AfterStart; } else { Invariant.Assert(nodeOffset == this.SymbolCount - 1); edge = ElementEdge.BeforeEnd; } return edge; } internal int GetOffsetFromEdge(ElementEdge edge) { int offset; switch (edge) { case ElementEdge.BeforeStart: offset = 0; break; case ElementEdge.AfterStart: offset = 1; break; case ElementEdge.BeforeEnd: offset = this.SymbolCount - 1; break; case ElementEdge.AfterEnd: offset = this.SymbolCount; break; default: offset = 0; Invariant.Assert(false, "Bad ElementEdge value!"); break; } return offset; } #endregion Internal methods //------------------------------------------------------ // // Internal Properties // //------------------------------------------------------ #region Internal Properties // Count of TextPositions referencing the node's BeforeStart edge. internal abstract bool BeforeStartReferenceCount { get; set; } // Count of TextPositions referencing the node's AfterStart edge. internal abstract bool AfterStartReferenceCount { get; set; } // Count of TextPositions referencing the node's BeforeEnd edge. internal abstract bool BeforeEndReferenceCount { get; set; } // Count of TextPositions referencing the node's AfterEnd edge. internal abstract bool AfterEndReferenceCount { get; set; } #endregion Internal Properties } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.text .
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SRDisplayNameAttribute.cs
- BlurBitmapEffect.cs
- XmlAttributeAttribute.cs
- BackStopAuthenticationModule.cs
- MeshGeometry3D.cs
- RegisteredExpandoAttribute.cs
- AutomationPattern.cs
- DatatypeImplementation.cs
- newinstructionaction.cs
- XmlSchemaSubstitutionGroup.cs
- SafeCryptContextHandle.cs
- DefaultBindingPropertyAttribute.cs
- ExpressionBuilderCollection.cs
- ExpressionEditorAttribute.cs
- ResourceKey.cs
- ListParaClient.cs
- CellRelation.cs
- TimeStampChecker.cs
- RayMeshGeometry3DHitTestResult.cs
- UniqueConstraint.cs
- ContentOperations.cs
- FormsIdentity.cs
- TableRowGroup.cs
- XmlSchemaRedefine.cs
- EntityDesignerDataSourceView.cs
- WebPartConnectVerb.cs
- ClientTarget.cs
- SmtpSection.cs
- CodeNamespace.cs
- CompilationPass2Task.cs
- Boolean.cs
- SecureStringHasher.cs
- DictionaryEntry.cs
- Invariant.cs
- CompositeControlDesigner.cs
- DrawingBrush.cs
- LockingPersistenceProvider.cs
- PropertyChangingEventArgs.cs
- PerformanceCounterCategory.cs
- SmtpClient.cs
- TraceSection.cs
- DummyDataSource.cs
- BordersPage.cs
- UnsafeNativeMethodsCLR.cs
- GridErrorDlg.cs
- ParseNumbers.cs
- RadioButton.cs
- SponsorHelper.cs
- Geometry.cs
- Panel.cs
- DataGridTablesFactory.cs
- CheckBox.cs
- TypeResolvingOptionsAttribute.cs
- BitmapEffectDrawing.cs
- NameTable.cs
- UnsafeNativeMethodsCLR.cs
- UniqueConstraint.cs
- Simplifier.cs
- XPathSelectionIterator.cs
- XPathParser.cs
- ApplicationTrust.cs
- DataGridToolTip.cs
- XamlStackWriter.cs
- ProjectionPlanCompiler.cs
- EventLogLink.cs
- InfoCardCryptoHelper.cs
- BitmapDownload.cs
- HostingEnvironmentException.cs
- VideoDrawing.cs
- ConnectionPoolManager.cs
- AttributeEmitter.cs
- CodeBinaryOperatorExpression.cs
- ListViewInsertedEventArgs.cs
- WebServiceData.cs
- MDIWindowDialog.cs
- HttpTransportManager.cs
- LogStream.cs
- BuildProviderUtils.cs
- XmlCharCheckingWriter.cs
- MetadataProperty.cs
- ResourceSet.cs
- ProviderSettingsCollection.cs
- Quaternion.cs
- ResourcePermissionBaseEntry.cs
- CatalogZone.cs
- EntityDataSourceValidationException.cs
- SqlSelectStatement.cs
- ComponentChangedEvent.cs
- LocalValueEnumerator.cs
- ClientBuildManager.cs
- TextTreeRootNode.cs
- ProfilePropertySettings.cs
- ContextProperty.cs
- RenderData.cs
- DependencyProperty.cs
- ToolStripHighContrastRenderer.cs
- MimeFormatExtensions.cs
- DockPatternIdentifiers.cs
- diagnosticsswitches.cs
- StringAnimationUsingKeyFrames.cs