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
- JsonServiceDocumentSerializer.cs
- StringPropertyBuilder.cs
- MenuItemStyle.cs
- SQLRoleProvider.cs
- PrimitiveType.cs
- ToolStripSettings.cs
- DataFormat.cs
- DataGridViewCellStyle.cs
- sqlmetadatafactory.cs
- LoginView.cs
- exports.cs
- DataKeyCollection.cs
- SortedList.cs
- InputScopeConverter.cs
- COM2PictureConverter.cs
- StreamWriter.cs
- EntityClientCacheKey.cs
- ArrayExtension.cs
- DuplicateDetector.cs
- ToolStripTextBox.cs
- ListViewItemMouseHoverEvent.cs
- DynamicEntity.cs
- HiddenFieldPageStatePersister.cs
- DocumentGrid.cs
- MatrixAnimationUsingKeyFrames.cs
- TextElement.cs
- ScriptControlManager.cs
- TreeView.cs
- StandardBindingImporter.cs
- QilLoop.cs
- SqlDataReader.cs
- DocumentGrid.cs
- SortFieldComparer.cs
- ElementHost.cs
- LookupNode.cs
- MergeFilterQuery.cs
- NotifyCollectionChangedEventArgs.cs
- UnmanagedBitmapWrapper.cs
- StylusButton.cs
- DataSourceView.cs
- DataSetMappper.cs
- XsltContext.cs
- SrgsElement.cs
- SelectionWordBreaker.cs
- XmlProcessingInstruction.cs
- ProfileManager.cs
- GrammarBuilderRuleRef.cs
- DynamicObject.cs
- Bitmap.cs
- ProcessStartInfo.cs
- PipeStream.cs
- RuntimeWrappedException.cs
- HebrewNumber.cs
- OutputWindow.cs
- NamespaceInfo.cs
- FormViewPagerRow.cs
- GeneralTransformGroup.cs
- RegexCapture.cs
- FileSecurity.cs
- PropertyValueChangedEvent.cs
- UnmanagedMemoryAccessor.cs
- XmlSchemaImporter.cs
- AdRotatorDesigner.cs
- XmlDocumentFragment.cs
- ToolboxCategoryItems.cs
- DynamicRouteExpression.cs
- _TransmitFileOverlappedAsyncResult.cs
- RtfFormatStack.cs
- PermissionAttributes.cs
- cookie.cs
- ToolBarButtonClickEvent.cs
- CqlLexerHelpers.cs
- UMPAttributes.cs
- ContainerFilterService.cs
- ReplyAdapterChannelListener.cs
- CodeParameterDeclarationExpression.cs
- ReflectionUtil.cs
- DesignerAutoFormatCollection.cs
- InternalsVisibleToAttribute.cs
- OwnerDrawPropertyBag.cs
- TextTreeTextBlock.cs
- CaseStatement.cs
- TrustManagerMoreInformation.cs
- InstanceLockQueryResult.cs
- AutoCompleteStringCollection.cs
- CodeSubDirectory.cs
- DataGridViewColumnConverter.cs
- LayoutTableCell.cs
- DataGridCommandEventArgs.cs
- KerberosRequestorSecurityTokenAuthenticator.cs
- Window.cs
- DbConnectionClosed.cs
- AttachedAnnotation.cs
- RoleGroupCollection.cs
- CorrelationInitializer.cs
- XmlEntityReference.cs
- BrowserDefinitionCollection.cs
- SiteOfOriginPart.cs
- EntityDataSourceChangingEventArgs.cs
- RoleGroupCollection.cs