Code:
/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / wpf / src / Framework / MS / Internal / Annotations / Component / AdornerPresentationContext.cs / 1305600 / AdornerPresentationContext.cs
//---------------------------------------------------------------------------- //// Copyright(C) Microsoft Corporation. All rights reserved. // // // Description: // AdornerPresentationContext knows that annotation comonents are wrapped // in an AnnotationAdorner and hosted in the AdornerLayer. Note, implementation-wise // a new PresentationContext is created for every annotation component. Executing // operations on a presentation context for a different annotation component // (located in the same adorner layer) works, but is slower than using the // presentation context stored in the annotation component. // // History: // 04/01/2004: axelk: Created AdornerPresentationContext.cs // 10/20/2004: rruiz: Moved class to MS.Internal. // // Copyright(C) 2002 by Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Annotations; using System.Windows.Documents; using System.Windows.Media; using System.Collections; namespace MS.Internal.Annotations.Component { ////// AdornerPresentationContext knows that annotation comonents are wrapped in an AnnotationAdorner and hosted in the AdornerLayer. /// Note, implementation-wise a new PresentationContext is created for every annotation component. Executing operations on a presentation context /// for a different annotation component (located in the same adorner layer) works, but is slower than using the presentation context stored in the /// annotation component. /// internal class AdornerPresentationContext : PresentationContext { #region Constructors ////// Create an initialized instance of an AdornerPresentationContext. Set the presentation context of the /// component wrapped in the adorner /// /// AdornerLayer this presentation context is on, must not be null /// AnnotationAdorner that wraps the annotation component. Will be null in case of creating enclosing context private AdornerPresentationContext(AdornerLayer adornerLayer, AnnotationAdorner adorner) { if (adornerLayer == null) throw new ArgumentNullException("adornerLayer"); _adornerLayer = adornerLayer; if (adorner != null) { if (adorner.AnnotationComponent == null) throw new ArgumentNullException("annotation component"); if (adorner.AnnotationComponent.PresentationContext != null) throw new InvalidOperationException(SR.Get(SRID.ComponentAlreadyInPresentationContext, adorner.AnnotationComponent)); _annotationAdorner = adorner; } } #endregion Constructors #region Static Methods ////// Host a component in an adorner layer. /// Wrap the component in an annotation adorner, add that to the adorner layer, create and set presentation context and invalidate to pick up styles. /// Note, this is called from two places: (1) component manager to host choosen annotation component, and (2) presentation context when component /// adds additional IAnnotationComponent. /// /// Adorner layer the component is hosted in /// Component that is being hosted /// element being annotated /// if true - put the component on top and calculate its z-order internal static void HostComponent(AdornerLayer adornerLayer, IAnnotationComponent component, UIElement annotatedElement, bool reorder) { AnnotationAdorner newAdorner = new AnnotationAdorner(component, annotatedElement); // Create the context for the layer and adorner, make sure the adorner's component has its context. newAdorner.AnnotationComponent.PresentationContext = new AdornerPresentationContext(adornerLayer, newAdorner); int level = GetComponentLevel(component); if (reorder) { component.ZOrder = GetNextZOrder(adornerLayer, level); } adornerLayer.Add(newAdorner, ComponentToAdorner(component.ZOrder, level)); } ////// Sets the Z-order level of an annotation Component type /// /// the component type /// level - 0 means on top of all other types, bigger number means /// lower level ///ZLevel defines the Z-order disposition of this component type according to other /// component types in the same adorner layer. Components with lower ZLevel will be instantiated /// on top of the components with Higher ZLevel. /// The Z-order of all the components with the same ZLevel is defined by the value of /// IAnnotationComponent.ZOrder property with zero meaning the component is on top of all other /// inside the same level. ZOrder property can be changed by invoking /// BringToTop method. This will move the component to the top of its priority group. If there are other /// components with higher priority they will still be on top of that component. If more than /// one component type have the same ZLevel that means they all can stay on top of each other. /// Setting IAnnotationComponent.ZOrder must be invoked only by the PrezentationContext /// when the Z-order changes. It can not be set by application in v1. internal static void SetTypeZLevel(Type type, int level) { Invariant.Assert(level >= 0, "level is < 0"); Invariant.Assert(type != null, "type is null"); if (_ZLevel.ContainsKey(type)) { _ZLevel[type] = level; } else { _ZLevel.Add(type, level); } } ////// the allowed Z-order values range for this level. /// Used to define minimal Z-order value for types that are supposed to live above TextSelection /// which has a fixed Z-order value /// /// the Z-order level /// min Z-order value for this level /// max Z-order value for this level internal static void SetZLevelRange(int level, int min, int max) { if (_ZRanges[level] == null) { _ZRanges.Add(level, new ZRange(min, max)); } } #endregion Static Methods #region Public Properties ////// Returns the adorner layer which acts as a host for annotation components managed by the annotation component manager /// ///UIElement for the adorner layer public override UIElement Host { get { return _adornerLayer; } } ////// Get the enclosing presentation context. /// ///Enclosing PresentationContext or null if there is none public override PresentationContext EnclosingContext { get { Visual parent = VisualTreeHelper.GetParent(_adornerLayer) as Visual; if (parent == null) return null; AdornerLayer parentLayer = AdornerLayer.GetAdornerLayer((UIElement)parent); if (parentLayer == null) return null; PresentationContext p = new AdornerPresentationContext(parentLayer, null); return p; } } #endregion Public Properties #region Public Methods ////// Add the component to the adornerlayer of this presentation context. /// Create a new presentation context which includes the wrapped annotation adorner and the adornerlayer. /// Assign new presentation context into the component. /// /// Component to add to host public override void AddToHost(IAnnotationComponent component) { if (component == null) throw new ArgumentNullException("component"); AdornerPresentationContext.HostComponent(_adornerLayer, component, component.AnnotatedElement, false); } ////// Remove annotation component from host; in our case: respective annotation adorner from adornerLayer. /// If this presentation context does not contain the component search the adorner layer. /// Null out the presentation context of the component and set the local annotationAdorner to null if necessary, /// ask the annotation adorner to remove all visual children. /// /// Component to remove from host /// if true - recalculate z-order public override void RemoveFromHost(IAnnotationComponent component, bool reorder) { if (component == null) throw new ArgumentNullException("component"); if (IsInternalComponent(component)) { _annotationAdorner.AnnotationComponent.PresentationContext = null; _adornerLayer.Remove(_annotationAdorner); _annotationAdorner.RemoveChildren(); _annotationAdorner = null; } else {// need to find annotation adorner in layer, remove it and do house-keeping AnnotationAdorner foundAdorner = this.FindAnnotationAdorner(component); if (foundAdorner == null) throw new InvalidOperationException(SR.Get(SRID.ComponentNotInPresentationContext, component)); _adornerLayer.Remove(foundAdorner); foundAdorner.RemoveChildren(); // now get rid of reference from presentation context of annotation component to annotation adorner AdornerPresentationContext p = component.PresentationContext as AdornerPresentationContext; if (p != null) p.ResetInternalAnnotationAdorner(); // finally get rid of reference from annotation component to presentation context component.PresentationContext = null; } } ////// Invalidate the transform for this adorner. called when adorner inside changed aspects of the transform. /// This might go away if InvalidateMeasure works /// (unclear if Peter means this should work on the adorner or even one down on the annotation component itself) /// /// Component to invalidate transform for public override void InvalidateTransform(IAnnotationComponent component) { AnnotationAdorner adorner = GetAnnotationAdorner(component); adorner.InvalidateTransform(); } ////// Sets a component on top of its ZLevel /// /// Component to change z-order of public override void BringToFront(IAnnotationComponent component) { AnnotationAdorner adorner = GetAnnotationAdorner(component); int level = GetComponentLevel(component); int nextLevel = GetNextZOrder(_adornerLayer, level); // Only change the ZOrder if its not already on the top if (nextLevel != component.ZOrder + 1) { component.ZOrder = nextLevel; _adornerLayer.SetAdornerZOrder(adorner, ComponentToAdorner(component.ZOrder, level)); } } ////// Sets a component on bttom of its ZLevel /// /// Component to change z-order of public override void SendToBack(IAnnotationComponent component) { AnnotationAdorner adorner = GetAnnotationAdorner(component); int level = GetComponentLevel(component); // Only change the ZOrder if its not already on the bottom if (0 != component.ZOrder) { component.ZOrder = 0; UpdateComponentZOrder(component); } } ////// Determines if the passed in object is equal to this object. /// Two AdornerPresentationContexts will be equal if they both have the same adorner layer. /// /// The object to compare with. ///True if the objects are equal. False otherwise. public override bool Equals(object o) { AdornerPresentationContext p = o as AdornerPresentationContext; if (p != null) { return (p._adornerLayer == this._adornerLayer); } return false; } ////// overload operator for ==, to be same as Equal implementation. /// /// AdornerPresentationContext to compare /// AdornerPresentationContext to compare ///public static bool operator ==(AdornerPresentationContext left, AdornerPresentationContext right) { if ((object)left == null) return (object)right == null; return left.Equals(right); } /// /// overload operator for !=, to go along with definition for == /// /// AdornerPresentationContext to compare /// AdornerPresentationContext to compare ///public static bool operator !=(AdornerPresentationContext c1, AdornerPresentationContext c2) { return !(c1 == c2); } /// /// Delegate hash to adorner layer /// public override int GetHashCode() { return (int)this._adornerLayer.GetHashCode(); } ////// Updates the ZOrder of the input component and on all components with the same ZLevel /// that have same or bigger Z-order as the input component on a given adorner layer /// /// the component public void UpdateComponentZOrder(IAnnotationComponent component) { Invariant.Assert(component != null, "null component"); //check Z-order range for this level int level = GetComponentLevel(component); //get the component's adorner AnnotationAdorner adorner = FindAnnotationAdorner(component); if (adorner == null) return; //set the adorner z-order _adornerLayer.SetAdornerZOrder(adorner, ComponentToAdorner(component.ZOrder, level)); Listadorners = GetTopAnnotationAdorners(level, component); if (adorners == null) return; int lastZOrder = component.ZOrder + 1; foreach (AnnotationAdorner topAdorner in adorners) { topAdorner.AnnotationComponent.ZOrder = lastZOrder; _adornerLayer.SetAdornerZOrder(topAdorner, ComponentToAdorner(lastZOrder, level)); lastZOrder++; } } #endregion Public Methods #region Private Methods /// /// Reset the annotation adorner to null. This is needed for reset of found adorner in method RemoveFromHost /// private void ResetInternalAnnotationAdorner() { _annotationAdorner = null; } ////// Return true if the given annotation component is the one this presentation context is on. /// /// The component that might be referred to by this presentation context ///True if the component is internal private bool IsInternalComponent(IAnnotationComponent component) { return _annotationAdorner != null && component == _annotationAdorner.AnnotationComponent; } ////// Return the annotation adorner for the given annotation component. /// will not look at local annotation adorner, will always iterate through annotation adorners of adorner layer. /// Return null if none can be found. /// /// The component that is wrapped by an annotation adorner ///The annotation adorner that wraps the component in the adorner layer associated with this presentation context private AnnotationAdorner FindAnnotationAdorner(IAnnotationComponent component) { if (_adornerLayer == null) return null; foreach (Adorner adorner in _adornerLayer.GetAdorners(component.AnnotatedElement)) { AnnotationAdorner annotationAdorner = adorner as AnnotationAdorner; if (annotationAdorner != null && annotationAdorner.AnnotationComponent == component) return annotationAdorner; } return null; } ////// Finds all AnnotationAddorners from particular Z-level that have the same or bigger z-order as the component /// /// the ZLevel of interest /// the component ///the AnnotationAdorner children private ListGetTopAnnotationAdorners(int level, IAnnotationComponent component) { List res = new List (); int count = VisualTreeHelper.GetChildrenCount(_adornerLayer); if (count == 0) return res; for (int i = 0; i < count; i++) { DependencyObject child = VisualTreeHelper.GetChild(_adornerLayer, i); AnnotationAdorner adorner = child as AnnotationAdorner; if (adorner != null) { IAnnotationComponent childComponent = adorner.AnnotationComponent; if ((childComponent != component) && (GetComponentLevel(childComponent) == level) && (childComponent.ZOrder >= component.ZOrder)) { AddAdorner(res, adorner); } } } return res; } /// /// Inserts an adorner after the last adorner with ZOrder less or equal of the input one /// /// adorners list /// the new adorner ///In most cases the AnnotationAdorners are already orderd so we expect that the new one /// will be added at the end of the list. That is why we start scaning from the end. private void AddAdorner(Listadorners, AnnotationAdorner adorner) { Debug.Assert((adorners != null) && (adorner != null), "null adorners list or adorner"); int index = 0; if (adorners.Count > 0) { for (index = adorners.Count; index > 0; index--) { if (adorners[index-1].AnnotationComponent.ZOrder <= adorner.AnnotationComponent.ZOrder) break; } } adorners.Insert(index, adorner); } /// /// Gets the next free Z-order value for the components in this level /// /// adorner layer /// Z-level ///next free Z-order value private static int GetNextZOrder(AdornerLayer adornerLayer, int level) { Invariant.Assert(adornerLayer != null, "null adornerLayer"); int res = 0; int count = VisualTreeHelper.GetChildrenCount(adornerLayer); if (count == 0) return res; for ( int i = 0; i < count; i++) { DependencyObject child = VisualTreeHelper.GetChild(adornerLayer, i); AnnotationAdorner adorner = child as AnnotationAdorner; if (adorner != null) { if ((GetComponentLevel(adorner.AnnotationComponent) == level) && (adorner.AnnotationComponent.ZOrder >= res)) { res = adorner.AnnotationComponent.ZOrder + 1; } } } return res; } ////// Finds the correct AdornerLayer where a component lives /// /// the component ///private AnnotationAdorner GetAnnotationAdorner(IAnnotationComponent component) { if (component == null) throw new ArgumentNullException("component"); //find the adornerLayer AnnotationAdorner adorner = _annotationAdorner; if (!this.IsInternalComponent(component)) { adorner = this.FindAnnotationAdorner(component); if (adorner == null) throw new InvalidOperationException(SR.Get(SRID.ComponentNotInPresentationContext, component)); } return adorner; } /// /// Returns the component ZLevel /// /// component ///ZLevel private static int GetComponentLevel(IAnnotationComponent component) { int level = 0; Type type = component.GetType(); if (_ZLevel.ContainsKey(type)) level = (int)_ZLevel[type]; return level; } ////// Converts the component z-order to the Adorner z-order. The adorner z-order /// is shifted by the minimal value for this level. Also there is a restriction /// about the maximal possible value for this level too /// /// component z-order /// component z-level ///private static int ComponentToAdorner(int zOrder, int level) { int res = zOrder; ZRange range = (ZRange)_ZRanges[level]; if (range != null) { //adjust the Z-order (shift it with the minimal value for this range) //that way the component does need to know the range for its type that is // set by the application. It always sets the z-order as it starts from 0 res += range.Min; if (res < range.Min) res = range.Min; if (res > range.Max) res = range.Max; } return res; } #endregion Private Methods #region Private Fields /// /// The annotation adorner which wraps the annotation component this presentation context is optimized for. /// Can be null. /// private AnnotationAdorner _annotationAdorner = null; ////// The adornerLayer which contains the annotation component. Basically what the presentation hides. /// private AdornerLayer _adornerLayer; ////// The hashtable holds the priority level for each Component type as defined by the application /// private static Hashtable _ZLevel = new Hashtable(); ////// The ZRanges for the ZLevels. /// private static Hashtable _ZRanges = new Hashtable(); #endregion Private Fields #region Private classes ////// This is to control the relationships with TextSelection which lives in the same /// AdornerLayer. Will be removed when more flexible Z-ordering mechanism is available /// private class ZRange { public ZRange(int min, int max) { //exchange values if needed if (min > max) { int temp = min; min = max; max = temp; } _min = min; _max = max; } public int Min { get { return _min; } } public int Max { get { return _max; } } private int _min, _max; } #endregion Internal classes } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------------------- //// Copyright(C) Microsoft Corporation. All rights reserved. // // // Description: // AdornerPresentationContext knows that annotation comonents are wrapped // in an AnnotationAdorner and hosted in the AdornerLayer. Note, implementation-wise // a new PresentationContext is created for every annotation component. Executing // operations on a presentation context for a different annotation component // (located in the same adorner layer) works, but is slower than using the // presentation context stored in the annotation component. // // History: // 04/01/2004: axelk: Created AdornerPresentationContext.cs // 10/20/2004: rruiz: Moved class to MS.Internal. // // Copyright(C) 2002 by Microsoft Corporation. All rights reserved. //--------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Annotations; using System.Windows.Documents; using System.Windows.Media; using System.Collections; namespace MS.Internal.Annotations.Component { ////// AdornerPresentationContext knows that annotation comonents are wrapped in an AnnotationAdorner and hosted in the AdornerLayer. /// Note, implementation-wise a new PresentationContext is created for every annotation component. Executing operations on a presentation context /// for a different annotation component (located in the same adorner layer) works, but is slower than using the presentation context stored in the /// annotation component. /// internal class AdornerPresentationContext : PresentationContext { #region Constructors ////// Create an initialized instance of an AdornerPresentationContext. Set the presentation context of the /// component wrapped in the adorner /// /// AdornerLayer this presentation context is on, must not be null /// AnnotationAdorner that wraps the annotation component. Will be null in case of creating enclosing context private AdornerPresentationContext(AdornerLayer adornerLayer, AnnotationAdorner adorner) { if (adornerLayer == null) throw new ArgumentNullException("adornerLayer"); _adornerLayer = adornerLayer; if (adorner != null) { if (adorner.AnnotationComponent == null) throw new ArgumentNullException("annotation component"); if (adorner.AnnotationComponent.PresentationContext != null) throw new InvalidOperationException(SR.Get(SRID.ComponentAlreadyInPresentationContext, adorner.AnnotationComponent)); _annotationAdorner = adorner; } } #endregion Constructors #region Static Methods ////// Host a component in an adorner layer. /// Wrap the component in an annotation adorner, add that to the adorner layer, create and set presentation context and invalidate to pick up styles. /// Note, this is called from two places: (1) component manager to host choosen annotation component, and (2) presentation context when component /// adds additional IAnnotationComponent. /// /// Adorner layer the component is hosted in /// Component that is being hosted /// element being annotated /// if true - put the component on top and calculate its z-order internal static void HostComponent(AdornerLayer adornerLayer, IAnnotationComponent component, UIElement annotatedElement, bool reorder) { AnnotationAdorner newAdorner = new AnnotationAdorner(component, annotatedElement); // Create the context for the layer and adorner, make sure the adorner's component has its context. newAdorner.AnnotationComponent.PresentationContext = new AdornerPresentationContext(adornerLayer, newAdorner); int level = GetComponentLevel(component); if (reorder) { component.ZOrder = GetNextZOrder(adornerLayer, level); } adornerLayer.Add(newAdorner, ComponentToAdorner(component.ZOrder, level)); } ////// Sets the Z-order level of an annotation Component type /// /// the component type /// level - 0 means on top of all other types, bigger number means /// lower level ///ZLevel defines the Z-order disposition of this component type according to other /// component types in the same adorner layer. Components with lower ZLevel will be instantiated /// on top of the components with Higher ZLevel. /// The Z-order of all the components with the same ZLevel is defined by the value of /// IAnnotationComponent.ZOrder property with zero meaning the component is on top of all other /// inside the same level. ZOrder property can be changed by invoking /// BringToTop method. This will move the component to the top of its priority group. If there are other /// components with higher priority they will still be on top of that component. If more than /// one component type have the same ZLevel that means they all can stay on top of each other. /// Setting IAnnotationComponent.ZOrder must be invoked only by the PrezentationContext /// when the Z-order changes. It can not be set by application in v1. internal static void SetTypeZLevel(Type type, int level) { Invariant.Assert(level >= 0, "level is < 0"); Invariant.Assert(type != null, "type is null"); if (_ZLevel.ContainsKey(type)) { _ZLevel[type] = level; } else { _ZLevel.Add(type, level); } } ////// the allowed Z-order values range for this level. /// Used to define minimal Z-order value for types that are supposed to live above TextSelection /// which has a fixed Z-order value /// /// the Z-order level /// min Z-order value for this level /// max Z-order value for this level internal static void SetZLevelRange(int level, int min, int max) { if (_ZRanges[level] == null) { _ZRanges.Add(level, new ZRange(min, max)); } } #endregion Static Methods #region Public Properties ////// Returns the adorner layer which acts as a host for annotation components managed by the annotation component manager /// ///UIElement for the adorner layer public override UIElement Host { get { return _adornerLayer; } } ////// Get the enclosing presentation context. /// ///Enclosing PresentationContext or null if there is none public override PresentationContext EnclosingContext { get { Visual parent = VisualTreeHelper.GetParent(_adornerLayer) as Visual; if (parent == null) return null; AdornerLayer parentLayer = AdornerLayer.GetAdornerLayer((UIElement)parent); if (parentLayer == null) return null; PresentationContext p = new AdornerPresentationContext(parentLayer, null); return p; } } #endregion Public Properties #region Public Methods ////// Add the component to the adornerlayer of this presentation context. /// Create a new presentation context which includes the wrapped annotation adorner and the adornerlayer. /// Assign new presentation context into the component. /// /// Component to add to host public override void AddToHost(IAnnotationComponent component) { if (component == null) throw new ArgumentNullException("component"); AdornerPresentationContext.HostComponent(_adornerLayer, component, component.AnnotatedElement, false); } ////// Remove annotation component from host; in our case: respective annotation adorner from adornerLayer. /// If this presentation context does not contain the component search the adorner layer. /// Null out the presentation context of the component and set the local annotationAdorner to null if necessary, /// ask the annotation adorner to remove all visual children. /// /// Component to remove from host /// if true - recalculate z-order public override void RemoveFromHost(IAnnotationComponent component, bool reorder) { if (component == null) throw new ArgumentNullException("component"); if (IsInternalComponent(component)) { _annotationAdorner.AnnotationComponent.PresentationContext = null; _adornerLayer.Remove(_annotationAdorner); _annotationAdorner.RemoveChildren(); _annotationAdorner = null; } else {// need to find annotation adorner in layer, remove it and do house-keeping AnnotationAdorner foundAdorner = this.FindAnnotationAdorner(component); if (foundAdorner == null) throw new InvalidOperationException(SR.Get(SRID.ComponentNotInPresentationContext, component)); _adornerLayer.Remove(foundAdorner); foundAdorner.RemoveChildren(); // now get rid of reference from presentation context of annotation component to annotation adorner AdornerPresentationContext p = component.PresentationContext as AdornerPresentationContext; if (p != null) p.ResetInternalAnnotationAdorner(); // finally get rid of reference from annotation component to presentation context component.PresentationContext = null; } } ////// Invalidate the transform for this adorner. called when adorner inside changed aspects of the transform. /// This might go away if InvalidateMeasure works /// (unclear if Peter means this should work on the adorner or even one down on the annotation component itself) /// /// Component to invalidate transform for public override void InvalidateTransform(IAnnotationComponent component) { AnnotationAdorner adorner = GetAnnotationAdorner(component); adorner.InvalidateTransform(); } ////// Sets a component on top of its ZLevel /// /// Component to change z-order of public override void BringToFront(IAnnotationComponent component) { AnnotationAdorner adorner = GetAnnotationAdorner(component); int level = GetComponentLevel(component); int nextLevel = GetNextZOrder(_adornerLayer, level); // Only change the ZOrder if its not already on the top if (nextLevel != component.ZOrder + 1) { component.ZOrder = nextLevel; _adornerLayer.SetAdornerZOrder(adorner, ComponentToAdorner(component.ZOrder, level)); } } ////// Sets a component on bttom of its ZLevel /// /// Component to change z-order of public override void SendToBack(IAnnotationComponent component) { AnnotationAdorner adorner = GetAnnotationAdorner(component); int level = GetComponentLevel(component); // Only change the ZOrder if its not already on the bottom if (0 != component.ZOrder) { component.ZOrder = 0; UpdateComponentZOrder(component); } } ////// Determines if the passed in object is equal to this object. /// Two AdornerPresentationContexts will be equal if they both have the same adorner layer. /// /// The object to compare with. ///True if the objects are equal. False otherwise. public override bool Equals(object o) { AdornerPresentationContext p = o as AdornerPresentationContext; if (p != null) { return (p._adornerLayer == this._adornerLayer); } return false; } ////// overload operator for ==, to be same as Equal implementation. /// /// AdornerPresentationContext to compare /// AdornerPresentationContext to compare ///public static bool operator ==(AdornerPresentationContext left, AdornerPresentationContext right) { if ((object)left == null) return (object)right == null; return left.Equals(right); } /// /// overload operator for !=, to go along with definition for == /// /// AdornerPresentationContext to compare /// AdornerPresentationContext to compare ///public static bool operator !=(AdornerPresentationContext c1, AdornerPresentationContext c2) { return !(c1 == c2); } /// /// Delegate hash to adorner layer /// public override int GetHashCode() { return (int)this._adornerLayer.GetHashCode(); } ////// Updates the ZOrder of the input component and on all components with the same ZLevel /// that have same or bigger Z-order as the input component on a given adorner layer /// /// the component public void UpdateComponentZOrder(IAnnotationComponent component) { Invariant.Assert(component != null, "null component"); //check Z-order range for this level int level = GetComponentLevel(component); //get the component's adorner AnnotationAdorner adorner = FindAnnotationAdorner(component); if (adorner == null) return; //set the adorner z-order _adornerLayer.SetAdornerZOrder(adorner, ComponentToAdorner(component.ZOrder, level)); Listadorners = GetTopAnnotationAdorners(level, component); if (adorners == null) return; int lastZOrder = component.ZOrder + 1; foreach (AnnotationAdorner topAdorner in adorners) { topAdorner.AnnotationComponent.ZOrder = lastZOrder; _adornerLayer.SetAdornerZOrder(topAdorner, ComponentToAdorner(lastZOrder, level)); lastZOrder++; } } #endregion Public Methods #region Private Methods /// /// Reset the annotation adorner to null. This is needed for reset of found adorner in method RemoveFromHost /// private void ResetInternalAnnotationAdorner() { _annotationAdorner = null; } ////// Return true if the given annotation component is the one this presentation context is on. /// /// The component that might be referred to by this presentation context ///True if the component is internal private bool IsInternalComponent(IAnnotationComponent component) { return _annotationAdorner != null && component == _annotationAdorner.AnnotationComponent; } ////// Return the annotation adorner for the given annotation component. /// will not look at local annotation adorner, will always iterate through annotation adorners of adorner layer. /// Return null if none can be found. /// /// The component that is wrapped by an annotation adorner ///The annotation adorner that wraps the component in the adorner layer associated with this presentation context private AnnotationAdorner FindAnnotationAdorner(IAnnotationComponent component) { if (_adornerLayer == null) return null; foreach (Adorner adorner in _adornerLayer.GetAdorners(component.AnnotatedElement)) { AnnotationAdorner annotationAdorner = adorner as AnnotationAdorner; if (annotationAdorner != null && annotationAdorner.AnnotationComponent == component) return annotationAdorner; } return null; } ////// Finds all AnnotationAddorners from particular Z-level that have the same or bigger z-order as the component /// /// the ZLevel of interest /// the component ///the AnnotationAdorner children private ListGetTopAnnotationAdorners(int level, IAnnotationComponent component) { List res = new List (); int count = VisualTreeHelper.GetChildrenCount(_adornerLayer); if (count == 0) return res; for (int i = 0; i < count; i++) { DependencyObject child = VisualTreeHelper.GetChild(_adornerLayer, i); AnnotationAdorner adorner = child as AnnotationAdorner; if (adorner != null) { IAnnotationComponent childComponent = adorner.AnnotationComponent; if ((childComponent != component) && (GetComponentLevel(childComponent) == level) && (childComponent.ZOrder >= component.ZOrder)) { AddAdorner(res, adorner); } } } return res; } /// /// Inserts an adorner after the last adorner with ZOrder less or equal of the input one /// /// adorners list /// the new adorner ///In most cases the AnnotationAdorners are already orderd so we expect that the new one /// will be added at the end of the list. That is why we start scaning from the end. private void AddAdorner(Listadorners, AnnotationAdorner adorner) { Debug.Assert((adorners != null) && (adorner != null), "null adorners list or adorner"); int index = 0; if (adorners.Count > 0) { for (index = adorners.Count; index > 0; index--) { if (adorners[index-1].AnnotationComponent.ZOrder <= adorner.AnnotationComponent.ZOrder) break; } } adorners.Insert(index, adorner); } /// /// Gets the next free Z-order value for the components in this level /// /// adorner layer /// Z-level ///next free Z-order value private static int GetNextZOrder(AdornerLayer adornerLayer, int level) { Invariant.Assert(adornerLayer != null, "null adornerLayer"); int res = 0; int count = VisualTreeHelper.GetChildrenCount(adornerLayer); if (count == 0) return res; for ( int i = 0; i < count; i++) { DependencyObject child = VisualTreeHelper.GetChild(adornerLayer, i); AnnotationAdorner adorner = child as AnnotationAdorner; if (adorner != null) { if ((GetComponentLevel(adorner.AnnotationComponent) == level) && (adorner.AnnotationComponent.ZOrder >= res)) { res = adorner.AnnotationComponent.ZOrder + 1; } } } return res; } ////// Finds the correct AdornerLayer where a component lives /// /// the component ///private AnnotationAdorner GetAnnotationAdorner(IAnnotationComponent component) { if (component == null) throw new ArgumentNullException("component"); //find the adornerLayer AnnotationAdorner adorner = _annotationAdorner; if (!this.IsInternalComponent(component)) { adorner = this.FindAnnotationAdorner(component); if (adorner == null) throw new InvalidOperationException(SR.Get(SRID.ComponentNotInPresentationContext, component)); } return adorner; } /// /// Returns the component ZLevel /// /// component ///ZLevel private static int GetComponentLevel(IAnnotationComponent component) { int level = 0; Type type = component.GetType(); if (_ZLevel.ContainsKey(type)) level = (int)_ZLevel[type]; return level; } ////// Converts the component z-order to the Adorner z-order. The adorner z-order /// is shifted by the minimal value for this level. Also there is a restriction /// about the maximal possible value for this level too /// /// component z-order /// component z-level ///private static int ComponentToAdorner(int zOrder, int level) { int res = zOrder; ZRange range = (ZRange)_ZRanges[level]; if (range != null) { //adjust the Z-order (shift it with the minimal value for this range) //that way the component does need to know the range for its type that is // set by the application. It always sets the z-order as it starts from 0 res += range.Min; if (res < range.Min) res = range.Min; if (res > range.Max) res = range.Max; } return res; } #endregion Private Methods #region Private Fields /// /// The annotation adorner which wraps the annotation component this presentation context is optimized for. /// Can be null. /// private AnnotationAdorner _annotationAdorner = null; ////// The adornerLayer which contains the annotation component. Basically what the presentation hides. /// private AdornerLayer _adornerLayer; ////// The hashtable holds the priority level for each Component type as defined by the application /// private static Hashtable _ZLevel = new Hashtable(); ////// The ZRanges for the ZLevels. /// private static Hashtable _ZRanges = new Hashtable(); #endregion Private Fields #region Private classes ////// This is to control the relationships with TextSelection which lives in the same /// AdornerLayer. Will be removed when more flexible Z-ordering mechanism is available /// private class ZRange { public ZRange(int min, int max) { //exchange values if needed if (min > max) { int temp = min; min = max; max = temp; } _min = min; _max = max; } public int Min { get { return _min; } } public int Max { get { return _max; } } private int _min, _max; } #endregion Internal classes } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- SiteMapDataSource.cs
- ListItemCollection.cs
- SqlClientWrapperSmiStreamChars.cs
- WebServiceParameterData.cs
- WindowsListViewSubItem.cs
- Int16Storage.cs
- NullReferenceException.cs
- ControlIdConverter.cs
- TdsParserSafeHandles.cs
- AssociationSetEnd.cs
- SR.cs
- WS2007FederationHttpBinding.cs
- ClientUtils.cs
- SafeLibraryHandle.cs
- Command.cs
- EntityClientCacheEntry.cs
- Bits.cs
- DataGridItemEventArgs.cs
- DataGridViewAdvancedBorderStyle.cs
- Point4DValueSerializer.cs
- SafeProcessHandle.cs
- WebPartDisplayModeEventArgs.cs
- ListManagerBindingsCollection.cs
- EUCJPEncoding.cs
- EarlyBoundInfo.cs
- CommonGetThemePartSize.cs
- TagMapInfo.cs
- Variant.cs
- ConsumerConnectionPointCollection.cs
- AddInPipelineAttributes.cs
- ServiceModelReg.cs
- DataGridViewHeaderCell.cs
- SchemaTableColumn.cs
- BamlLocalizationDictionary.cs
- BuildResultCache.cs
- PageTheme.cs
- MenuItem.cs
- TrackingMemoryStreamFactory.cs
- TerminateSequenceResponse.cs
- VisualBasicSettingsHandler.cs
- TreeViewHitTestInfo.cs
- securitycriticaldataformultiplegetandset.cs
- DocumentViewer.cs
- TimeSpan.cs
- InitiatorServiceModelSecurityTokenRequirement.cs
- RectangleHotSpot.cs
- DeclaredTypeElement.cs
- SmiEventSink_DeferedProcessing.cs
- DefaultSerializationProviderAttribute.cs
- ScaleTransform3D.cs
- ActivityTypeDesigner.xaml.cs
- RepeatBehaviorConverter.cs
- OleDbConnectionFactory.cs
- DesignerActionMethodItem.cs
- ConditionalAttribute.cs
- RegexCompiler.cs
- FileIOPermission.cs
- StreamSecurityUpgradeInitiatorAsyncResult.cs
- BitmapMetadataEnumerator.cs
- SrgsElementFactory.cs
- QilLiteral.cs
- ListViewContainer.cs
- Button.cs
- HyperLinkField.cs
- TypeLibConverter.cs
- TextTreePropertyUndoUnit.cs
- WebPartCancelEventArgs.cs
- TaiwanLunisolarCalendar.cs
- SolidColorBrush.cs
- SimpleHandlerBuildProvider.cs
- XAMLParseException.cs
- GroupDescription.cs
- TextEvent.cs
- StyleXamlParser.cs
- ButtonFieldBase.cs
- PreDigestedSignedInfo.cs
- WindowsButton.cs
- XsltCompileContext.cs
- DifferencingCollection.cs
- BuildResultCache.cs
- FixedSOMImage.cs
- TextContainerChangedEventArgs.cs
- PerformanceCounter.cs
- PreProcessor.cs
- ServiceDiscoveryElement.cs
- BaseTemplateBuildProvider.cs
- ObjectCache.cs
- propertytag.cs
- ReachSerializer.cs
- LookupBindingPropertiesAttribute.cs
- ObjectNotFoundException.cs
- XslUrlEditor.cs
- SearchForVirtualItemEventArgs.cs
- log.cs
- DynamicAttribute.cs
- MemberDescriptor.cs
- HuffmanTree.cs
- Decoder.cs
- SerializationEventsCache.cs
- Expressions.cs