/// <summary> /// Set <see cref="AttributeAttachmentLevel"/> from string. If the string is not valid then <see cref="AttributeAttachmentLevel"/> is set to <see cref="AttachmentLevel.None"/> /// </summary> /// <param name="level"> /// The attachment level /// </param> public void SetAttachmentLevel(string level) { if (string.IsNullOrEmpty(level) || !Enum.TryParse(level, true, out this._attributeAttachmentLevel)) { this._attributeAttachmentLevel = AttachmentLevel.None; // redundant but specified for readability } }
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors /// <summary> /// internal constructor that creates an AttachedAnnotationChangedEventArgs /// </summary> /// <param name="action">action represented by this instance</param> /// <param name="attachedAnnotation">annotation that was added/deleted/modified</param> /// <param name="previousAttachedAnchor">if action is modified, previous attached anchor</param> /// <param name="previousAttachmentLevel">if action is modified, previous attachment level</param> internal AttachedAnnotationChangedEventArgs(AttachedAnnotationAction action, IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { Invariant.Assert(attachedAnnotation != null); _action = action; _attachedAnnotation = attachedAnnotation; _previousAttachedAnchor = previousAttachedAnchor; _previousAttachmentLevel = previousAttachmentLevel; }
// Token: 0x06007BEA RID: 31722 RVA: 0x0022D40C File Offset: 0x0022B60C internal void Update(object attachedAnchor, AttachmentLevel attachmentLevel, DependencyObject parent) { this._attachedAnchor = attachedAnchor; this._attachmentLevel = attachmentLevel; this._selectionProcessor = this._locatorManager.GetSelectionProcessor(attachedAnchor.GetType()); if (parent != null) { this._parent = parent; return; } this._parent = this._selectionProcessor.GetParent(this._attachedAnchor); }
/// <summary> /// Create an instance of AttachedAnnotation with a specified parent. Takes an optional /// parent for the attached annotation. This is useful when the parent is known before /// hand and not available through the normal means (such as in printing). /// </summary> /// <param name="manager">the LocatorManager providing processors for this anchored annotation</param> /// <param name="annotation">the annotation itself</param> /// <param name="anchor">the annotation's anchor represented by the attached anchor</param> /// <param name="attachedAnchor">the attached anchor itself</param> /// <param name="attachmentLevel">the level of the attached anchor</param> /// <param name="parent">parent of the selection</param> internal AttachedAnnotation(LocatorManager manager, Annotation annotation, AnnotationResource anchor, Object attachedAnchor, AttachmentLevel attachmentLevel, DependencyObject parent) { Debug.Assert(manager != null, "LocatorManager can not be null"); Debug.Assert(annotation != null, "Annotation can not be null"); Debug.Assert(anchor != null, "Anchor can not be null"); Debug.Assert(attachedAnchor != null, "AttachedAnchor can not be null"); _annotation = annotation; _anchor = anchor; _locatorManager = manager; Update(attachedAnchor, attachmentLevel, parent); }
public AttributeCriterionMap() { Map(o => o.Name).ToAttribute("id", true) .Set(v => _name = v) .Converter(new StringConverter()); Map(o => o.AttachmentLevel).ToAttribute("attachmentLevel", false) .Set(v => _attachmentLevel = v) .Converter(new EnumConverter <AttachmentLevel>()); Map(o => o.Value).ToContent() .Set(v => _value = v) .Converter(new StringConverter()); }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// Update the attached anchor and level for this attached annotation. Internal method called by /// the annotation service when a change to an anchor is processed. Optional parent will be used /// if present. Otherwise we get the parent from the selection processor. /// </summary> /// <param name="attachedAnchor">the new attached anchor</param> /// <param name="attachmentLevel">the new attachment level</param> /// <param name="parent">optional, the parent of the attached annotation</param> internal void Update(object attachedAnchor, AttachmentLevel attachmentLevel, DependencyObject parent) { Debug.Assert(attachedAnchor != null, "AttachedAnchor can not be null"); Debug.Assert(attachmentLevel > AttachmentLevel.Unresolved && attachmentLevel <= AttachmentLevel.Incomplete, "Undefined attachment level"); _attachedAnchor = attachedAnchor; _attachmentLevel = attachmentLevel; _selectionProcessor = _locatorManager.GetSelectionProcessor(attachedAnchor.GetType()); // Use optional parent if available if (parent != null) { _parent = parent; } else { _parent = _selectionProcessor.GetParent(_attachedAnchor); } Debug.Assert(_selectionProcessor != null, SR.Get(SRID.NoProcessorForSelectionType, attachedAnchor.GetType())); }
/// <summary> /// Resolves a single locator starting at the given startNode. /// Sets the selection and attachmentLevel if necessary. /// </summary> /// <param name="selection">object representing the content that has been resolved /// so far; updated if the locator passed in is resolved</param> /// <param name="attachmentLevel">attachmentLevel of content that has been resolved /// so far; updated based on the resolution of the passed in locator</param> /// <param name="attemptedLevel">the level that is represented by this locator - /// start, middle or end</param> /// <param name="locator">the locator to resolve</param> /// <param name="offset">the offset into the locator to start the resolution at</param> /// <param name="startNode">the node to start the resolution at</param> /// <param name="skipStartNode">whether or not the start node should be looked at</param> /// <returns>the data representing the resolution of the single locator; used for /// special cases by calling code to override results from this method</returns> private ResolvingLocatorState ResolveSingleLocator(ref object selection, ref AttachmentLevel attachmentLevel, AttachmentLevel attemptedLevel, ContentLocator locator, int offset, DependencyObject startNode, bool skipStartNode) { ResolvingLocatorState data = new ResolvingLocatorState(); data.LocatorPartIndex = offset; data.ContentLocatorBase = locator; PrePostDescendentsWalker<ResolvingLocatorState> walker = new PrePostDescendentsWalker<ResolvingLocatorState>(TreeWalkPriority.VisualTree, ResolveLocatorPart, TerminateResolve, data); walker.StartWalk(startNode, skipStartNode); if (data.AttachmentLevel == AttachmentLevel.Full && data.AttachedAnchor != null) { // Merge the results with pre-existing selection if (selection != null) { SelectionProcessor selProcessor = GetSelectionProcessor(selection.GetType()); object newSelection; if (selProcessor != null) { if (selProcessor.MergeSelections(selection, data.AttachedAnchor, out newSelection)) { selection = newSelection; } else { // If we can't merge, them this locator isn't included in final results so we // we turn off the level that we are attempting to resolve attachmentLevel &= ~attemptedLevel; } } else { // If not selection processor, the locator can't be resolved so // we turn off the level that we were attempting to resolve attachmentLevel &= ~attemptedLevel; } } else { selection = data.AttachedAnchor; } } else { // ContentLocator didn't fully resolve so we turn off the level // that we were attempting to resolve attachmentLevel &= ~attemptedLevel; } return data; }
/// <summary> /// Searches the element subtree for a node that maps to the /// passed in ContentLocatorBase. /// Note: For LocatorGroups the startNode, offset, and prefixes /// are ignored. Due to the nature of LocatorGroups, we always /// start searching at the node with the service enabled, with /// the first locator part, ignoring all prefixes. /// </summary> /// <param name="startNode">the root of the subtree to search</param> /// <param name="prefixes">locators for the root of the subtree</param> /// <param name="locator">the ContentLocatorBase we are resolving to an anchor</param> /// <param name="attachmentLevel">type of the anchor returned</param> /// <returns>the anchor for the passed in ContentLocatorBase; will return null if no match can be found</returns> /// <exception cref="ArgumentNullException">startNode or locator is null</exception> internal Object FindAttachedAnchor(DependencyObject startNode, ContentLocator[] prefixes, ContentLocatorBase locator, out AttachmentLevel attachmentLevel) { if (startNode == null) throw new ArgumentNullException("startNode"); if (locator == null) throw new ArgumentNullException("locator"); // Set it to unresolved initially attachmentLevel = AttachmentLevel.Unresolved; Object anchor = null; bool matched = true; int locatorPartIdx = FindMatchingPrefix(prefixes, locator, out matched); // The annotation's locator starts with at least // one of the locators for the local root. if (matched) { ContentLocator realLocator = locator as ContentLocator; if (realLocator == null || locatorPartIdx < realLocator.Parts.Count) { // Now we try to resolve. If any locator parts were matched to the startNode we want to // start resolving with its children, skipping a revisit to the startNode. anchor = InternalResolveLocator(locator, locatorPartIdx, startNode, locatorPartIdx != 0 /*skipStartNode*/, out attachmentLevel); } // If nothing was returned, we base our return values on the results // of matching against the local root. if (attachmentLevel == AttachmentLevel.Unresolved && locatorPartIdx > 0) { if (locatorPartIdx == 0) { attachmentLevel = AttachmentLevel.Unresolved; } // If there was anything left to resolve then its incomplete // else if (realLocator != null && locatorPartIdx < realLocator.Parts.Count) { attachmentLevel = AttachmentLevel.Incomplete; anchor = startNode; } // otherwise its fully resolved else { attachmentLevel = AttachmentLevel.Full; anchor = startNode; } } } return anchor; }
/// <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);
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors /// <summary> /// Create an instance of AttachedAnnotation. /// </summary> /// <param name="manager">the LocatorManager providing processors for this anchored annotation</param> /// <param name="annotation">the annotation itself</param> /// <param name="anchor">the annotation's anchor represented by the attached anchor</param> /// <param name="attachedAnchor">the attached anchor itself</param> /// <param name="attachmentLevel">the level of the attached anchor</param> internal AttachedAnnotation(LocatorManager manager, Annotation annotation, AnnotationResource anchor, Object attachedAnchor, AttachmentLevel attachmentLevel) : this(manager, annotation, anchor, attachedAnchor, attachmentLevel, null) { }
/// <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; }
// Token: 0x06007C10 RID: 31760 RVA: 0x0022E31C File Offset: 0x0022C51C private object InternalResolveLocator(ContentLocatorBase locator, int offset, DependencyObject startNode, bool skipStartNode, out AttachmentLevel attachmentLevel) { attachmentLevel = AttachmentLevel.Full; object result = null; ContentLocatorGroup contentLocatorGroup = locator as ContentLocatorGroup; ContentLocator contentLocator = locator as ContentLocator; AttachmentLevel attachmentLevel2 = AttachmentLevel.Unresolved; if (contentLocator != null && offset == contentLocator.Parts.Count - 1) { ContentLocatorPart locatorPart = contentLocator.Parts[offset]; SelectionProcessor selectionProcessorForLocatorPart = this.GetSelectionProcessorForLocatorPart(locatorPart); if (selectionProcessorForLocatorPart != null) { result = selectionProcessorForLocatorPart.ResolveLocatorPart(locatorPart, startNode, out attachmentLevel2); attachmentLevel = attachmentLevel2; return(result); } } IList <ContentLocator> list; if (contentLocatorGroup == null) { list = new List <ContentLocator>(1); list.Add(contentLocator); } else { AnnotationService service = AnnotationService.GetService(startNode); if (service != null) { startNode = service.Root; } list = contentLocatorGroup.Locators; offset = 0; skipStartNode = false; } bool flag = true; if (list.Count > 0) { LocatorManager.ResolvingLocatorState resolvingLocatorState = this.ResolveSingleLocator(ref result, ref attachmentLevel, AttachmentLevel.StartPortion, list[0], offset, startNode, skipStartNode); if (list.Count == 1) { result = resolvingLocatorState.AttachedAnchor; attachmentLevel = resolvingLocatorState.AttachmentLevel; } else { if (list.Count > 2) { AttachmentLevel attachmentLevel3 = AttachmentLevel.Unresolved; AttachmentLevel attachmentLevel4 = attachmentLevel; for (int i = 1; i < list.Count - 1; i++) { resolvingLocatorState = this.ResolveSingleLocator(ref result, ref attachmentLevel, AttachmentLevel.MiddlePortion, list[i], offset, startNode, skipStartNode); if (attachmentLevel3 == AttachmentLevel.Unresolved || (attachmentLevel & AttachmentLevel.MiddlePortion) != AttachmentLevel.Unresolved) { attachmentLevel3 = attachmentLevel; } attachmentLevel = attachmentLevel4; } attachmentLevel = attachmentLevel3; } else { flag = false; } resolvingLocatorState = this.ResolveSingleLocator(ref result, ref attachmentLevel, AttachmentLevel.EndPortion, list[list.Count - 1], offset, startNode, skipStartNode); if (!flag && attachmentLevel == AttachmentLevel.MiddlePortion) { attachmentLevel &= ~AttachmentLevel.MiddlePortion; } if (attachmentLevel == (AttachmentLevel.StartPortion | AttachmentLevel.EndPortion)) { attachmentLevel = AttachmentLevel.Full; } } } else { attachmentLevel = AttachmentLevel.Unresolved; } return(result); }
// Token: 0x06007C11 RID: 31761 RVA: 0x0022E4B0 File Offset: 0x0022C6B0 private LocatorManager.ResolvingLocatorState ResolveSingleLocator(ref object selection, ref AttachmentLevel attachmentLevel, AttachmentLevel attemptedLevel, ContentLocator locator, int offset, DependencyObject startNode, bool skipStartNode) { LocatorManager.ResolvingLocatorState resolvingLocatorState = new LocatorManager.ResolvingLocatorState(); resolvingLocatorState.LocatorPartIndex = offset; resolvingLocatorState.ContentLocatorBase = locator; PrePostDescendentsWalker <LocatorManager.ResolvingLocatorState> prePostDescendentsWalker = new PrePostDescendentsWalker <LocatorManager.ResolvingLocatorState>(TreeWalkPriority.VisualTree, new VisitedCallback <LocatorManager.ResolvingLocatorState>(this.ResolveLocatorPart), new VisitedCallback <LocatorManager.ResolvingLocatorState>(this.TerminateResolve), resolvingLocatorState); prePostDescendentsWalker.StartWalk(startNode, skipStartNode); if (resolvingLocatorState.AttachmentLevel == AttachmentLevel.Full && resolvingLocatorState.AttachedAnchor != null) { if (selection != null) { SelectionProcessor selectionProcessor = this.GetSelectionProcessor(selection.GetType()); if (selectionProcessor != null) { object obj; if (selectionProcessor.MergeSelections(selection, resolvingLocatorState.AttachedAnchor, out obj)) { selection = obj; } else { attachmentLevel &= ~attemptedLevel; } } else { attachmentLevel &= ~attemptedLevel; } } else { selection = resolvingLocatorState.AttachedAnchor; } } else { attachmentLevel &= ~attemptedLevel; } return(resolvingLocatorState); }
/// <summary> /// Set <see cref="AttributeAttachmentLevel"/> from string. If the string is not valid then <see cref="AttributeAttachmentLevel"/> is set to <see cref="AttachmentLevel.None"/> /// </summary> /// <param name="level"> /// The attachment level /// </param> public void SetAttachmentLevel(string level) { if (string.IsNullOrEmpty(level) || !Enum.TryParse(level, true, out this._attributeAttachmentLevel)) { this._attributeAttachmentLevel = AttachmentLevel.None; // redundant but specified for readability } }
/// <summary> /// Create an instance of AttachedAnnotation with a specified parent. Takes an optional /// parent for the attached annotation. This is useful when the parent is known before /// hand and not available through the normal means (such as in printing). /// </summary> /// <param name="manager">the LocatorManager providing processors for this anchored annotation</param> /// <param name="annotation">the annotation itself</param> /// <param name="anchor">the annotation's anchor represented by the attached anchor</param> /// <param name="attachedAnchor">the attached anchor itself</param> /// <param name="attachmentLevel">the level of the attached anchor</param> /// <param name="parent">parent of the selection</param> internal AttachedAnnotation(LocatorManager manager, Annotation annotation, AnnotationResource anchor, Object attachedAnchor, AttachmentLevel attachmentLevel, DependencyObject parent) { Debug.Assert(manager != null, "LocatorManager can not be null"); Debug.Assert(annotation != null, "Annotation can not be null"); Debug.Assert(anchor != null, "Anchor can not be null"); Debug.Assert(attachedAnchor != null, "AttachedAnchor can not be null"); _annotation = annotation; _anchor = anchor; _locatorManager = manager; Update(attachedAnchor, attachmentLevel, parent); }
// Token: 0x06007C46 RID: 31814 RVA: 0x0022F3A8 File Offset: 0x0022D5A8 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 (TextSelectionProcessor.CharacterRangeElementName != locatorPart.PartType) { throw new ArgumentException(SR.Get("IncorrectLocatorPartType", new object[] { locatorPart.PartType.Namespace + ":" + locatorPart.PartType.Name }), "locatorPart"); } int num = 0; int num2 = 0; string text = locatorPart.NameValuePairs["Count"]; if (text == null) { throw new ArgumentException(SR.Get("InvalidLocatorPart", new object[] { "Count" })); } int num3 = int.Parse(text, NumberFormatInfo.InvariantInfo); TextAnchor textAnchor = new TextAnchor(); attachmentLevel = AttachmentLevel.Unresolved; for (int i = 0; i < num3; i++) { TextSelectionProcessor.GetLocatorPartSegmentValues(locatorPart, i, out num, out num2); ITextPointer textPointer; ITextPointer textPointer2; if (!this.GetNodesStartAndEnd(startNode, out textPointer, out textPointer2)) { return(null); } int offsetToPosition = textPointer.GetOffsetToPosition(textPointer2); if (num > offsetToPosition) { return(null); } ITextPointer textPointer3 = textPointer.CreatePointer(num); ITextPointer textPointer4 = (offsetToPosition <= num2) ? textPointer2.CreatePointer() : textPointer.CreatePointer(num2); if (textPointer3.CompareTo(textPointer4) >= 0) { return(null); } textAnchor.AddTextSegment(textPointer3, textPointer4); } if (textAnchor.IsEmpty) { throw new ArgumentException(SR.Get("IncorrectAnchorLength"), "locatorPart"); } attachmentLevel = AttachmentLevel.Full; if (this._clamping) { ITextPointer start = textAnchor.Start; ITextPointer end = textAnchor.End; IServiceProvider serviceProvider; if (this._targetPage != null) { serviceProvider = this._targetPage; } else { FlowDocument node = start.TextContainer.Parent as FlowDocument; serviceProvider = (PathNode.GetParent(node) as IServiceProvider); } Invariant.Assert(serviceProvider != null, "No ServiceProvider found to get TextView from."); ITextView textView = serviceProvider.GetService(typeof(ITextView)) as ITextView; Invariant.Assert(textView != null, "Null TextView provided by ServiceProvider."); textAnchor = TextAnchor.TrimToIntersectionWith(textAnchor, textView.TextSegments); if (textAnchor == null) { attachmentLevel = AttachmentLevel.Unresolved; } else { if (textAnchor.Start.CompareTo(start) != 0) { attachmentLevel &= ~AttachmentLevel.StartPortion; } if (textAnchor.End.CompareTo(end) != 0) { attachmentLevel &= ~AttachmentLevel.EndPortion; } } } return(textAnchor); }
/// <summary> /// Service indicates attached annotation has changed. /// For now, take all annotation components maped from old attached annotation and map from new. /// Then iterate through annotation components to let them know. /// Note, this needs to change later. If modify is radical, existing component might not want it anymore, /// and new one might need to be found... /// </summary> /// <param name="attachedAnnotation">The modified attached annotation</param> /// <param name="previousAttachedAnchor">The previous attached anchor for the attached annotation</param> /// <param name="previousAttachmentLevel">The previous attachment level for the attached annotation</param> private void ModifyAttachedAnnotation(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { Debug.Assert(attachedAnnotation != null, "attachedAnnotation should not be null"); Debug.Assert(previousAttachedAnchor != null, "previousAttachedAnchor should not be null"); // if there was no component found for this attached annotation // then we treat the modify case as an add if (!_attachedAnnotations.ContainsKey(attachedAnnotation)) { // this is not necessarily a bug, it can be that the old attached annotation does not have an // associated annotation component. this.AddAttachedAnnotation(attachedAnnotation, true); return; } // we have a previous component for this attached annotation // we find the chooser for the new attached annotation // and ask it to choose a component // 1- if it returned null then we just remove the attached annotation // 2- if it returned a different component, then we treat it as a remove/add // 3- if it returned the same component then we call ModifyAttachedAnnotation on the component IAnnotationComponent newComponent = FindComponent(attachedAnnotation); if (newComponent == null) { RemoveAttachedAnnotation(attachedAnnotation, true); } else { IList <IAnnotationComponent> currentList = _attachedAnnotations[attachedAnnotation]; //save the current list // if we found the new component in any of the list of components we already have for this // attached annotation if (currentList.Contains(newComponent)) { // ask the components to handle the anchor modification event foreach (IAnnotationComponent component in currentList) { component.ModifyAttachedAnnotation(attachedAnnotation, previousAttachedAnchor, previousAttachmentLevel); // let the annotation component know if (component.AttachedAnnotations.Count == 0) { // if component decides it can not handle it, remove it component.PresentationContext.RemoveFromHost(component, true); } } } else { // remove all components RemoveAttachedAnnotation(attachedAnnotation, true); // add the new component AddComponent(attachedAnnotation, newComponent, true); } } }
/// <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(nameof(startNode)); if (locatorPart == null) throw new ArgumentNullException(nameof(locatorPart)); attachmentLevel = AttachmentLevel.Full; return startNode; }
/// <summary> /// Service indicates attached annotation has changed. /// For now, take all annotation components maped from old attached annotation and map from new. /// Then iterate through annotation components to let them know. /// Note, this needs to change later. If modify is radical, existing component might not want it anymore, /// and new one might need to be found... /// </summary> /// <param name="attachedAnnotation">The modified attached annotation</param> /// <param name="previousAttachedAnchor">The previous attached anchor for the attached annotation</param> /// <param name="previousAttachmentLevel">The previous attachment level for the attached annotation</param> private void ModifyAttachedAnnotation(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { Debug.Assert(attachedAnnotation != null, "attachedAnnotation should not be null"); Debug.Assert(previousAttachedAnchor != null, "previousAttachedAnchor should not be null"); // if there was no component found for this attached annotation // then we treat the modify case as an add if (!_attachedAnnotations.ContainsKey(attachedAnnotation)) { // this is not necessarily a bug, it can be that the old attached annotation does not have an // associated annotation component. this.AddAttachedAnnotation(attachedAnnotation, true); return; } // we have a previous component for this attached annotation // we find the chooser for the new attached annotation // and ask it to choose a component // 1- if it returned null then we just remove the attached annotation // 2- if it returned a different component, then we treat it as a remove/add // 3- if it returned the same component then we call ModifyAttachedAnnotation on the component IAnnotationComponent newComponent = FindComponent(attachedAnnotation); if (newComponent == null) { RemoveAttachedAnnotation(attachedAnnotation, true); } else { IList<IAnnotationComponent> currentList = _attachedAnnotations[attachedAnnotation]; //save the current list // if we found the new component in any of the list of components we already have for this // attached annotation if (currentList.Contains(newComponent)) { // ask the components to handle the anchor modification event foreach (IAnnotationComponent component in currentList) { component.ModifyAttachedAnnotation(attachedAnnotation, previousAttachedAnchor, previousAttachmentLevel); // let the annotation component know if (component.AttachedAnnotations.Count == 0) { // if component decides it can not handle it, remove it component.PresentationContext.RemoveFromHost(component, true); } } } else { // remove all components RemoveAttachedAnnotation(attachedAnnotation, true); // add the new component AddComponent(attachedAnnotation, newComponent, true); } } }
// Token: 0x06007C0A RID: 31754 RVA: 0x0022DEF4 File Offset: 0x0022C0F4 internal object FindAttachedAnchor(DependencyObject startNode, ContentLocator[] prefixes, ContentLocatorBase locator, out AttachmentLevel attachmentLevel) { if (startNode == null) { throw new ArgumentNullException("startNode"); } if (locator == null) { throw new ArgumentNullException("locator"); } attachmentLevel = AttachmentLevel.Unresolved; object result = null; bool flag = true; int num = this.FindMatchingPrefix(prefixes, locator, out flag); if (flag) { ContentLocator contentLocator = locator as ContentLocator; if (contentLocator == null || num < contentLocator.Parts.Count) { result = this.InternalResolveLocator(locator, num, startNode, num != 0, out attachmentLevel); } if (attachmentLevel == AttachmentLevel.Unresolved && num > 0) { if (num == 0) { attachmentLevel = AttachmentLevel.Unresolved; } else if (contentLocator != null && num < contentLocator.Parts.Count) { attachmentLevel = AttachmentLevel.Incomplete; result = startNode; } else { attachmentLevel = AttachmentLevel.Full; result = startNode; } } } return(result); }
// Token: 0x06007C8E RID: 31886 RVA: 0x002306D0 File Offset: 0x0022E8D0 private void ModifyAttachedAnnotation(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { if (!this._attachedAnnotations.ContainsKey(attachedAnnotation)) { this.AddAttachedAnnotation(attachedAnnotation, true); return; } IAnnotationComponent annotationComponent = this.FindComponent(attachedAnnotation); if (annotationComponent == null) { this.RemoveAttachedAnnotation(attachedAnnotation, true); return; } IList <IAnnotationComponent> list = this._attachedAnnotations[attachedAnnotation]; if (list.Contains(annotationComponent)) { using (IEnumerator <IAnnotationComponent> enumerator = list.GetEnumerator()) { while (enumerator.MoveNext()) { IAnnotationComponent annotationComponent2 = enumerator.Current; annotationComponent2.ModifyAttachedAnnotation(attachedAnnotation, previousAttachedAnchor, previousAttachmentLevel); if (annotationComponent2.AttachedAnnotations.Count == 0) { annotationComponent2.PresentationContext.RemoveFromHost(annotationComponent2, true); } } return; } } this.RemoveAttachedAnnotation(attachedAnnotation, true); this.AddComponent(attachedAnnotation, annotationComponent, true); }
// Token: 0x06007CBB RID: 31931 RVA: 0x001279B5 File Offset: 0x00125BB5 public void ModifyAttachedAnnotation(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { throw new NotSupportedException(SR.Get("NotSupported")); }
/// <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; }
// Token: 0x06007BDE RID: 31710 RVA: 0x0022D33B File Offset: 0x0022B53B internal AttachedAnnotation(LocatorManager manager, Annotation annotation, AnnotationResource anchor, object attachedAnchor, AttachmentLevel attachmentLevel) : this(manager, annotation, anchor, attachedAnchor, attachmentLevel, null) { }
/// <summary> /// Asks the LocatorManager to find the attached anchor for a certain anchor /// </summary> /// <param name="anchor">the anchor to be resolved</param> /// <param name="attachmentLevel">the attachment level of the resulting attached anchor</param> /// <returns></returns> private object FindAttachedAnchor(AnnotationResource anchor, out AttachmentLevel attachmentLevel) { Invariant.Assert(anchor != null, "Parameter 'anchor' is null."); attachmentLevel = AttachmentLevel.Unresolved; Object attachedAnchor = null; foreach (ContentLocatorBase locator in anchor.ContentLocators) { attachedAnchor = LocatorManager.FindAttachedAnchor(_root, null, locator, out attachmentLevel); if (attachedAnchor != null) break; } return attachedAnchor; }
// Token: 0x06007BDF RID: 31711 RVA: 0x0022D34B File Offset: 0x0022B54B internal AttachedAnnotation(LocatorManager manager, Annotation annotation, AnnotationResource anchor, object attachedAnchor, AttachmentLevel attachmentLevel, DependencyObject parent) { this._annotation = annotation; this._anchor = anchor; this._locatorManager = manager; this.Update(attachedAnchor, attachmentLevel, parent); }
// Token: 0x06007BD3 RID: 31699 RVA: 0x0022CD00 File Offset: 0x0022AF00 public override object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel) { if (startNode == null) { throw new ArgumentNullException("startNode"); } DocumentPage documentPage = null; FixedPage fixedPage = startNode as FixedPage; if (fixedPage != null) { documentPage = this.GetDocumentPage(fixedPage); } else { DocumentPageView documentPageView = startNode as DocumentPageView; if (documentPageView != null) { documentPage = (documentPageView.DocumentPage as FixedDocumentPage); if (documentPage == null) { documentPage = (documentPageView.DocumentPage as FixedDocumentSequenceDocumentPage); } } } if (documentPage == null) { throw new ArgumentException(SR.Get("StartNodeMustBeDocumentPageViewOrFixedPage"), "startNode"); } if (locatorPart == null) { throw new ArgumentNullException("locatorPart"); } attachmentLevel = AttachmentLevel.Unresolved; ITextView textView = (ITextView)((IServiceProvider)documentPage).GetService(typeof(ITextView)); ReadOnlyCollection <TextSegment> textSegments = textView.TextSegments; if (textSegments == null || textSegments.Count <= 0) { return(null); } TextAnchor textAnchor = new TextAnchor(); if (documentPage != null) { string text = locatorPart.NameValuePairs["Count"]; if (text == null) { throw new ArgumentException(SR.Get("InvalidLocatorPart", new object[] { "Count" })); } int num = int.Parse(text, NumberFormatInfo.InvariantInfo); for (int i = 0; i < num; i++) { Point point; Point point2; this.GetLocatorPartSegmentValues(locatorPart, i, out point, out point2); ITextPointer textPointer; if (double.IsNaN(point.X) || double.IsNaN(point.Y)) { textPointer = FixedTextSelectionProcessor.FindStartVisibleTextPointer(documentPage); } else { textPointer = textView.GetTextPositionFromPoint(point, true); } if (textPointer != null) { ITextPointer textPointer2; if (double.IsNaN(point2.X) || double.IsNaN(point2.Y)) { textPointer2 = FixedTextSelectionProcessor.FindEndVisibleTextPointer(documentPage); } else { textPointer2 = textView.GetTextPositionFromPoint(point2, true); } Invariant.Assert(textPointer2 != null, "end TP is null when start TP is not"); attachmentLevel = AttachmentLevel.Full; textAnchor.AddTextSegment(textPointer, textPointer2); } } } if (textAnchor.TextSegments.Count > 0) { return(textAnchor); } return(null); }
/// <summary> /// Initializes a new instance of the <see cref="GesmesAttributeGroup"/> class. /// </summary> /// <param name="map"> /// The map. /// </param> /// <param name="level"> /// The attachment level /// </param> public GesmesAttributeGroup(GesmesKeyMap map, RelStatus level) { this._map = map; switch (level) { case RelStatus.None: throw new ArgumentException(Resources.ErrorInvalidAttachmentLevel, "level"); case RelStatus.DataSet: // no dimension this._dimensionValues = new string[0]; this._level = AttachmentLevel.DataSet; break; case RelStatus.Sibling: // all dimensions. FREQ is wildcarded this._dimensionValues = new string[map.Count]; this._dimensionValues[0] = string.Empty; this._firstDimension = 1; this._level = AttachmentLevel.Group; break; case RelStatus.Series: // all dimensions this._dimensionValues = new string[map.Count]; this._level = AttachmentLevel.Series; break; case RelStatus.Observation: // all dimensions plus time period and time format this._dimensionValues = new string[map.Count + 2]; this._timePeriodPosition = map.Count; this._timeFormatPosition = this._timePeriodPosition + 1; this._level = AttachmentLevel.Observation; break; } }
/// <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> /// 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); }
// Token: 0x06007C56 RID: 31830 RVA: 0x0022F999 File Offset: 0x0022DB99 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; return(null); }
/// <summary> /// factory method to create an AttachedAnnotationChangedEventArgs for the action modified /// </summary> /// <param name="attachedAnnotation">the IAttachedAnnotation associated with the event</param> /// <param name="previousAttachedAnchor">the previous attached anchor for the attached annotation</param> /// <param name="previousAttachmentLevel">the previous attachment level for the attached annotation</param> /// <returns>the constructed AttachedAnnotationChangedEventArgs</returns> internal static AttachedAnnotationChangedEventArgs Modified(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { Invariant.Assert(attachedAnnotation != null && previousAttachedAnchor != null); return(new AttachedAnnotationChangedEventArgs(AttachedAnnotationAction.AnchorModified, attachedAnnotation, previousAttachedAnchor, previousAttachmentLevel)); }
/// <summary> /// Modify an attached annotation that is held by the component /// </summary> /// <param name="attachedAnnotation">The attached annotation after modification</param> /// <param name="previousAttachedAnchor">The attached anchor previously associated with the attached annotation.</param> /// <param name="previousAttachmentLevel">The previous attachment level of the attached annotation.</param> public void ModifyAttachedAnnotation(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { throw new NotSupportedException(SR.Get(SRID.NotSupported)); }
/// <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> /// 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; }
//------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// Update the attached anchor and level for this attached annotation. Internal method called by /// the annotation service when a change to an anchor is processed. Optional parent will be used /// if present. Otherwise we get the parent from the selection processor. /// </summary> /// <param name="attachedAnchor">the new attached anchor</param> /// <param name="attachmentLevel">the new attachment level</param> /// <param name="parent">optional, the parent of the attached annotation</param> internal void Update(object attachedAnchor, AttachmentLevel attachmentLevel, DependencyObject parent) { Debug.Assert(attachedAnchor != null, "AttachedAnchor can not be null"); Debug.Assert(attachmentLevel > AttachmentLevel.Unresolved && attachmentLevel <= AttachmentLevel.Incomplete, "Undefined attachment level"); _attachedAnchor = attachedAnchor; _attachmentLevel = attachmentLevel; _selectionProcessor = _locatorManager.GetSelectionProcessor(attachedAnchor.GetType()); // Use optional parent if available if (parent != null) { _parent = parent; } else { _parent = _selectionProcessor.GetParent(_attachedAnchor); } Debug.Assert(_selectionProcessor != null, SR.Get(SRID.NoProcessorForSelectionType, attachedAnchor.GetType())); }
/// <summary> /// factory method to create an AttachedAnnotationChangedEventArgs for the action modified /// </summary> /// <param name="attachedAnnotation">the IAttachedAnnotation associated with the event</param> /// <param name="previousAttachedAnchor">the previous attached anchor for the attached annotation</param> /// <param name="previousAttachmentLevel">the previous attachment level for the attached annotation</param> /// <returns>the constructed AttachedAnnotationChangedEventArgs</returns> internal static AttachedAnnotationChangedEventArgs Modified(IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { Invariant.Assert(attachedAnnotation != null && previousAttachedAnchor != null); return new AttachedAnnotationChangedEventArgs(AttachedAnnotationAction.AnchorModified, attachedAnnotation, previousAttachedAnchor, previousAttachmentLevel); }
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ #region Constructors /// <summary> /// internal constructor that creates an AttachedAnnotationChangedEventArgs /// </summary> /// <param name="action">action represented by this instance</param> /// <param name="attachedAnnotation">annotation that was added/deleted/modified</param> /// <param name="previousAttachedAnchor">if action is modified, previous attached anchor</param> /// <param name="previousAttachmentLevel">if action is modified, previous attachment level</param> internal AttachedAnnotationChangedEventArgs(AttachedAnnotationAction action, IAttachedAnnotation attachedAnnotation, object previousAttachedAnchor, AttachmentLevel previousAttachmentLevel) { Invariant.Assert(attachedAnnotation != null); _action = action; _attachedAnnotation = attachedAnnotation; _previousAttachedAnchor = previousAttachedAnchor; _previousAttachmentLevel = previousAttachmentLevel; }
// Token: 0x06007C28 RID: 31784 public abstract object ResolveLocatorPart(ContentLocatorPart locatorPart, DependencyObject startNode, out AttachmentLevel attachmentLevel);
/// <summary> /// Produces an anchor spanning the content specified by 'locator'. /// This method traverses the tree and, using the registered /// processors, resolves the locator in the current element tree. /// </summary> /// <param name="locator">the locator to be resolved</param> /// <param name="offset">the index of the locator part to begin resolution with, ignored for /// LocatorGroups which always start with the first locator part</param> /// <param name="startNode">the tree node to start the resolution from</param> /// <param name="attachmentLevel">type of the returned anchor</param> /// <returns>an anchor that spans the content specified by locator; may return /// null if the locator could not be resolved (in which case type is set to /// AttachmentLevel.Unresolved</returns> /// <exception cref="ArgumentNullException">locator or startNode are null</exception> /// <exception cref="ArgumentException">offset is negative or greater than /// locator.Count - 1</exception> public Object ResolveLocator(ContentLocatorBase locator, int offset, DependencyObject startNode, out AttachmentLevel attachmentLevel) { VerifyAccess(); if (locator == null) throw new ArgumentNullException("locator"); if (startNode == null) throw new ArgumentNullException("startNode"); // Offset need only be checked for Locators ContentLocator realLocator = locator as ContentLocator; if (realLocator != null) { if (offset < 0 || offset >= realLocator.Parts.Count) throw new ArgumentOutOfRangeException("offset"); } return InternalResolveLocator(locator, offset, startNode, false /*skipStartNode*/, out 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); }
/// <summary> /// Resolves a locator starting on a specified locator part with a specified tree node. /// The tree node can optionally be skipped (if some previous locator part has already /// matched it) in which case the resolution starts with its children. /// </summary> /// <param name="locator">the locator to resolve</param> /// <param name="offset">the index of the first locator part to resolve</param> /// <param name="startNode">the node to start the resolution at</param> /// <param name="skipStartNode">specifies whether to start with the startNode or its children</param> /// <param name="attachmentLevel">return value specifying how successful the resolution was</param> /// <returns>the attached anchor the locator was resolved to</returns> /// <exception cref="InvalidOperationException">if a locator set is resolved and the individual selections /// can't be merged</exception> private Object InternalResolveLocator(ContentLocatorBase locator, int offset, DependencyObject startNode, bool skipStartNode, out AttachmentLevel attachmentLevel) { Debug.Assert(locator != null, "locator can not be null"); Debug.Assert(startNode != null, "startNode can not be null"); // Set it to unresolved initially attachmentLevel = AttachmentLevel.Full; Object selection = null; ContentLocatorGroup locatorGroup = locator as ContentLocatorGroup; ContentLocator realLocator = locator as ContentLocator; AttachmentLevel individualAttachmentLevel = AttachmentLevel.Unresolved; // If only one locator part left, it might represent a selection so we take // care of that case before trying to resolve the locator part if (realLocator != null && offset == realLocator.Parts.Count - 1) { ContentLocatorPart locatorPart = realLocator.Parts[offset]; SelectionProcessor selProcessor = GetSelectionProcessorForLocatorPart(locatorPart); if (selProcessor != null) { selection = selProcessor.ResolveLocatorPart(locatorPart, startNode, out individualAttachmentLevel); attachmentLevel = individualAttachmentLevel; // No node has actually been matched in this case so we // return the default Unresolved (set at top of method). // Its up to the caller to know if the node and // index passed in represented an incomplete resolution. return selection; } } IList<ContentLocator> locators = null; // Setup the locators and other inputs before the loop. Normal locators // are put in an array of locators (with one element). LocatorGroups have // their Locators collection used. if (locatorGroup == null) { Debug.Assert(offset >= 0 && offset < realLocator.Parts.Count, "offset out of range"); locators = new List <ContentLocator> (1); locators.Add(realLocator); } else { // If there is a service, start at its root. AnnotationService svc = AnnotationService.GetService(startNode); if (svc != null) { startNode = svc.Root; } locators = locatorGroup.Locators; // Always start resolving locator groups from the beginning // and use the node the service is enabled on to start offset = 0; skipStartNode = false; } bool middlePortionExists = true; if (locators.Count > 0) { // Otherwise we need to resolve each of the locators in the locator set // and then try to merge the anchors that are returned ResolvingLocatorState data = ResolveSingleLocator(ref selection, ref attachmentLevel, AttachmentLevel.StartPortion, locators[0], offset, startNode, skipStartNode); // Special case - when there is only one locator we simply use the anchor and level // returned from resolving that single locator if (locators.Count == 1) { selection = data.AttachedAnchor; attachmentLevel = data.AttachmentLevel; } else { // Resolve all locators after the first and before the last if (locators.Count > 2) { AttachmentLevel tempLevel = AttachmentLevel.Unresolved; AttachmentLevel savedLevel = attachmentLevel; for (int i = 1; i < locators.Count - 1; i++) { data = ResolveSingleLocator(ref selection, ref attachmentLevel, AttachmentLevel.MiddlePortion, locators[i], offset, startNode, skipStartNode); //if there are >1 middle locators some of them might be resolved, some other - not //if even one middle locator is resolved we should save its attachmenLevel if ((tempLevel == AttachmentLevel.Unresolved) || ((attachmentLevel & AttachmentLevel.MiddlePortion) != 0)) tempLevel = attachmentLevel; attachmentLevel = savedLevel; } attachmentLevel = tempLevel; } else { // We make note that there were no middle portion locators middlePortionExists = false; } // Process the last locator data = ResolveSingleLocator(ref selection, ref attachmentLevel, AttachmentLevel.EndPortion, locators[locators.Count - 1], offset, startNode, skipStartNode); // If no locators exists for the middle portion we need to make // sure its not the only portion left on. if (!middlePortionExists && attachmentLevel == AttachmentLevel.MiddlePortion) { attachmentLevel &= ~AttachmentLevel.MiddlePortion; } //if start and end is resolved we consider this as fully resolved //this will handle the case of empty middle page in fixed if (attachmentLevel == (AttachmentLevel.StartPortion | AttachmentLevel.EndPortion)) attachmentLevel = AttachmentLevel.Full; } } else { // There are no locators to resolve attachmentLevel = AttachmentLevel.Unresolved; } return selection; }
// Token: 0x06007C06 RID: 31750 RVA: 0x0022DE04 File Offset: 0x0022C004 public object ResolveLocator(ContentLocatorBase locator, int offset, DependencyObject startNode, out AttachmentLevel attachmentLevel) { base.VerifyAccess(); if (locator == null) { throw new ArgumentNullException("locator"); } if (startNode == null) { throw new ArgumentNullException("startNode"); } ContentLocator contentLocator = locator as ContentLocator; if (contentLocator != null && (offset < 0 || offset >= contentLocator.Parts.Count)) { throw new ArgumentOutOfRangeException("offset"); } return(this.InternalResolveLocator(locator, offset, startNode, false, out attachmentLevel)); }