161 lines
5.5 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|