/// <summary>Returns a value that indicates whether a given <see cref="T:System.Windows.Annotations.ContentLocatorPart" /> is identical to this <see cref="T:System.Windows.Annotations.ContentLocatorPart" />.</summary> /// <param name="obj">The part to compare for equality.</param> /// <returns> /// <see langword="true" /> if the <see cref="P:System.Windows.Annotations.ContentLocatorPart.NameValuePairs" /> within both parts are identical; otherwise, <see langword="false" />.</returns> // Token: 0x06006326 RID: 25382 RVA: 0x001BE010 File Offset: 0x001BC210 public override bool Equals(object obj) { ContentLocatorPart contentLocatorPart = obj as ContentLocatorPart; if (contentLocatorPart == this) { return(true); } if (contentLocatorPart == null) { return(false); } if (!this._type.Equals(contentLocatorPart.PartType)) { return(false); } if (contentLocatorPart.NameValuePairs.Count != this._nameValues.Count) { return(false); } foreach (KeyValuePair <string, string> keyValuePair in this._nameValues) { string b; if (!contentLocatorPart._nameValues.TryGetValue(keyValuePair.Key, out b)) { return(false); } if (keyValuePair.Value != b) { return(false); } } return(true); }
/// <summary>Returns a value that indicates whether the starting sequence of <see cref="T:System.Windows.Annotations.ContentLocatorPart" /> elements in a specified <see cref="T:System.Windows.Annotations.ContentLocator" /> are identical to those in this <see cref="T:System.Windows.Annotations.ContentLocator" />.</summary> /// <param name="locator">The <see cref="T:System.Windows.Annotations.ContentLocator" /> with the list of <see cref="T:System.Windows.Annotations.ContentLocatorPart" /> elements to compare with this <see cref="T:System.Windows.Annotations.ContentLocator" />.</param> /// <returns> /// <see langword="true" /> if the starting sequence of <see cref="T:System.Windows.Annotations.ContentLocatorPart" /> elements in this <see cref="T:System.Windows.Annotations.ContentLocator" /> matches those in the specified <paramref name="locator" />; otherwise, <see langword="false" />.</returns> /// <exception cref="T:System.ArgumentNullException"> /// <paramref name="locator" /> is <see langword="null" />.</exception> // Token: 0x06006337 RID: 25399 RVA: 0x001BE4EC File Offset: 0x001BC6EC public bool StartsWith(ContentLocator locator) { if (locator == null) { throw new ArgumentNullException("locator"); } Invariant.Assert(locator.Parts != null, "Locator has null Parts property."); if (this.Parts.Count < locator.Parts.Count) { return(false); } for (int i = 0; i < locator.Parts.Count; i++) { ContentLocatorPart contentLocatorPart = locator.Parts[i]; ContentLocatorPart contentLocatorPart2 = this.Parts[i]; if (contentLocatorPart == null && contentLocatorPart2 != null) { return(false); } if (!contentLocatorPart.Matches(contentLocatorPart2)) { return(false); } } return(true); }
//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods /// <summary> /// Determines if this list begins with the ContentLocatorParts that /// make up matchList. All ContentLocatorParts in matchList must /// be present and in the same order in this list for /// true to be returned. /// </summary> /// <param name="locator">the list to compare with</param> /// <returns> /// true if this list begins with the ContentLocatorParts in locator; /// false otherwise. If locator is longer than this locator, will /// return false as well. /// </returns> /// <exception cref="ArgumentNullException">locator is null</exception> public bool StartsWith(ContentLocator locator) { if (locator == null) { throw new ArgumentNullException("locator"); } Invariant.Assert(locator.Parts != null, "Locator has null Parts property."); // If this locator is shorter than matchList, then this can't contain matchList. #pragma warning suppress 6506 // Invariant.Assert(locator.Parts != null) if (this.Parts.Count < locator.Parts.Count) { return(false); } for (int locatorPartIndex = 0; locatorPartIndex < locator.Parts.Count; locatorPartIndex++) { ContentLocatorPart left = locator.Parts[locatorPartIndex]; ContentLocatorPart right = this.Parts[locatorPartIndex]; // ContentLocator parts can be null so check for that case here if (left == null && right != null) { return(false); } if (!left.Matches(right)) { return(false); } } return(true); }
// Token: 0x0600632D RID: 25389 RVA: 0x001BE15C File Offset: 0x001BC35C internal bool Matches(ContentLocatorPart part) { bool flag = false; string value; this._nameValues.TryGetValue("IncludeOverlaps", out value); if (!bool.TryParse(value, out flag) || !flag) { return(this.Equals(part)); } if (part == this) { return(true); } if (!this._type.Equals(part.PartType)) { return(false); } int num; int num2; TextSelectionProcessor.GetMaxMinLocatorPartValues(this, out num, out num2); int num3; int num4; TextSelectionProcessor.GetMaxMinLocatorPartValues(part, out num3, out num4); return((num == num3 && num2 == num4) || (num != int.MinValue && ((num3 >= num && num3 <= num2) || (num3 < num && num4 >= num)))); }
/// <summary>Creates a modifiable deep copy clone of this <see cref="T:System.Windows.Annotations.ContentLocatorPart" />.</summary> /// <returns>A modifiable deep copy clone of this <see cref="T:System.Windows.Annotations.ContentLocatorPart" />.</returns> // Token: 0x06006328 RID: 25384 RVA: 0x001BE0CC File Offset: 0x001BC2CC public object Clone() { ContentLocatorPart contentLocatorPart = new ContentLocatorPart(this._type); foreach (KeyValuePair <string, string> keyValuePair in this._nameValues) { contentLocatorPart.NameValuePairs.Add(keyValuePair.Key, keyValuePair.Value); } return(contentLocatorPart); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// Determines if a locator part matches this locator part. Matches is /// different from equals because a locator part may be defined to match /// a range of locator parts, not just exact replicas. /// </summary> internal bool Matches(ContentLocatorPart part) { bool overlaps = false; string overlapsString; _nameValues.TryGetValue(TextSelectionProcessor.IncludeOverlaps, out overlapsString); // If IncludeOverlaps is true, a match is any locator part // whose range overlaps with ours if (Boolean.TryParse(overlapsString, out overlaps) && overlaps) { // We match ourselves if (part == this) { return(true); } // Have different type names if (!_type.Equals(part.PartType)) { return(false); } int desiredStartOffset; int desiredEndOffset; TextSelectionProcessor.GetMaxMinLocatorPartValues(this, out desiredStartOffset, out desiredEndOffset); int startOffset; int endOffset; TextSelectionProcessor.GetMaxMinLocatorPartValues(part, out startOffset, out endOffset); // Take care of an exact match to us (which may include offset==MinValue // which we don't want to handle with the formula below. if (desiredStartOffset == startOffset && desiredEndOffset == endOffset) { return(true); } // Take care of the special case of no content to match to if (desiredStartOffset == int.MinValue) { return(false); } if ((startOffset >= desiredStartOffset && startOffset <= desiredEndOffset) || (startOffset < desiredStartOffset && endOffset >= desiredStartOffset)) { return(true); } return(false); } return(this.Equals(part)); }
/// <summary> /// Create a deep clone of this ContentLocatorPart. The returned ContentLocatorPart /// is equal to this ContentLocatorPart. /// </summary> /// <returns>a deep clone of this ContentLocatorPart; never returns null</returns> public object Clone() { ContentLocatorPart newPart = new ContentLocatorPart(_type); foreach (KeyValuePair <string, string> k_v in _nameValues) { newPart.NameValuePairs.Add(k_v.Key, k_v.Value); } return(newPart); }
//------------------------------------------------------ // // Public Methods // //------------------------------------------------------ #region Public Methods /// <summary> /// Compares two ContentLocatorParts for equality. They are equal if they /// contain the same set of name/value pairs. /// </summary> /// <param name="obj">second locator part</param> /// <returns>true - the ContentLocatorParts are equal, false - different</returns> public override bool Equals(object obj) { ContentLocatorPart part = obj as ContentLocatorPart; string otherValue; // We are equal to ourselves if (part == this) { return(true); } // Not a locator part if (part == null) { return(false); } // Have different type names if (!_type.Equals(part.PartType)) { return(false); } // Have different number of name/value pairs if (part.NameValuePairs.Count != _nameValues.Count) { return(false); } foreach (KeyValuePair <string, string> k_v in _nameValues) { // A name/value pair isn't present or has a different value if (!part._nameValues.TryGetValue(k_v.Key, out otherValue)) { return(false); } if (k_v.Value != otherValue) { return(false); } } return(true); }
/// <summary> /// Creates a deep copy of this list. A new list with a clone of /// every ContentLocatorPart in this list, in the same order, is returned. /// Never returns null. /// </summary> /// <returns>a deep copy of this list</returns> public override Object Clone() { ContentLocator clone = new ContentLocator(); ContentLocatorPart newPart = null; foreach (ContentLocatorPart part in this.Parts) { if (part != null) { newPart = (ContentLocatorPart)part.Clone(); } else { newPart = null; } clone.Parts.Add(newPart); } return(clone); }
/// <summary> /// Creates a DataId locator part for node. /// </summary> /// <param name="node">logical tree node for which a locator part will be created</param> /// <returns>a DataId locator part for node, or null if node has no /// value for the DataIdProperty</returns> /// <exception cref="ArgumentNullException">node is null</exception> private ContentLocatorPart CreateLocatorPart(DependencyObject node) { Debug.Assert(node != null, "DependencyObject can not be null"); // Get values from the node string nodeId = GetNodeId(node); if ((nodeId == null) || (nodeId.Length == 0)) return null; ContentLocatorPart part = new ContentLocatorPart(DataIdElementName); part.NameValuePairs.Add(ValueAttributeName, nodeId); return part; }
//----------------------------------------------------- // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// Determines if a locator part matches this locator part. Matches is /// different from equals because a locator part may be defined to match /// a range of locator parts, not just exact replicas. /// </summary> internal bool Matches(ContentLocatorPart part) { bool overlaps = false; string overlapsString; _nameValues.TryGetValue(TextSelectionProcessor.IncludeOverlaps, out overlapsString); // If IncludeOverlaps is true, a match is any locator part // whose range overlaps with ours if (Boolean.TryParse(overlapsString, out overlaps) && overlaps) { // We match ourselves if (part == this) { return true; } // Have different type names if (!_type.Equals(part.PartType)) { return false; } int desiredStartOffset; int desiredEndOffset; TextSelectionProcessor.GetMaxMinLocatorPartValues(this, out desiredStartOffset, out desiredEndOffset); int startOffset; int endOffset; TextSelectionProcessor.GetMaxMinLocatorPartValues(part, out startOffset, out endOffset); // Take care of an exact match to us (which may include offset==MinValue // which we don't want to handle with the formula below. if (desiredStartOffset == startOffset && desiredEndOffset == endOffset) { return true; } // Take care of the special case of no content to match to if (desiredStartOffset == int.MinValue) { return false; } if ((startOffset >= desiredStartOffset && startOffset <= desiredEndOffset) || (startOffset < desiredStartOffset && endOffset >= desiredStartOffset)) { return true; } return false; } return this.Equals(part); }
/// <summary> /// Searches the logical tree for a node matching the values of /// locatorPart. The search begins with startNode. /// </summary> /// <param name="locatorPart">locator part to be matched, must be of the type /// handled by this processor</param> /// <param name="startNode">logical tree node to start search at</param> /// <param name="continueResolving">return flag indicating whether the search /// should continue (presumably because the search was not exhaustive)</param> /// <returns>returns a node that matches the locator part; null if no such /// node is found</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect /// type</exception> public override DependencyObject ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out bool continueResolving) { if (locatorPart == null) throw new ArgumentNullException("locatorPart"); if (startNode == null) throw new ArgumentNullException("startNode"); if (DataIdElementName != locatorPart.PartType) throw new ArgumentException(SR.Get(SRID.IncorrectLocatorPartType, locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name), "locatorPart"); // Initial value continueResolving = true; // Get the values from the locator part... string id = locatorPart.NameValuePairs[ValueAttributeName]; if(id == null) { throw new ArgumentException(SR.Get(SRID.IncorrectLocatorPartType, locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name), "locatorPart"); } // and from the node to examine. string nodeId = GetNodeId(startNode); if (nodeId != null) { if (nodeId.Equals(id)) { return startNode; } else { // If there was a value and it didn't match, // we shouldn't bother checking the subtree continueResolving = false; } } return null; }
/// <summary> /// Extracts the values of attributes from a locator part. /// </summary> /// <param name="locatorPart">the locator part to extract values from</param> /// <param name="segmentNumber">number of segment value to retrieve</param> /// <param name="start">the start point value based on StartXAttribute and StartYAttribute values</param> /// <param name="end">the end point value based on EndXAttribyte and EndYattribute values</param> private void GetLocatorPartSegmentValues(ContentLocatorPart locatorPart, int segmentNumber, out Point start, out Point end) { if (locatorPart == null) throw new ArgumentNullException("locatorPart"); if (FixedTextElementName != locatorPart.PartType) throw new ArgumentException(SR.Get(SRID.IncorrectLocatorPartType, locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name), "locatorPart"); string segmentValue = locatorPart.NameValuePairs[TextSelectionProcessor.SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo)]; if (segmentValue == null) throw new ArgumentException(SR.Get(SRID.InvalidLocatorPart, TextSelectionProcessor.SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo))); string[] values = segmentValue.Split(TextSelectionProcessor.Separator); if (values.Length != 4) throw new ArgumentException(SR.Get(SRID.InvalidLocatorPart, TextSelectionProcessor.SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo))); start = GetPoint(values[0], values[1]); end = GetPoint(values[2], values[3]); }
/// <summary> /// Create a deep clone of this ContentLocatorPart. The returned ContentLocatorPart /// is equal to this ContentLocatorPart. /// </summary> /// <returns>a deep clone of this ContentLocatorPart; never returns null</returns> public object Clone() { ContentLocatorPart newPart = new ContentLocatorPart(_type); foreach (KeyValuePair<string, string> k_v in _nameValues) { newPart.NameValuePairs.Add(k_v.Key, k_v.Value); } return newPart; }
/// <summary> /// Searches the logical tree for a node matching the values of /// locatorPart. A match must be a chunk which produces the same /// fingerprint as in the locator part. /// </summary> /// <param name="locatorPart">locator part to be matched, must be of the type /// handled by this processor</param> /// <param name="startNode">logical tree node to start search at</param> /// <param name="continueResolving">return flag indicating whether the search /// should continue (presumably because the search was not exhaustive). This /// processor will return false if the startNode is a FixedPage /// with a different page number than the locator part's page number. /// Otherwise the return value will be true. /// inside the FixedPage(like TextSelection) </param> /// <returns>returns a node that matches the locator part; null if no such /// node is found</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect /// type</exception> public override DependencyObject ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out bool continueResolving) { if (locatorPart == null) throw new ArgumentNullException("locatorPart"); if (startNode == null) throw new ArgumentNullException("startNode"); if (PageNumberElementName != locatorPart.PartType) throw new ArgumentException(SR.Get(SRID.IncorrectLocatorPartType, locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name), "locatorPart"); // Initial value continueResolving = true; int pageNumber = 0; string pageNumberString = locatorPart.NameValuePairs[ValueAttributeName]; if (pageNumberString != null) pageNumber = Int32.Parse(pageNumberString, NumberFormatInfo.InvariantInfo); else throw new ArgumentException(SR.Get(SRID.IncorrectLocatorPartType, locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name), "locatorPart"); // Get the actual FixedPage for the page number specified in the LocatorPart. We need // the actual FixedPage cause its what exists in the visual tree and what we'll use to // anchor the annotations to. FixedDocumentPage page = null; IDocumentPaginatorSource document = null; DocumentPageView dpv = null; if (_useLogicalTree) { document = startNode as FixedDocument; if (document != null) { page = document.DocumentPaginator.GetPage(pageNumber) as FixedDocumentPage; } else { document = startNode as FixedDocumentSequence; if (document != null) { FixedDocumentSequenceDocumentPage sequencePage = document.DocumentPaginator.GetPage(pageNumber) as FixedDocumentSequenceDocumentPage; if (sequencePage != null) { page = sequencePage.ChildDocumentPage as FixedDocumentPage; } } } } else { dpv = startNode as DocumentPageView; if (dpv != null) { page = dpv.DocumentPage as FixedDocumentPage; if (page == null) { FixedDocumentSequenceDocumentPage sequencePage = dpv.DocumentPage as FixedDocumentSequenceDocumentPage; if (sequencePage != null) { page = sequencePage.ChildDocumentPage as FixedDocumentPage; } } // If this was the wrong fixed page we want to stop searching this subtree if (page != null && dpv.PageNumber != pageNumber) { continueResolving = false; page = null; } } } if (page != null) { return page.FixedPage; } return null; }
/// <summary> /// Creates a TextRange object spanning the portion of 'startNode' /// specified by 'locatorPart'. /// </summary> /// <param name="locatorPart">FixedTextRange locator part specifying start and end point of /// the TextRange</param> /// <param name="startNode">the FixedPage containing this locator part</param> /// <param name="attachmentLevel">set to AttachmentLevel.Full if the FixedPage for the locator /// part was found, AttachmentLevel.Unresolved otherwise</param> /// <returns>a TextRange spanning the text between start end end point in the FixedTextRange /// locator part /// , null if selection described by locator part could not be /// recreated</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect type</exception> /// <exception cref="ArgumentException">startNode is not a FixedPage</exception> /// <exception cref="ArgumentException">startNode does not belong to the DocumentViewer</exception> public override Object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel) { if (startNode == null) throw new ArgumentNullException("startNode"); DocumentPage docPage = null; FixedPage page = startNode as FixedPage; if (page != null) { docPage = GetDocumentPage(page); } else { // If we were passed a DPV because we are walking the visual tree, // extract the DocumentPage from it; its TextView will be used to // turn coordinates into text positions DocumentPageView dpv = startNode as DocumentPageView; if (dpv != null) { docPage = dpv.DocumentPage as FixedDocumentPage; if (docPage == null) { docPage = dpv.DocumentPage as FixedDocumentSequenceDocumentPage; } } } if (docPage == null) { throw new ArgumentException(SR.Get(SRID.StartNodeMustBeDocumentPageViewOrFixedPage), "startNode"); } if (locatorPart == null) throw new ArgumentNullException("locatorPart"); attachmentLevel = AttachmentLevel.Unresolved; ITextView tv = (ITextView)((IServiceProvider)docPage).GetService(typeof(ITextView)); Debug.Assert(tv != null); ReadOnlyCollection<TextSegment> ts = tv.TextSegments; //check first if a TextRange can be generated if (ts == null || ts.Count <= 0) return null; TextAnchor resolvedAnchor = new TextAnchor(); if (docPage != null) { string stringCount = locatorPart.NameValuePairs["Count"]; if (stringCount == null) throw new ArgumentException(SR.Get(SRID.InvalidLocatorPart, TextSelectionProcessor.CountAttribute)); int count = Int32.Parse(stringCount, NumberFormatInfo.InvariantInfo); for(int i = 0; i < count; i++) { // First we extract the start and end Point from the locator part. Point start; Point end; GetLocatorPartSegmentValues(locatorPart, i, out start, out end); //calulate start ITextPointer ITextPointer segStart; if (double.IsNaN(start.X) || double.IsNaN(start.Y)) { //get start of the page segStart = FindStartVisibleTextPointer(docPage); } else { //convert Point to TextPointer segStart = tv.GetTextPositionFromPoint(start, true); } if (segStart == null) { //selStart can be null if there are no insertion points on this page continue; } //calulate end ITextPointer ITextPointer segEnd; if (double.IsNaN(end.X) || double.IsNaN(end.Y)) { segEnd = FindEndVisibleTextPointer(docPage); } else { //convert Point to TextPointer segEnd = tv.GetTextPositionFromPoint(end, true); } //end TP can not be null when start is not Invariant.Assert(segEnd != null, "end TP is null when start TP is not"); attachmentLevel = AttachmentLevel.Full; // Not always true right? resolvedAnchor.AddTextSegment(segStart, segEnd); } } if (resolvedAnchor.TextSegments.Count > 0) return resolvedAnchor; else return null; }
/// <summary> /// Reads the internal data for this ContentLocator from the reader. This /// method is used by an XmlSerializer to deserialize a ContentLocator. Don't /// use this method directly, to deserialize a ContentLocator from Xml, use an /// XmlSerializer. /// </summary> /// <param name="reader">the reader to read internal data from</param> /// <exception cref="ArgumentNullException">reader is null</exception> public void ReadXml(XmlReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } // We expect no attributes on a "ContentLocator", // so throw using the name of one of the unexpected attributes Annotation.CheckForNonNamespaceAttribute(reader, AnnotationXmlConstants.Elements.ContentLocator); if (!reader.IsEmptyElement) { reader.Read(); // Reads the start of the "ContentLocator" element // ContentLocatorParts cannot write themselves out (see above). They could read // themselves in but instead of having write code in one place and read // code somewhere else - we keep it together in this class. while (!(AnnotationXmlConstants.Elements.ContentLocator == reader.LocalName && XmlNodeType.EndElement == reader.NodeType)) { if (XmlNodeType.Element != reader.NodeType) { throw new XmlException(SR.Get(SRID.InvalidXmlContent, AnnotationXmlConstants.Elements.ContentLocator)); } ContentLocatorPart part = new ContentLocatorPart(new XmlQualifiedName(reader.LocalName, reader.NamespaceURI)); // Read each of the Item elements within the ContentLocatorPart if (!reader.IsEmptyElement) { // We expect no attributes on a locator part tag, // so throw using the name of one of the unexpected attributes Annotation.CheckForNonNamespaceAttribute(reader, part.PartType.Name); reader.Read(); // Read the start of the locator part tag while (!(XmlNodeType.EndElement == reader.NodeType && part.PartType.Name == reader.LocalName)) { if (AnnotationXmlConstants.Elements.Item == reader.LocalName && reader.NamespaceURI == AnnotationXmlConstants.Namespaces.CoreSchemaNamespace) { string name = null; string value = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case AnnotationXmlConstants.Attributes.ItemName: name = reader.Value; break; case AnnotationXmlConstants.Attributes.ItemValue: value = reader.Value; break; default: if (!Annotation.IsNamespaceDeclaration(reader)) { throw new XmlException(SR.Get(SRID.UnexpectedAttribute, reader.LocalName, AnnotationXmlConstants.Elements.Item)); } break; } } if (name == null) { throw new XmlException(SR.Get(SRID.RequiredAttributeMissing, AnnotationXmlConstants.Attributes.ItemName, AnnotationXmlConstants.Elements.Item)); } if (value == null) { throw new XmlException(SR.Get(SRID.RequiredAttributeMissing, AnnotationXmlConstants.Attributes.ItemValue, AnnotationXmlConstants.Elements.Item)); } reader.MoveToContent(); part.NameValuePairs.Add(name, value); bool isEmpty = reader.IsEmptyElement; reader.Read(); // Read the beginning of the complete Item tag if (!isEmpty) { if (!(XmlNodeType.EndElement == reader.NodeType && AnnotationXmlConstants.Elements.Item == reader.LocalName)) { // Should not contain any content, only attributes throw new XmlException(SR.Get(SRID.InvalidXmlContent, AnnotationXmlConstants.Elements.Item)); } else { reader.Read(); // Read the end of the Item tag } } } else { // The locator part contains data other than just "Item" tags throw new XmlException(SR.Get(SRID.InvalidXmlContent, part.PartType.Name)); } } } _parts.Add(part); reader.Read(); // Read the ContentLocatorPart element } } reader.Read(); // Reads the end of the "ContentLocator" element (or whole element if empty) }
GenerateLocatorParts(Object selection, DependencyObject startNode) { if (startNode == null) throw new ArgumentNullException("startNode"); List<ContentLocatorPart> res = null; ITextView textView = VerifySelection(selection); res = new List<ContentLocatorPart>(1); int startOffset; int endOffset; if (textView != null && textView.IsValid) { GetTextViewTextRange(textView, out startOffset, out endOffset); } else { // This causes no content to be loaded startOffset = -1; endOffset = -1; } ContentLocatorPart part = new ContentLocatorPart(TextSelectionProcessor.CharacterRangeElementName);// DocumentPageViewLocatorPart(); part.NameValuePairs.Add(TextSelectionProcessor.CountAttribute, 1.ToString(NumberFormatInfo.InvariantInfo)); part.NameValuePairs.Add(TextSelectionProcessor.SegmentAttribute + 0.ToString(NumberFormatInfo.InvariantInfo), startOffset.ToString(NumberFormatInfo.InvariantInfo) + TextSelectionProcessor.Separator[0] + endOffset.ToString(NumberFormatInfo.InvariantInfo)); part.NameValuePairs.Add(TextSelectionProcessor.IncludeOverlaps, Boolean.TrueString); res.Add(part); return res; }
/// <summary> /// Creates a selection object spanning the portion of 'startNode' /// specified by 'locatorPart'. /// </summary> /// <param name="locatorPart">locator part specifying data to be spanned</param> /// <param name="startNode">the node to be spanned by the created /// selection</param> /// <param name="attachmentLevel">describes the level of resolution reached when resolving the locator part</param> /// <returns>a selection spanning the portion of 'startNode' specified by /// 'locatorPart'</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect type</exception> public abstract Object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel);
/// <summary> /// This processor doesn't resolve ContentLocatorParts. It simply returns null. /// </summary> /// <param name="locatorPart">locator part specifying data to be spanned</param> /// <param name="startNode">the node to be spanned by the created /// selection</param> /// <param name="attachmentLevel">always set to AttachmentLevel.Unresolved</param> /// <returns>always returns null; this processor does not resolve ContentLocatorParts</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are null</exception> public override Object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel) { if (locatorPart == null) throw new ArgumentNullException("locatorPart"); if (startNode == null) throw new ArgumentNullException("startNode"); attachmentLevel = AttachmentLevel.Unresolved; // ContentLocator Parts generated by this selection processor cannot be resolved return null; }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// Gets the smallest offset and the largest offset from all the segments defined in the locator part. /// </summary> internal static void GetMaxMinLocatorPartValues(ContentLocatorPart locatorPart, out int startOffset, out int endOffset) { if (locatorPart == null) throw new ArgumentNullException("locatorPart"); string stringCount = locatorPart.NameValuePairs[CountAttribute]; if (stringCount == null) throw new ArgumentException(SR.Get(SRID.InvalidLocatorPart, TextSelectionProcessor.CountAttribute)); int count = Int32.Parse(stringCount,NumberFormatInfo.InvariantInfo); startOffset = Int32.MaxValue; endOffset = 0; int segStart; int segEnd; for (int i = 0; i < count; i++) { GetLocatorPartSegmentValues(locatorPart, i, out segStart, out segEnd); if (segStart < startOffset) startOffset = segStart; if (segEnd > endOffset) endOffset = segEnd; } }
/// <summary> /// Searches the logical tree for a node matching the values of /// locatorPart. The search begins with startNode. /// </summary> /// <remarks> /// Subclasses can choose to only examine startNode or traverse /// the logical tree looking for a match. The algorithms for some /// locator part types may require a search of the tree instead of /// a simple examination of one node. /// </remarks> /// <param name="locatorPart">locator part to be matched, must be of the type /// handled by this processor</param> /// <param name="startNode">logical tree node to start search at</param> /// <param name="continueResolving">return flag indicating whether the search /// should continue (presumably because the search was not exhaustive)</param> /// <returns>returns a node that matches the locator part; null if no such /// node is found</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect /// type</exception> public abstract DependencyObject ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out bool continueResolving);
/// <summary> /// Reads the internal data for this ContentLocator from the reader. This /// method is used by an XmlSerializer to deserialize a ContentLocator. Don't /// use this method directly, to deserialize a ContentLocator from Xml, use an /// XmlSerializer. /// </summary> /// <param name="reader">the reader to read internal data from</param> /// <exception cref="ArgumentNullException">reader is null</exception> public void ReadXml(XmlReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } // We expect no attributes on a "ContentLocator", // so throw using the name of one of the unexpected attributes Annotation.CheckForNonNamespaceAttribute(reader, AnnotationXmlConstants.Elements.ContentLocator); if (!reader.IsEmptyElement) { reader.Read(); // Reads the start of the "ContentLocator" element // ContentLocatorParts cannot write themselves out (see above). They could read // themselves in but instead of having write code in one place and read // code somewhere else - we keep it together in this class. while (!(AnnotationXmlConstants.Elements.ContentLocator == reader.LocalName && XmlNodeType.EndElement == reader.NodeType)) { if (XmlNodeType.Element != reader.NodeType) { throw new XmlException(SR.Get(SRID.InvalidXmlContent, AnnotationXmlConstants.Elements.ContentLocator)); } ContentLocatorPart part = new ContentLocatorPart(new XmlQualifiedName(reader.LocalName, reader.NamespaceURI)); // Read each of the Item elements within the ContentLocatorPart if (!reader.IsEmptyElement) { // We expect no attributes on a locator part tag, // so throw using the name of one of the unexpected attributes Annotation.CheckForNonNamespaceAttribute(reader, part.PartType.Name); reader.Read(); // Read the start of the locator part tag while (!(XmlNodeType.EndElement == reader.NodeType && part.PartType.Name == reader.LocalName)) { if (AnnotationXmlConstants.Elements.Item == reader.LocalName && reader.NamespaceURI == AnnotationXmlConstants.Namespaces.CoreSchemaNamespace) { string name = null; string value = null; while (reader.MoveToNextAttribute()) { switch (reader.LocalName) { case AnnotationXmlConstants.Attributes.ItemName: name = reader.Value; break; case AnnotationXmlConstants.Attributes.ItemValue: value = reader.Value; break; default: if (!Annotation.IsNamespaceDeclaration(reader)) throw new XmlException(SR.Get(SRID.UnexpectedAttribute, reader.LocalName, AnnotationXmlConstants.Elements.Item)); break; } } if (name == null) { throw new XmlException(SR.Get(SRID.RequiredAttributeMissing, AnnotationXmlConstants.Attributes.ItemName, AnnotationXmlConstants.Elements.Item)); } if (value == null) { throw new XmlException(SR.Get(SRID.RequiredAttributeMissing, AnnotationXmlConstants.Attributes.ItemValue, AnnotationXmlConstants.Elements.Item)); } reader.MoveToContent(); part.NameValuePairs.Add(name, value); bool isEmpty = reader.IsEmptyElement; reader.Read(); // Read the beginning of the complete Item tag if (!isEmpty) { if (!(XmlNodeType.EndElement == reader.NodeType && AnnotationXmlConstants.Elements.Item == reader.LocalName)) { // Should not contain any content, only attributes throw new XmlException(SR.Get(SRID.InvalidXmlContent, AnnotationXmlConstants.Elements.Item)); } else { reader.Read(); // Read the end of the Item tag } } } else { // The locator part contains data other than just "Item" tags throw new XmlException(SR.Get(SRID.InvalidXmlContent, part.PartType.Name)); } } } _parts.Add(part); reader.Read(); // Read the ContentLocatorPart element } } reader.Read(); // Reads the end of the "ContentLocator" element (or whole element if empty) }
GenerateLocatorParts(Object selection, DependencyObject startNode) { if (startNode == null) throw new ArgumentNullException("startNode"); if (selection == null) throw new ArgumentNullException("selection"); ITextPointer start; ITextPointer end; IList<TextSegment> textSegments = null; TextSelectionHelper.CheckSelection(selection, out start, out end, out textSegments); if (!(start is TextPointer)) throw new ArgumentException(SR.Get(SRID.WrongSelectionType), "selection"); ITextPointer elementStart; ITextPointer elementEnd; // If we can't get the start/end of the node then we can't generate a locator part if (!GetNodesStartAndEnd(startNode, out elementStart, out elementEnd)) return null; if (elementStart.CompareTo(end) > 0) throw new ArgumentException(SR.Get(SRID.InvalidStartNodeForTextSelection), "startNode"); if (elementEnd.CompareTo(start) < 0) throw new ArgumentException(SR.Get(SRID.InvalidStartNodeForTextSelection), "startNode"); ContentLocatorPart part = new ContentLocatorPart(CharacterRangeElementName); int startOffset = 0; int endOffset = 0; for(int i = 0; i < textSegments.Count; i++) { GetTextSegmentValues(textSegments[i], elementStart, elementEnd, out startOffset, out endOffset); part.NameValuePairs.Add(SegmentAttribute + i.ToString(NumberFormatInfo.InvariantInfo), startOffset.ToString(NumberFormatInfo.InvariantInfo) + TextSelectionProcessor.Separator[0] + endOffset.ToString(NumberFormatInfo.InvariantInfo)); } part.NameValuePairs.Add(CountAttribute, textSegments.Count.ToString(NumberFormatInfo.InvariantInfo)); List<ContentLocatorPart> res = new List<ContentLocatorPart>(1); res.Add(part); return res; }
GenerateLocatorParts(Object selection, DependencyObject startNode) { if (startNode == null) throw new ArgumentNullException("startNode"); if (selection == null) throw new ArgumentNullException("selection"); CheckSelection(selection); FixedPageProxy fp = startNode as FixedPageProxy; if (fp == null) throw new ArgumentException(SR.Get(SRID.StartNodeMustBeFixedPageProxy), "startNode"); ContentLocatorPart part = new ContentLocatorPart(FixedTextElementName); if (fp.Segments.Count == 0) { part.NameValuePairs.Add(TextSelectionProcessor.CountAttribute, 1.ToString(NumberFormatInfo.InvariantInfo)); part.NameValuePairs.Add(TextSelectionProcessor.SegmentAttribute + 0.ToString(NumberFormatInfo.InvariantInfo), ",,,"); } else { part.NameValuePairs.Add(TextSelectionProcessor.CountAttribute, fp.Segments.Count.ToString(NumberFormatInfo.InvariantInfo)); for (int i = 0; i < fp.Segments.Count; i++) { string value = ""; if (!double.IsNaN(fp.Segments[i].Start.X)) { value += fp.Segments[i].Start.X.ToString(NumberFormatInfo.InvariantInfo) + TextSelectionProcessor.Separator[0] + fp.Segments[i].Start.Y.ToString(NumberFormatInfo.InvariantInfo); } else { value += TextSelectionProcessor.Separator[0]; } value += TextSelectionProcessor.Separator[0]; if (!double.IsNaN(fp.Segments[i].End.X)) { value += fp.Segments[i].End.X.ToString(NumberFormatInfo.InvariantInfo) + TextSelectionProcessor.Separator[0] + fp.Segments[i].End.Y.ToString(NumberFormatInfo.InvariantInfo); } else { value += TextSelectionProcessor.Separator[0]; } part.NameValuePairs.Add(TextSelectionProcessor.SegmentAttribute + i.ToString(NumberFormatInfo.InvariantInfo), value); } } List<ContentLocatorPart> res = new List<ContentLocatorPart>(1); res.Add(part); return res; }
/// <summary> /// Creates a selection object spanning the portion of 'startNode' /// specified by 'locatorPart'. /// </summary> /// <param name="locatorPart">locator part specifying data to be spanned</param> /// <param name="startNode">the node to be spanned by the created /// selection</param> /// <param name="attachmentLevel">set to AttachmentLevel.Full if the entire range of text /// was resolved, otherwise set to StartPortion, MiddlePortion, or EndPortion based on /// which part of the range was resolved</param> /// <returns>a selection spanning the portion of 'startNode' specified by /// 'locatorPart', null if selection described by locator part could not be /// recreated</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect type</exception> public override Object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel) { if (startNode == null) throw new ArgumentNullException("startNode"); if (locatorPart == null) throw new ArgumentNullException("locatorPart"); if (CharacterRangeElementName != locatorPart.PartType) throw new ArgumentException(SR.Get(SRID.IncorrectLocatorPartType, locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name), "locatorPart"); // First we extract the offset and length of the // text range from the locator part. int startOffset = 0; int endOffset = 0; string stringCount = locatorPart.NameValuePairs[CountAttribute]; if (stringCount == null) throw new ArgumentException(SR.Get(SRID.InvalidLocatorPart, TextSelectionProcessor.CountAttribute)); int count = Int32.Parse(stringCount,NumberFormatInfo.InvariantInfo); TextAnchor anchor = new TextAnchor(); attachmentLevel = AttachmentLevel.Unresolved; for (int i = 0; i < count; i++) { GetLocatorPartSegmentValues(locatorPart, i, out startOffset, out endOffset); // Now we grab the TextRange so we can create a selection. // TextBox doesn't expose its internal TextRange so we use // its API for creating and getting the selection. ITextPointer elementStart; ITextPointer elementEnd; // If we can't get the start/end of the node then we can't resolve the locator part if (!GetNodesStartAndEnd(startNode, out elementStart, out elementEnd)) return null; // If the offset is not withing the element's text range we return null int textRangeLength = elementStart.GetOffsetToPosition(elementEnd); if (startOffset > textRangeLength) return null; ITextPointer start = elementStart.CreatePointer(startOffset);// new TextPointer((TextPointer)elementStart, startOffset); ITextPointer end = (textRangeLength <= endOffset) ? elementEnd.CreatePointer() : //new TextPointer((TextPointer)elementEnd) : elementStart.CreatePointer(endOffset);// new TextPointer((TextPointer)elementStart, endOffset); //we do not process 0 length selection if (start.CompareTo(end) >= 0) return null; anchor.AddTextSegment(start, end); } //we do not support 0 or negative length selection if (anchor.IsEmpty) { throw new ArgumentException(SR.Get(SRID.IncorrectAnchorLength), "locatorPart"); } attachmentLevel = AttachmentLevel.Full; if (_clamping) { ITextPointer currentStart = anchor.Start; ITextPointer currentEnd = anchor.End; IServiceProvider serviceProvider = null; ITextView textView = null; if (_targetPage != null) { serviceProvider = _targetPage as IServiceProvider; } else { FlowDocument content = currentStart.TextContainer.Parent as FlowDocument; serviceProvider = PathNode.GetParent(content as DependencyObject) as IServiceProvider; } Invariant.Assert(serviceProvider != null, "No ServiceProvider found to get TextView from."); textView = serviceProvider.GetService(typeof(ITextView)) as ITextView; Invariant.Assert(textView != null, "Null TextView provided by ServiceProvider."); anchor = TextAnchor.TrimToIntersectionWith(anchor, textView.TextSegments); if (anchor == null) { attachmentLevel = AttachmentLevel.Unresolved; } else { if (anchor.Start.CompareTo(currentStart) != 0) { attachmentLevel &= ~AttachmentLevel.StartPortion; } if (anchor.End.CompareTo(currentEnd) != 0) { attachmentLevel &= ~AttachmentLevel.EndPortion; } } } return anchor; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods /// <summary> /// Creates an instance of the locator part type handled by this /// handler that represents node. /// </summary> /// <param name="page">FixedPage for which a locator part will be created</param> /// <returns> /// a locator part of the type handled by this handler representing /// the passed in node; null is returned if the locator part cannot /// be created for the node /// </returns> static internal ContentLocatorPart CreateLocatorPart(int page) { Debug.Assert(page >= 0, "page can not be negative"); ContentLocatorPart part = new ContentLocatorPart(PageNumberElementName); part.NameValuePairs.Add(ValueAttributeName, page.ToString(NumberFormatInfo.InvariantInfo)); return part; }
//------------------------------------------------------ // // Private Methods // //------------------------------------------------------ #region Private Methods /// <summary> /// Extracts the values of attributes from a locator part. /// </summary> /// <param name="locatorPart">the locator part to extract values from</param> /// <param name="segmentNumber">the number of the segment to extract values for</param> /// <param name="startOffset">value of offset attribute</param> /// <param name="endOffset">value of length attribute</param> private static void GetLocatorPartSegmentValues(ContentLocatorPart locatorPart, int segmentNumber, out int startOffset, out int endOffset) { if (segmentNumber < 0) throw new ArgumentException("segmentNumber"); string segmentString = locatorPart.NameValuePairs[SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo)]; string[] values = segmentString.Split(Separator); if (values.Length != 2) { throw new ArgumentException(SR.Get(SRID.InvalidLocatorPart, SegmentAttribute + segmentNumber.ToString(NumberFormatInfo.InvariantInfo))); } startOffset = Int32.Parse(values[0], NumberFormatInfo.InvariantInfo); endOffset = Int32.Parse(values[1], NumberFormatInfo.InvariantInfo); }
/// <summary> /// Creates a selection object spanning the portion of 'startNode' /// specified by 'locatorPart'. /// </summary> /// <param name="locatorPart">locator part specifying data to be spanned</param> /// <param name="startNode">the node to be spanned by the created /// selection</param> /// <param name="attachmentLevel">always set to AttachmentLevel.Full</param> /// <returns>a selection spanning the portion of 'startNode' specified by /// 'locatorPart'</returns> /// <exception cref="ArgumentNullException">locatorPart or startNode are /// null</exception> /// <exception cref="ArgumentException">locatorPart is of the incorrect type</exception> public override Object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel) { if (startNode == null) throw new ArgumentNullException("startNode"); if (locatorPart == null) throw new ArgumentNullException("locatorPart"); attachmentLevel = AttachmentLevel.Full; return startNode; }
/// <summary> /// Returns the selection processor registered to handle the locator /// part's type. If none is registered, null is returned. /// </summary> /// <param name="locatorPart">locator part for which a selection processor is /// being retreived</param> /// <returns>the selection processor for the locatorPart's type; null if no /// processor has been registerd for that type</returns> /// <exception cref="ArgumentNullException">locatorPart is null</exception> public SelectionProcessor GetSelectionProcessorForLocatorPart(ContentLocatorPart locatorPart) { VerifyAccess(); if (locatorPart == null) throw new ArgumentNullException("locatorPart"); return _locatorPartHandlers[locatorPart.PartType] as SelectionProcessor; }
/// <summary>Deserializes the <see cref="T:System.Windows.Annotations.ContentLocator" /> from a specified <see cref="T:System.Xml.XmlReader" />.</summary> /// <param name="reader">The XML reader to use to deserialize the <see cref="T:System.Windows.Annotations.ContentLocator" />.</param> /// <exception cref="T:System.ArgumentNullException"> /// <paramref name="reader" /> is <see langword="null" />.</exception> /// <exception cref="T:System.Xml.XmlException">The serialized XML for the <see cref="T:System.Windows.Annotations.ContentLocator" /> is not valid.</exception> // Token: 0x0600633B RID: 25403 RVA: 0x001BE740 File Offset: 0x001BC940 public void ReadXml(XmlReader reader) { if (reader == null) { throw new ArgumentNullException("reader"); } Annotation.CheckForNonNamespaceAttribute(reader, "ContentLocator"); if (!reader.IsEmptyElement) { reader.Read(); while (!("ContentLocator" == reader.LocalName) || XmlNodeType.EndElement != reader.NodeType) { if (XmlNodeType.Element != reader.NodeType) { throw new XmlException(SR.Get("InvalidXmlContent", new object[] { "ContentLocator" })); } ContentLocatorPart contentLocatorPart = new ContentLocatorPart(new XmlQualifiedName(reader.LocalName, reader.NamespaceURI)); if (!reader.IsEmptyElement) { Annotation.CheckForNonNamespaceAttribute(reader, contentLocatorPart.PartType.Name); reader.Read(); while (XmlNodeType.EndElement != reader.NodeType || !(contentLocatorPart.PartType.Name == reader.LocalName)) { if (!("Item" == reader.LocalName) || !(reader.NamespaceURI == "http://schemas.microsoft.com/windows/annotations/2003/11/core")) { throw new XmlException(SR.Get("InvalidXmlContent", new object[] { contentLocatorPart.PartType.Name })); } string text = null; string text2 = null; while (reader.MoveToNextAttribute()) { string localName = reader.LocalName; if (!(localName == "Name")) { if (!(localName == "Value")) { if (!Annotation.IsNamespaceDeclaration(reader)) { throw new XmlException(SR.Get("UnexpectedAttribute", new object[] { reader.LocalName, "Item" })); } } else { text2 = reader.Value; } } else { text = reader.Value; } } if (text == null) { throw new XmlException(SR.Get("RequiredAttributeMissing", new object[] { "Name", "Item" })); } if (text2 == null) { throw new XmlException(SR.Get("RequiredAttributeMissing", new object[] { "Value", "Item" })); } reader.MoveToContent(); contentLocatorPart.NameValuePairs.Add(text, text2); bool isEmptyElement = reader.IsEmptyElement; reader.Read(); if (!isEmptyElement) { if (XmlNodeType.EndElement != reader.NodeType || !("Item" == reader.LocalName)) { throw new XmlException(SR.Get("InvalidXmlContent", new object[] { "Item" })); } reader.Read(); } } } this._parts.Add(contentLocatorPart); reader.Read(); } } reader.Read(); }