Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / System / Windows / Documents / TextTreeDeleteContentUndoUnit.cs / 1407647 / TextTreeDeleteContentUndoUnit.cs
//---------------------------------------------------------------------------- // //// Copyright (C) Microsoft Corporation. All rights reserved. // // // // Description: Undo unit for TextContainer.DeleteContent calls. // // History: // 03/03/2004 : [....] - Created // //--------------------------------------------------------------------------- using MS.Internal; using System; using System.IO; using System.Windows.Controls; using System.Windows.Markup; using System.Xml; using System.Security; namespace System.Windows.Documents { // Undo unit for TextContainer.DeleteContent calls. internal class TextTreeDeleteContentUndoUnit : TextTreeUndoUnit { //----------------------------------------------------- // // Constructors // //----------------------------------------------------- #region Constructors // Creates a new instance. // start/end span the content to copy into the new undo unit -- they // should always share the same scoping TextElement. internal TextTreeDeleteContentUndoUnit(TextContainer tree, TextPointer start, TextPointer end) : base(tree, start.GetSymbolOffset()) { TextTreeNode node; TextTreeNode haltNode; start.DebugAssertGeneration(); end.DebugAssertGeneration(); Invariant.Assert(start.GetScopingNode() == end.GetScopingNode(), "start/end have different scope!"); node = start.GetAdjacentNode(LogicalDirection.Forward); haltNode = end.GetAdjacentNode(LogicalDirection.Forward); // Walk the content, copying runs as we go. _content = CopyContent(node, haltNode); } #endregion Constructors //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- #region Public Methods // Called by the undo manager. Restores tree state to its condition // when the unit was created. Assumes the tree state matches conditions // just after the unit was created. // // Note that inside the scope of this call we'll also create redo records, // which are very fragmented -- one for each TextPointerContext run. // In the future, if we have perf issues, we could consider disabling // reentrant calls to the UndoManager and instead manually adding a single // undo unit here to prevent the fragmentation. public override void DoCore() { TextPointer navigator; ContentContainer container; VerifyTreeContentHashCode(); // We need forward gravity to make following inserts work. navigator = new TextPointer(this.TextContainer, this.SymbolOffset, LogicalDirection.Forward); for (container = _content; container != null; container = container.NextContainer) { container.Do(navigator); } } #endregion Public Methods //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods // Used also in TextTreeExtractElementUndoUnit internal static TableColumn[] SaveColumns(Table table) { TableColumn[] savedColumns; if (table.Columns.Count > 0) { savedColumns = new TableColumn[table.Columns.Count]; for (int columnIndex = 0; columnIndex < table.Columns.Count; columnIndex++) { savedColumns[columnIndex] = CopyColumn(table.Columns[columnIndex]); } } else { savedColumns = null; } return savedColumns; } // Used also in TextTreeExtractElementUndoUnit internal static void RestoreColumns(Table table, TableColumn[] savedColumns) { if (savedColumns != null) { for (int columnIndex = 0; columnIndex < savedColumns.Length; columnIndex++) { if (table.Columns.Count <= columnIndex) { table.Columns.Add(CopyColumn(savedColumns[columnIndex])); } } } } private static TableColumn CopyColumn(TableColumn sourceTableColumn) { TableColumn newTableColumn = new TableColumn(); LocalValueEnumerator properties = sourceTableColumn.GetLocalValueEnumerator(); while (properties.MoveNext()) { LocalValueEntry propertyEntry = properties.Current; if (!propertyEntry.Property.ReadOnly) { newTableColumn.SetValue(propertyEntry.Property, propertyEntry.Value); } } return newTableColumn; } #endregion Internal Methods //----------------------------------------------------- // // Private Methods // //------------------------------------------------------ #region Private Methods // Walks the tree from node to the end of its sibling list, // copying content along the way, // halting when/if haltNode is encountered. haltNode may be // null, in which case we walk to the end of the sibling list. // // Returns a ContentContainer holding a deep copy of all content // walked. // // This method is called recursively when TextElement nodes // are encountered. private ContentContainer CopyContent(TextTreeNode node, TextTreeNode haltNode) { ContentContainer firstContainer; ContentContainer container; ContentContainer nextContainer; TextTreeTextNode textNode; TextTreeObjectNode objectNode; TextTreeTextElementNode elementNode; firstContainer = null; container = null; while (node != haltNode && node != null) { textNode = node as TextTreeTextNode; if (textNode != null) { node = CopyTextNode(textNode, haltNode, out nextContainer); } else { objectNode = node as TextTreeObjectNode; if (objectNode != null) { node = CopyObjectNode(objectNode, out nextContainer); } else { Invariant.Assert(node is TextTreeTextElementNode, "Unexpected TextTreeNode type!"); elementNode = (TextTreeTextElementNode)node; node = CopyElementNode(elementNode, out nextContainer); } } if (container == null) { firstContainer = nextContainer; } else { container.NextContainer = nextContainer; } container = nextContainer; } return firstContainer; } // Copies a run of text into a ContentContainer. // Returns the next node to examine. private TextTreeNode CopyTextNode(TextTreeTextNode textNode, TextTreeNode haltNode, out ContentContainer container) { SplayTreeNode node; char[] text; int count; int symbolOffset; Invariant.Assert(textNode != haltNode, "Expect at least one node to copy!"); symbolOffset = textNode.GetSymbolOffset(this.TextContainer.Generation); // Get a count of all the characters we're about to copy. count = 0; node = textNode; do { count += textNode.SymbolCount; node = textNode.GetNextNode(); textNode = node as TextTreeTextNode; } while (textNode != null && textNode != haltNode); // Allocate storage. text = new char[count]; // Copy the text. TextTreeText.ReadText(this.TextContainer.RootTextBlock, symbolOffset, count, text, 0 /*startIndex*/); container = new TextContentContainer(text); return (TextTreeNode)node; } ////// Copies an embedded UIElement into a ContentContainer. /// Returns the next node to examine. /// ////// Critical: This function makes a security decision (checks for unmanaged code permission). /// TreatAsSafe: Doesn't call critical code and doesn't expose critical data. /// [SecurityCritical, SecurityTreatAsSafe] private TextTreeNode CopyObjectNode(TextTreeObjectNode objectNode, out ContentContainer container) { // XamlWriter.Save demands unmanaged code permission. Since it's not safe to assert // here as custom type converters and value serializers can potentially execute // arbitrary code, we block the call to XamlWriter.Save in partial trust. if (SecurityHelper.CheckUnmanagedCodePermission()) { string xml; xml = XamlWriter.Save(objectNode.EmbeddedElement); container = new ObjectContentContainer(xml, objectNode.EmbeddedElement); } else { container = new ObjectContentContainer(null, null); } return (TextTreeNode)objectNode.GetNextNode(); } // Copies a TextElement and all its contained content into a ContentContainer. // Returns the next node to examine. private TextTreeNode CopyElementNode(TextTreeTextElementNode elementNode, out ContentContainer container) { if(elementNode.TextElement is Table) { container = new TableElementContentContainer(elementNode.TextElement as Table, GetPropertyRecordArray(elementNode.TextElement), CopyContent((TextTreeNode)elementNode.GetFirstContainedNode(), null)); } else { container = new ElementContentContainer(elementNode.TextElement.GetType(), GetPropertyRecordArray(elementNode.TextElement), elementNode.TextElement.Resources, CopyContent((TextTreeNode)elementNode.GetFirstContainedNode(), null)); } return (TextTreeNode)elementNode.GetNextNode(); } #endregion Private methods //----------------------------------------------------- // // Private Types // //----------------------------------------------------- #region Private Types // ContentContainer encapsulates a serialized copy of one of // - Text run. // - UIElement. // - TextElement. private abstract class ContentContainer { // Inserts the content held by this container at a specified position. // Navigator is positioned just past the new content on return. // Navigator is expected to have forward gravity. internal abstract void Do(TextPointer navigator); // The content following this container. Always a different // container type. internal ContentContainer NextContainer { get { return _nextContainer; } set { _nextContainer = value; } } private ContentContainer _nextContainer; } // A serialized text run. private class TextContentContainer : ContentContainer { internal TextContentContainer(char[] text) { _text = text; } // Inserts the content held by this container at a specified position. // Navigator is positioned just past the new content on return. // Navigator is expected to have forward gravity. internal override void Do(TextPointer navigator) { navigator.TextContainer.InsertTextInternal(navigator, _text); } // The text covered by this run. private readonly char[] _text; } // A serialized UIElement. private class ObjectContentContainer : ContentContainer { internal ObjectContentContainer(string xml, object element) { _xml = xml; // Store a strong reference to the deleted element. // Note that we are not supposed to use this reference in any other way // as just to prevent garbage collector to delete object. // We need to keep it in memory for ensuring that image cache // keeps the same uri references to image bitmaps. // Otherwise uri-s of packaged (pasted) images will be broken // on undo. _element = element; } // Inserts the content held by this container at a specified position. // Navigator is positioned just past the new content on return. // Navigator is expected to have forward gravity. internal override void Do(TextPointer navigator) { DependencyObject embeddedObject = null; // Get the object to be inserted. // If xml is null which we set it not to call SaveAsXml in the partial trust envirnment, // create the dummy Grid object to be inserted so that we can [....] TextContainer // count with the undo unit. if (_xml != null) { try { embeddedObject = (DependencyObject)XamlReader.Load(new XmlTextReader(new StringReader(_xml))); } catch (XamlParseException e) { Invariant.Assert(e != null); // Placed here for debugging convenience - to be able to see the exception. } } // When we cannot parse the object back, we loose it and substitute by an empty Grid // as an embeddedElement placeholder. if (embeddedObject == null) { embeddedObject = new Grid(); } navigator.TextContainer.InsertEmbeddedObjectInternal(navigator, embeddedObject); } // Serialized UIElement xml. private readonly string _xml; // Stores a strong reference to the deleted content to make sure // that all image data remains in image cache. // The object is not supposed to be used in any other sense // in this undo unit - only as a strong reference. // Image cache keeps the association between an image bitmap data // and its source url until the bitmapdata is referred to by a strong reference. // That's why we need this. private readonly Object _element; } // A serialized TextElement. private class ElementContentContainer : ContentContainer { // Creates a new instance. // childContainer holds all content covered by this TextElement. internal ElementContentContainer(Type elementType, PropertyRecord[] localValues, ResourceDictionary resources, ContentContainer childContainer) { _elementType = elementType; _localValues = localValues; _childContainer = childContainer; _resources = resources; } // Inserts the content held by this container at a specified position. // Navigator is positioned just past the new content on return. // Navigator is expected to have forward gravity. internal override void Do(TextPointer navigator) { ContentContainer container; TextElement element; // Insert the element. element = (TextElement)Activator.CreateInstance(_elementType); element.Reposition(navigator, navigator); // Get inside its scope. navigator.MoveToNextContextPosition(LogicalDirection.Backward); // Set local values. // navigator.TextContainer.SetValues(navigator, TextTreeUndoUnit.ArrayToLocalValueEnumerator(_localValues)); // Restore resources element.Resources = _resources; // Insert contained content. for (container = _childContainer; container != null; container = container.NextContainer) { container.Do(navigator); } // Move outside the element's scope again. navigator.MoveToNextContextPosition(LogicalDirection.Forward); } // TextElement type. private readonly Type _elementType; // Local property values set on the TextElement. private readonly PropertyRecord []_localValues; // Resources defined locally on the TextElement private readonly ResourceDictionary _resources; // Contained content. private readonly ContentContainer _childContainer; } // A serialized Table Element private class TableElementContentContainer : ElementContentContainer { internal TableElementContentContainer(Table table, PropertyRecord []localValues, ContentContainer childContainer) : base(table.GetType(), localValues, table.Resources, childContainer) { _cpTable = table.TextContainer.Start.GetOffsetToPosition(table.ContentStart); _columns = SaveColumns(table); } internal override void Do(TextPointer navigator) { base.Do(navigator); if(_columns != null) { TextPointer textPointerTable = new TextPointer(navigator.TextContainer.Start, _cpTable, LogicalDirection.Forward); Table table = (Table) textPointerTable.Parent; RestoreColumns(table, _columns); } } private TableColumn[] _columns; private int _cpTable; } #endregion Private Types //----------------------------------------------------- // // Private Fields // //------------------------------------------------------ #region Private Fields // Serialized content. private readonly ContentContainer _content; #endregion Private Fields } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- OleDbEnumerator.cs
- RunInstallerAttribute.cs
- DetailsViewRowCollection.cs
- loginstatus.cs
- metadatamappinghashervisitor.cs
- COM2PropertyBuilderUITypeEditor.cs
- DocumentViewerBase.cs
- MasterPageCodeDomTreeGenerator.cs
- XmlTypeAttribute.cs
- PeerCollaboration.cs
- ExecutionContext.cs
- ReaderWriterLock.cs
- FileLevelControlBuilderAttribute.cs
- DataGridViewCellValueEventArgs.cs
- SqlIdentifier.cs
- LineSegment.cs
- EmptyImpersonationContext.cs
- BinaryFormatterSinks.cs
- HtmlInputRadioButton.cs
- BindingExpressionBase.cs
- RowToParametersTransformer.cs
- MetadataProperty.cs
- OdbcReferenceCollection.cs
- AccessDataSource.cs
- ClientConfigurationHost.cs
- EditCommandColumn.cs
- MediaTimeline.cs
- IItemContainerGenerator.cs
- XmlCharacterData.cs
- PointHitTestParameters.cs
- CompressedStack.cs
- CustomValidator.cs
- RoutedEventArgs.cs
- XslTransform.cs
- RectAnimationBase.cs
- CardSpacePolicyElement.cs
- ServiceInfo.cs
- PropertyOrder.cs
- SrgsItemList.cs
- ToolStripGripRenderEventArgs.cs
- LinkConverter.cs
- DataControlFieldHeaderCell.cs
- DurableTimerExtension.cs
- NameObjectCollectionBase.cs
- BitmapEffectInputConnector.cs
- BitmapEffectDrawing.cs
- securitycriticaldataformultiplegetandset.cs
- ObjectListItem.cs
- NetPeerTcpBindingElement.cs
- TextFormatter.cs
- LogicalExpr.cs
- CodeMemberMethod.cs
- ActivityExecutorDelegateInfo.cs
- AccessorTable.cs
- TextParaClient.cs
- SizeAnimation.cs
- SortedList.cs
- ProtectedConfigurationProviderCollection.cs
- XmlJsonReader.cs
- XmlSchemaAttribute.cs
- PointConverter.cs
- ImageFormatConverter.cs
- SpecularMaterial.cs
- QilName.cs
- SystemColors.cs
- DefaultValueAttribute.cs
- dsa.cs
- Message.cs
- Brushes.cs
- EnumerableRowCollection.cs
- DataSvcMapFileSerializer.cs
- HwndHostAutomationPeer.cs
- DataKeyArray.cs
- RawStylusInputCustomData.cs
- QueuePropertyVariants.cs
- XPathNodeInfoAtom.cs
- EntityDataSourceChangingEventArgs.cs
- NamedPipeConnectionPool.cs
- cookiecontainer.cs
- ActivityTrace.cs
- TableDetailsRow.cs
- ISCIIEncoding.cs
- RoutedCommand.cs
- EncryptedKeyIdentifierClause.cs
- Thread.cs
- ManipulationStartingEventArgs.cs
- SendingRequestEventArgs.cs
- WebPartDescriptionCollection.cs
- OleDbTransaction.cs
- Soap11ServerProtocol.cs
- QilScopedVisitor.cs
- SecurityRuntime.cs
- HtmlHead.cs
- GridViewColumnHeader.cs
- DesignerView.Commands.cs
- XmlSortKey.cs
- ClientWindowsAuthenticationMembershipProvider.cs
- ScriptManager.cs
- KeyPressEvent.cs
- ExternalDataExchangeClient.cs