| File: MS\Internal\Annotations\Component\AnnotationAdorner.cs | Web Access |
| Project: src\wpf\src\Microsoft.DotNet.Wpf\src\PresentationFramework\PresentationFramework.csproj (PresentationFramework) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // // Description: // AnnotationAdorner wraps an IAnnotationComponent. Its the bridge // between the component and the adorner layer. // using System.Windows; using System.Windows.Documents; using System.Windows.Media; namespace MS.Internal.Annotations.Component { /// <summary> /// An adorner which wraps one IAnnotationComponent. The wrapped component must be at least a UIElement. /// Adorners are UIElements. /// Note:-This class is sealed because it calls OnVisualChildrenChanged virtual in the /// constructor and it does not override it, but derived classes could. /// </summary> internal sealed class AnnotationAdorner : Adorner { #region Constructors /// <summary> /// Return an initialized annotation adorner /// </summary> /// <param name="component">The annotation component to wrap in the annotation adorner</param> /// <param name="annotatedElement">element being annotated</param> public AnnotationAdorner(IAnnotationComponent component, UIElement annotatedElement) : base(annotatedElement) { //The summary on top of the file says:- //The wrapped component must be at least a UIElement if (component is UIElement) { _annotationComponent = component; // wrapped annotation component is added as visual child this.AddVisualChild((UIElement)_annotationComponent); } else { throw new ArgumentException(SR.AnnotationAdorner_NotUIElement, nameof(component)); } } #endregion Constructors #region Public Methods /// <summary> /// Forwarded to the annotation component to get desired transform relative to the annotated element /// </summary> /// <param name="transform">Transform to adorned element</param> /// <returns>Transform to annotation component </returns> public override GeneralTransform GetDesiredTransform(GeneralTransform transform) { //if the component is not visual we do not need this if (!(_annotationComponent is UIElement)) return null; // Give the superclass a chance to modify the transform transform = base.GetDesiredTransform(transform); GeneralTransform compTransform = _annotationComponent.GetDesiredTransform(transform); // if the annotated element is null this component must be unloaded. //Temporary return null until the PageViewer Load/Unload bug is fixed //Convert it to an exception after that. if (_annotationComponent.AnnotatedElement == null) return null; if (compTransform == null) { // We need to store the element we are registering on. It may not // be available from the annotation component later. _annotatedElement = _annotationComponent.AnnotatedElement; // Wait for valid text view _annotatedElement.LayoutUpdated += OnLayoutUpdated; return transform; } return compTransform; } #endregion Public Methods #region Protected Methods /// <summary> /// Derived class must implement to support Visual children. The method must return /// the child at the specified index. Index must be between 0 and GetVisualChildrenCount-1. /// /// By default a Visual does not have any children. /// /// Remark: /// During this virtual call it is not valid to modify the Visual tree. /// </summary> protected override Visual GetVisualChild(int index) { if (index != 0 || _annotationComponent == null) { throw new ArgumentOutOfRangeException(nameof(index), index, SR.Visual_ArgumentOutOfRange); } return (UIElement)_annotationComponent; } /// <summary> /// Derived classes override this property to enable the Visual code to enumerate /// the Visual children. Derived classes need to return the number of children /// from this method. /// /// By default a Visual does not have any children. /// /// Remark: During this virtual method the Visual tree must not be modified. /// </summary> protected override int VisualChildrenCount { get { return _annotationComponent != null ? 1 : 0; } } /// <summary> /// Measurement override. Delegated to children. /// </summary> /// <param name="availableSize">Available size for the component</param> /// <returns>Return the size enclosing all children</returns> protected override Size MeasureOverride(Size availableSize) { Size childConstraint = new Size(Double.PositiveInfinity, Double.PositiveInfinity); Invariant.Assert(_annotationComponent != null, "AnnotationAdorner should only have one child - the annotation component."); ((UIElement)_annotationComponent).Measure(childConstraint); return new Size(0, 0); } /// <summary> /// Override for <seealso cref="FrameworkElement.ArrangeOverride" /> /// </summary> /// <param name="finalSize">The location reserved for this element by the parent</param> protected override Size ArrangeOverride(Size finalSize) { Invariant.Assert(_annotationComponent != null, "AnnotationAdorner should only have one child - the annotation component."); ((UIElement)_annotationComponent).Arrange(new Rect(((UIElement)_annotationComponent).DesiredSize)); return finalSize; } #endregion ProtectedMethods #region Internal Methods /// <summary> /// Remove all visual children of this AnnotationAdorner. /// Called by AdornerPresentationContext when an annotation adorner is removed from the adorner layer hosting it. /// </summary> internal void RemoveChildren() { this.RemoveVisualChild((UIElement)_annotationComponent); _annotationComponent = null; } /// <summary> /// Call this if the visual of the annotation changes. /// This ill invalidate the AnnotationAdorner and the AdornerLayer which /// will invoke remeasuring of the annotation visual. /// </summary> internal void InvalidateTransform() { AdornerLayer adornerLayer = (AdornerLayer)VisualTreeHelper.GetParent(this); InvalidateMeasure(); adornerLayer.InvalidateVisual(); } #endregion Internal Methods #region Internal Properties /// <summary> /// Return the annotation component that is being wrapped. AdornerPresentationContext needs this. /// </summary> /// <value>Wrapped annotation component</value> internal IAnnotationComponent AnnotationComponent { get { return _annotationComponent; } } #endregion Internal Properties #region Private Methods /// <summary> /// LayoutUpdate event handler /// </summary> /// <param name="sender">event sender (not used)</param> /// <param name="args">event arguments (not used)</param> private void OnLayoutUpdated(object sender, EventArgs args) { // Unregister for the event _annotatedElement.LayoutUpdated -= OnLayoutUpdated; _annotatedElement = null; // If there are still annotations to display, update the UI if (_annotationComponent.AttachedAnnotations.Count > 0) { _annotationComponent.PresentationContext.Host.InvalidateMeasure(); this.InvalidateMeasure(); } } #endregion Private Methods #region Private Fields /// <summary> /// The wrapped annotation component /// </summary> private IAnnotationComponent _annotationComponent; /// <summary> /// Used to unregister for the LayoutUpdated event - necessary because in the /// the component may have its annotated element cleared before we can unregister. /// </summary> private UIElement _annotatedElement; #endregion Private Fields } }