Files
HandyControl/src/Shared/HandyControl_Shared/Controls/Other/Magnifier.cs
T

161 lines
5.5 KiB
C#

using System.Windows;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using HandyControl.Data;
using HandyControl.Interactivity;
using HandyControl.Tools;
using HandyControl.Tools.Extension;
namespace HandyControl.Controls
{
[TemplatePart(Name = ElementVisualBrush, Type = typeof(VisualBrush))]
public class Magnifier : AdornerElement
{
private AdornerContainer _adornerContainer;
private Size _viewboxSize;
private const string ElementVisualBrush = "PART_VisualBrush";
private VisualBrush _visualBrush = new VisualBrush();
private readonly TranslateTransform _translateTransform;
public static readonly DependencyProperty HorizontalOffsetProperty = DependencyProperty.Register(
"HorizontalOffset", typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
public double HorizontalOffset
{
get => (double) GetValue(HorizontalOffsetProperty);
set => SetValue(HorizontalOffsetProperty, value);
}
public static readonly DependencyProperty VerticalOffsetProperty = DependencyProperty.Register(
"VerticalOffset", typeof(double), typeof(Magnifier), new PropertyMetadata(ValueBoxes.Double0Box));
public double VerticalOffset
{
get => (double) GetValue(VerticalOffsetProperty);
set => SetValue(VerticalOffsetProperty, value);
}
public static Magnifier Default => new Magnifier();
public static readonly DependencyProperty ScaleProperty = DependencyProperty.Register(
"Scale", typeof(double), typeof(Magnifier), new PropertyMetadata(5.0, OnScaleChanged), ValidateHelper.IsInRangeOfPosDouble);
private static void OnScaleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => ((Magnifier) d).UpdateViewboxSize();
public double Scale
{
get => (double) GetValue(ScaleProperty);
set => SetValue(ScaleProperty, value);
}
public Magnifier()
{
_translateTransform = new TranslateTransform();
RenderTransform = _translateTransform;
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
var visualBrush = GetTemplateChild(ElementVisualBrush) as VisualBrush ?? new VisualBrush();
visualBrush.Viewbox = _visualBrush.Viewbox;
_visualBrush = visualBrush;
}
protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
{
base.OnRenderSizeChanged(sizeInfo);
UpdateViewboxSize();
}
private void UpdateViewboxSize() => _viewboxSize = new Size(ActualWidth / Scale, ActualHeight / Scale);
protected sealed override void OnTargetChanged(FrameworkElement element, bool isNew)
{
base.OnTargetChanged(element, isNew);
if (element == null) return;
if (!isNew)
{
element.MouseEnter -= Element_MouseEnter;
element.MouseLeave -= Element_MouseLeave;
element.MouseMove -= Element_MouseMove;
ElementTarget = null;
}
else
{
element.MouseEnter += Element_MouseEnter;
element.MouseLeave += Element_MouseLeave;
element.MouseMove += Element_MouseMove;
ElementTarget = element;
}
}
protected override void Dispose() => HideAdornerElement();
private void UpdateLocation()
{
var targetPoint = Mouse.GetPosition(Target);
var subX = targetPoint.X - _visualBrush.Viewbox.Width / 2;
var subY = targetPoint.Y - _visualBrush.Viewbox.Height / 2;
var targetVector = VisualTreeHelper.GetOffset(Target);
_visualBrush.Viewbox = new Rect(new Point(subX + targetVector.X, subY + targetVector.Y), _viewboxSize);
var adornerPoint = Mouse.GetPosition(_adornerContainer);
_translateTransform.X = adornerPoint.X + HorizontalOffset;
_translateTransform.Y = adornerPoint.Y + VerticalOffset;
}
private void Element_MouseMove(object sender, MouseEventArgs e) => UpdateLocation();
private void Element_MouseLeave(object sender, MouseEventArgs e) => HideAdornerElement();
private void Element_MouseEnter(object sender, MouseEventArgs e) => ShowAdornerElement();
private void HideAdornerElement()
{
if (_adornerContainer == null) return;
var layer = AdornerLayer.GetAdornerLayer(Target);
if (layer != null)
{
layer.Remove(_adornerContainer);
}
else if (_adornerContainer != null && _adornerContainer.Parent is AdornerLayer parent)
{
parent.Remove(_adornerContainer);
}
if (_adornerContainer != null)
{
_adornerContainer.Child = null;
_adornerContainer = null;
}
}
private void ShowAdornerElement()
{
if (_adornerContainer == null)
{
var layer = AdornerLayer.GetAdornerLayer(Target);
if (layer == null) return;
_adornerContainer = new AdornerContainer(layer)
{
Child = this
};
layer.Add(_adornerContainer);
}
this.Show();
}
}
}