This commit is contained in:
Wiesław Šoltés 2020-04-13 12:03:24 +02:00
Родитель a6b1d9ffb9
Коммит 47b942d5ec
1 изменённых файлов: 175 добавлений и 141 удалений

Просмотреть файл

@ -22,18 +22,18 @@ namespace Wpf.Controls.PanAndZoom
private Point _previous; private Point _previous;
private Matrix _matrix; private Matrix _matrix;
private bool _isPanning; private bool _isPanning;
private static StretchMode[] _autoFitModes = (StretchMode[])Enum.GetValues(typeof(StretchMode)); private static readonly StretchMode[] s_autoFitModes = (StretchMode[])Enum.GetValues(typeof(StretchMode));
private static ButtonName[] _buttonNames = (ButtonName[])Enum.GetValues(typeof(ButtonName)); private static readonly ButtonName[] s_buttonNames = (ButtonName[])Enum.GetValues(typeof(ButtonName));
/// <summary> /// <summary>
/// Gets available stretch modes. /// Gets available stretch modes.
/// </summary> /// </summary>
public static StretchMode[] StretchModes => _autoFitModes; public static StretchMode[] StretchModes => s_autoFitModes;
/// <summary> /// <summary>
/// Gets available button names. /// Gets available button names.
/// </summary> /// </summary>
public static ButtonName[] ButtonNames => _buttonNames; public static ButtonName[] ButtonNames => s_buttonNames;
/// <inheritdoc/> /// <inheritdoc/>
public Action<double, double, double, double>? InvalidatedChild { get; set; } public Action<double, double, double, double>? InvalidatedChild { get; set; }
@ -415,14 +415,16 @@ namespace Wpf.Controls.PanAndZoom
{ {
var size = base.ArrangeOverride(finalSize); var size = base.ArrangeOverride(finalSize);
if (_element != null && _element.IsMeasureValid) if (_element == null || !_element.IsMeasureValid)
{ {
return size;
}
AutoFit( AutoFit(
size.Width, size.Width,
size.Height, size.Height,
_element.RenderSize.Width, _element.RenderSize.Width,
_element.RenderSize.Height); _element.RenderSize.Height);
}
return size; return size;
} }
@ -441,39 +443,44 @@ namespace Wpf.Controls.PanAndZoom
private void Border_PreviewMouseWheel(object sender, MouseWheelEventArgs e) private void Border_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{ {
if (EnableInput) if (!EnableInput)
{ {
Wheel(e); return;
} }
Wheel(e);
} }
private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e) private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{ {
if (EnableInput) if (!EnableInput)
{ {
return;
}
var button = PanButton; var button = PanButton;
if ((e.ChangedButton == MouseButton.Left && button == ButtonName.Left) if ((e.ChangedButton != MouseButton.Left || button != ButtonName.Left)
|| (e.ChangedButton == MouseButton.Right && button == ButtonName.Right) && (e.ChangedButton != MouseButton.Right || button != ButtonName.Right)
|| (e.ChangedButton == MouseButton.Middle && button == ButtonName.Middle)) && (e.ChangedButton != MouseButton.Middle || button != ButtonName.Middle))
{ {
return;
}
Pressed(e); Pressed(e);
} }
}
}
private void Border_PreviewMouseUp(object sender, MouseButtonEventArgs e) private void Border_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{ {
if (EnableInput) if (!EnableInput)
{ {
return;
}
var button = PanButton; var button = PanButton;
if ((e.ChangedButton == MouseButton.Left && button == ButtonName.Left) if ((e.ChangedButton != MouseButton.Left || button != ButtonName.Left)
|| (e.ChangedButton == MouseButton.Right && button == ButtonName.Right) && (e.ChangedButton != MouseButton.Right || button != ButtonName.Right)
|| (e.ChangedButton == MouseButton.Middle && button == ButtonName.Middle)) && (e.ChangedButton != MouseButton.Middle || button != ButtonName.Middle))
{ {
return;
}
Released(e); Released(e);
} }
}
}
private void Border_PreviewMouseMove(object sender, MouseEventArgs e) private void Border_PreviewMouseMove(object sender, MouseEventArgs e)
{ {
@ -485,64 +492,46 @@ namespace Wpf.Controls.PanAndZoom
private void Border_ManipulationStarting(object? sender, ManipulationStartingEventArgs e) private void Border_ManipulationStarting(object? sender, ManipulationStartingEventArgs e)
{ {
if (EnableInput && _element != null) if (!EnableInput || _element == null)
{ {
e.ManipulationContainer = this; return;
} }
e.ManipulationContainer = this;
} }
private void Border_ManipulationDelta(object? sender, ManipulationDeltaEventArgs e) private void Border_ManipulationDelta(object? sender, ManipulationDeltaEventArgs e)
{ {
if (EnableInput && _element != null) if (!EnableInput || _element == null)
{ {
var deltaManipulation = e.DeltaManipulation; return;
double scale = ((deltaManipulation.Scale.X - 1) * ZoomSpeed) + 1;
var matrix = ((MatrixTransform)_element.RenderTransform).Matrix;
Point center = new Point(_element.RenderSize.Width / 2, _element.RenderSize.Height / 2);
center = matrix.Transform(center);
if (EnableGestureZoom)
{
matrix.ScaleAt(scale, scale, center.X, center.Y);
} }
Manipulation(e.DeltaManipulation);
if (EnableGestureRotation)
{
matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y);
}
if (EnableGestureTranslation)
{
matrix.Translate(e.DeltaManipulation.Translation.X, e.DeltaManipulation.Translation.Y);
}
((MatrixTransform)_element.RenderTransform).Matrix = matrix;
e.Handled = true; e.Handled = true;
SetValue(ZoomXPropertyKey, matrix.M11);
SetValue(ZoomYPropertyKey, matrix.M22);
SetValue(OffsetXPropertyKey, matrix.OffsetX);
SetValue(OffsetYPropertyKey, matrix.OffsetY);
}
} }
private void ChildChanged(UIElement element) private void ChildChanged(UIElement element)
{ {
if (element != null && element != _element && _element != null) if (element == null || element == _element || _element == null)
{
}
else
{ {
DetachElement(); DetachElement();
} }
if (element != null && element != _element) if (element == null || element == _element)
{ {
AttachElement(element); return;
} }
AttachElement(element);
} }
private void AttachElement(UIElement element) private void AttachElement(UIElement element)
{ {
if (element != null) if (element == null)
{ {
return;
}
Defaults(); Defaults();
_element = element; _element = element;
this.Focus(); this.Focus();
@ -553,12 +542,13 @@ namespace Wpf.Controls.PanAndZoom
this.ManipulationStarting += Border_ManipulationStarting; this.ManipulationStarting += Border_ManipulationStarting;
this.ManipulationDelta += Border_ManipulationDelta; this.ManipulationDelta += Border_ManipulationDelta;
} }
}
private void DetachElement() private void DetachElement()
{ {
if (_element != null) if (_element == null)
{ {
return;
}
this.PreviewMouseWheel -= Border_PreviewMouseWheel; this.PreviewMouseWheel -= Border_PreviewMouseWheel;
this.PreviewMouseDown -= Border_PreviewMouseDown; this.PreviewMouseDown -= Border_PreviewMouseDown;
this.PreviewMouseUp -= Border_PreviewMouseUp; this.PreviewMouseUp -= Border_PreviewMouseUp;
@ -569,44 +559,76 @@ namespace Wpf.Controls.PanAndZoom
_element = null; _element = null;
Defaults(); Defaults();
} }
}
private void Wheel(MouseWheelEventArgs e) private void Wheel(MouseWheelEventArgs e)
{ {
if (_element != null && Mouse.Captured == null) if (_element == null || Mouse.Captured != null)
{ {
return;
}
Point point = e.GetPosition(_element); Point point = e.GetPosition(_element);
ZoomDeltaTo((double)e.Delta, point.X, point.Y); ZoomDeltaTo((double)e.Delta, point.X, point.Y);
} }
}
private void Pressed(MouseButtonEventArgs e) private void Pressed(MouseButtonEventArgs e)
{ {
if (_element != null && Mouse.Captured == null && _isPanning == false) if (_element == null || Mouse.Captured != null || _isPanning != false)
{ {
return;
}
Point point = e.GetPosition(_element); Point point = e.GetPosition(_element);
StartPan(point.X, point.Y); StartPan(point.X, point.Y);
_element.CaptureMouse(); _element.CaptureMouse();
_isPanning = true; _isPanning = true;
} }
}
private void Released(MouseButtonEventArgs e) private void Released(MouseButtonEventArgs e)
{ {
if (_element != null && _element.IsMouseCaptured == true && _isPanning == true) if (_element == null || _element.IsMouseCaptured != true || _isPanning != true)
{ {
return;
}
_element.ReleaseMouseCapture(); _element.ReleaseMouseCapture();
_isPanning = false; _isPanning = false;
} }
}
private void Moved(MouseEventArgs e) private void Moved(MouseEventArgs e)
{ {
if (_element != null && _element.IsMouseCaptured == true && _isPanning == true) if (_element == null || _element.IsMouseCaptured != true || _isPanning != true)
{ {
return;
}
Point point = e.GetPosition(_element); Point point = e.GetPosition(_element);
PanTo(point.X, point.Y); PanTo(point.X, point.Y);
} }
private void Manipulation(ManipulationDelta delta)
{
if (_element == null)
{
return;
}
var scale = ((delta.Scale.X - 1) * ZoomSpeed) + 1;
var center = new Point(_element.RenderSize.Width / 2, _element.RenderSize.Height / 2);
center = _matrix.Transform(center);
if (EnableGestureZoom)
{
_matrix.ScaleAt(scale, scale, center.X, center.Y);
}
if (EnableGestureRotation)
{
_matrix.RotateAt(delta.Rotation, center.X, center.Y);
}
if (EnableGestureTranslation)
{
_matrix.Translate(delta.Translation.X, delta.Translation.Y);
}
Invalidate();
} }
private double Constrain(double value, double minimum, double maximum) private double Constrain(double value, double minimum, double maximum)
@ -632,8 +654,10 @@ namespace Wpf.Controls.PanAndZoom
/// <inheritdoc/> /// <inheritdoc/>
public void Invalidate() public void Invalidate()
{ {
if (_element != null) if (_element == null)
{ {
return;
}
if (EnableConstrains == true) if (EnableConstrains == true)
{ {
Constrain(); Constrain();
@ -648,7 +672,6 @@ namespace Wpf.Controls.PanAndZoom
_element.RenderTransform = new MatrixTransform(_matrix); _element.RenderTransform = new MatrixTransform(_matrix);
_element.InvalidateVisual(); _element.InvalidateVisual();
} }
}
/// <inheritdoc/> /// <inheritdoc/>
public void ZoomTo(double zoom, double x, double y) public void ZoomTo(double zoom, double x, double y)
@ -741,6 +764,9 @@ namespace Wpf.Controls.PanAndZoom
return MatrixHelper.ScaleAt(zoom, zoom, cx, cy); return MatrixHelper.ScaleAt(zoom, zoom, cx, cy);
} }
} }
case StretchMode.None:
break;
} }
return Matrix.Identity; return Matrix.Identity;
} }
@ -749,41 +775,46 @@ namespace Wpf.Controls.PanAndZoom
public void Fill(double panelWidth, double panelHeight, double elementWidth, double elementHeight) public void Fill(double panelWidth, double panelHeight, double elementWidth, double elementHeight)
{ {
Debug.WriteLine($"Fill: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}"); Debug.WriteLine($"Fill: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}");
if (_element != null) if (_element == null)
{ {
return;
}
_matrix = GetMatrix(panelWidth, panelHeight, elementWidth, elementHeight, StretchMode.Fill); _matrix = GetMatrix(panelWidth, panelHeight, elementWidth, elementHeight, StretchMode.Fill);
Invalidate(); Invalidate();
} }
}
/// <inheritdoc/> /// <inheritdoc/>
public void Uniform(double panelWidth, double panelHeight, double elementWidth, double elementHeight) public void Uniform(double panelWidth, double panelHeight, double elementWidth, double elementHeight)
{ {
Debug.WriteLine($"Uniform: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}"); Debug.WriteLine($"Uniform: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}");
if (_element != null) if (_element == null)
{ {
return;
}
_matrix = GetMatrix(panelWidth, panelHeight, elementWidth, elementHeight, StretchMode.Uniform); _matrix = GetMatrix(panelWidth, panelHeight, elementWidth, elementHeight, StretchMode.Uniform);
Invalidate(); Invalidate();
} }
}
/// <inheritdoc/> /// <inheritdoc/>
public void UniformToFill(double panelWidth, double panelHeight, double elementWidth, double elementHeight) public void UniformToFill(double panelWidth, double panelHeight, double elementWidth, double elementHeight)
{ {
Debug.WriteLine($"UniformToFill: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}"); Debug.WriteLine($"UniformToFill: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}");
if (_element != null) if (_element == null)
{ {
return;
}
_matrix = GetMatrix(panelWidth, panelHeight, elementWidth, elementHeight, StretchMode.UniformToFill); _matrix = GetMatrix(panelWidth, panelHeight, elementWidth, elementHeight, StretchMode.UniformToFill);
Invalidate(); Invalidate();
} }
}
/// <inheritdoc/> /// <inheritdoc/>
public void AutoFit(double panelWidth, double panelHeight, double elementWidth, double elementHeight) public void AutoFit(double panelWidth, double panelHeight, double elementWidth, double elementHeight)
{ {
Debug.WriteLine($"AutoFit: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}"); Debug.WriteLine($"AutoFit: {panelWidth}x{panelHeight} {elementWidth}x{elementHeight}");
if (_element != null) if (_element == null)
{ {
return;
}
switch (Stretch) switch (Stretch)
{ {
case StretchMode.Fill: case StretchMode.Fill:
@ -798,7 +829,6 @@ namespace Wpf.Controls.PanAndZoom
} }
Invalidate(); Invalidate();
} }
}
/// <inheritdoc/> /// <inheritdoc/>
public void ToggleStretchMode() public void ToggleStretchMode()
@ -830,37 +860,41 @@ namespace Wpf.Controls.PanAndZoom
/// <inheritdoc/> /// <inheritdoc/>
public void Fill() public void Fill()
{ {
if (_element != null) if (_element == null)
{ {
Fill(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height); return;
} }
Fill(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height);
} }
/// <inheritdoc/> /// <inheritdoc/>
public void Uniform() public void Uniform()
{ {
if (_element != null) if (_element == null)
{ {
Uniform(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height); return;
} }
Uniform(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height);
} }
/// <inheritdoc/> /// <inheritdoc/>
public void UniformToFill() public void UniformToFill()
{ {
if (_element != null) if (_element == null)
{ {
UniformToFill(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height); return;
} }
UniformToFill(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height);
} }
/// <inheritdoc/> /// <inheritdoc/>
public void AutoFit() public void AutoFit()
{ {
if (_element != null) if (_element == null)
{ {
return;
}
AutoFit(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height); AutoFit(this.RenderSize.Width, this.RenderSize.Height, _element.RenderSize.Width, _element.RenderSize.Height);
} }
} }
} }
}