/************************************************************************************* Extended WPF Toolkit Copyright (C) 2007-2013 Xceed Software Inc. This program is provided to you under the terms of the Microsoft Public License (Ms-PL) as published at http://wpftoolkit.codeplex.com/license For more features, controls, and fast professional support, pick up the Plus Edition at http://xceed.com/wpf_toolkit Stay informed: follow @datagrid on Twitter or Like http://facebook.com/datagrids ***********************************************************************************/ using System.Windows; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; namespace Xceed.Wpf.Toolkit { public class MagnifierAdorner : Adorner { #region Members private Magnifier _magnifier; private Point _currentMousePosition; #endregion #region Constructors public MagnifierAdorner( UIElement element, Magnifier magnifier ) : base( element ) { _magnifier = magnifier; UpdateViewBox(); AddVisualChild( _magnifier ); Loaded += ( s, e ) => InputManager.Current.PostProcessInput += OnProcessInput; Unloaded += ( s, e ) => InputManager.Current.PostProcessInput -= OnProcessInput; } #endregion #region Private/Internal methods private void OnProcessInput( object sender, ProcessInputEventArgs e ) { Point pt = Mouse.GetPosition( this ); if( _currentMousePosition == pt ) return; _currentMousePosition = pt; UpdateViewBox(); InvalidateArrange(); } internal void UpdateViewBox() { var viewBoxLocation = CalculateViewBoxLocation(); _magnifier.ViewBox = new Rect( viewBoxLocation, _magnifier.ViewBox.Size ); } private Point CalculateViewBoxLocation() { double offsetX = 0, offsetY = 0; Point adorner = Mouse.GetPosition( this ); Point element = Mouse.GetPosition( AdornedElement ); offsetX = element.X - adorner.X; offsetY = element.Y - adorner.Y; //An element will use the offset from its parent (StackPanel, Grid, etc.) to be rendered. //When this element is put in a VisualBrush, the element will draw with that offset applied. //To fix this: we add that parent offset to Magnifier location. Vector parentOffsetVector = VisualTreeHelper.GetOffset( _magnifier.Target ); Point parentOffset = new Point( parentOffsetVector.X, parentOffsetVector.Y ); double left = _currentMousePosition.X - ( ( _magnifier.ViewBox.Width / 2 ) + offsetX ) + parentOffset.X; double top = _currentMousePosition.Y - ( ( _magnifier.ViewBox.Height / 2 ) + offsetY ) + parentOffset.Y; return new Point( left, top ); } #endregion #region Overrides protected override Visual GetVisualChild( int index ) { return _magnifier; } protected override int VisualChildrenCount { get { return 1; } } protected override Size MeasureOverride( Size constraint ) { _magnifier.Measure( constraint ); return base.MeasureOverride( constraint ); } protected override Size ArrangeOverride( Size finalSize ) { double x = _currentMousePosition.X - ( _magnifier.Width / 2 ); double y = _currentMousePosition.Y - ( _magnifier.Height / 2 ); _magnifier.Arrange( new Rect( x, y, _magnifier.Width, _magnifier.Height ) ); return base.ArrangeOverride( finalSize ); } #endregion } }