- content bigger then border - issues with scroll
- missing cursor when panning
- zoom when Max/Min is reached cause position is changing
- scrolls do not react to change of border bounds
- scrolls do not react to change of content bounds
This commit is contained in:
Marek Szkowron 2024-10-17 12:19:34 +02:00
Родитель 60d1ca107a
Коммит cb0da193e1
3 изменённых файлов: 73 добавлений и 22 удалений

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

@ -21,15 +21,16 @@ public partial class ZoomBorder : ILogicalScrollable
/// Calculate scrollable properties.
/// </summary>
/// <param name="source">The source bounds.</param>
/// <param name="borderSize">The size of border (this control)</param>
/// <param name="matrix">The transform matrix.</param>
/// <param name="extent">The extent of the scrollable content.</param>
/// <param name="viewport">The size of the viewport.</param>
/// <param name="offset">The current scroll offset.</param>
public static void CalculateScrollable(Rect source, Matrix matrix, out Size extent, out Size viewport, out Vector offset)
public static void CalculateScrollable(Rect source, Size borderSize, Matrix matrix, out Size extent, out Size viewport, out Vector offset)
{
var bounds = new Rect(0, 0, source.Width, source.Height);
viewport = bounds.Size;
viewport = borderSize;
var transformed = bounds.TransformToAABB(matrix);
@ -188,7 +189,7 @@ public partial class ZoomBorder : ILogicalScrollable
return;
}
CalculateScrollable(_element.Bounds, _matrix, out var extent, out var viewport, out var offset);
CalculateScrollable(_element.Bounds, this.Bounds.Size, _matrix, out var extent, out var viewport, out var offset);
Log($"[InvalidateScrollable] _element.Bounds: {_element.Bounds}, _matrix: {_matrix}");
Log($"[InvalidateScrollable] _extent: {_extent}, extent: {extent}, diff: {extent - _extent}");

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

@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using Avalonia.Controls.Metadata;
using Avalonia.Input;
using Avalonia.Media;
using Avalonia.Media.Transformation;
@ -11,6 +12,8 @@ namespace Avalonia.Controls.PanAndZoom;
/// <summary>
/// Pan and zoom control for Avalonia.
/// </summary>
[PseudoClasses(":isPanning")]
public partial class ZoomBorder : Border
{
[Conditional("DEBUG")]
@ -136,10 +139,18 @@ public partial class ZoomBorder : Border
Moved(e);
}
private void Element_PropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e)
{
if(e.Property == BoundsProperty)
{
InvalidateScrollable();
}
}
private void BoundsChanged(Rect bounds)
{
// Log($"[BoundsChanged] {bounds}");
//InvalidateScrollable();
InvalidateScrollable();
}
private void ChildChanged(Control? element)
@ -164,6 +175,7 @@ public partial class ZoomBorder : Border
return;
}
_element = element;
_element.PropertyChanged += Element_PropertyChanged;
PointerWheelChanged += Border_PointerWheelChanged;
PointerPressed += Border_PointerPressed;
PointerReleased += Border_PointerReleased;
@ -176,10 +188,12 @@ public partial class ZoomBorder : Border
{
return;
}
PointerWheelChanged -= Border_PointerWheelChanged;
PointerPressed -= Border_PointerPressed;
PointerReleased -= Border_PointerReleased;
PointerMoved -= Border_PointerMoved;
_element.PropertyChanged -= Element_PropertyChanged;
_element.RenderTransform = null;
_element = null;
}
@ -214,6 +228,7 @@ public partial class ZoomBorder : Border
BeginPanTo(point.X, point.Y);
_captured = true;
_isPanning = true;
SetPseudoClass(":isPanning", _isPanning);
}
}
@ -229,6 +244,7 @@ public partial class ZoomBorder : Border
}
_captured = false;
_isPanning = false;
SetPseudoClass(":isPanning", _isPanning);
}
private void Moved(PointerEventArgs e)
@ -421,6 +437,11 @@ public partial class ZoomBorder : Border
{
return;
}
if((ZoomX >= MaxZoomX && ZoomY >= MaxZoomY && ratio > 1) || (ZoomX <= MinZoomX && ZoomY <= MinZoomY && ratio < 1))
{
return;
}
_updating = true;
Log("[ZoomTo]");
@ -786,4 +807,6 @@ public partial class ZoomBorder : Border
}
AutoFit(Bounds.Width, Bounds.Height, _element.Bounds.Width, _element.Bounds.Height, skipTransitions);
}
private void SetPseudoClass(string name, bool flag) => PseudoClasses.Set(name, flag);
}

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

@ -95,20 +95,34 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_Default()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 100, 100);
var matrix = CreateMatrix();
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(100, 100), extent);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 300), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
}
[Fact]
public void CalculateScrollable_ViewportSmallerThenContent()
{
var borderSize = new Size(100, 100);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix();
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 300), extent);
Assert.Equal(new Size(100, 100), viewport);
Assert.Equal(new Vector(0, 0), offset);
}
[Fact]
public void CalculateScrollable_OffsetX_Negative()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(offsetX: -100);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(400, 300), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(100, 0), offset);
@ -117,9 +131,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_OffsetX_Positive()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(offsetX: 100);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(400, 300), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -128,9 +143,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_OffsetY_Negative()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(offsetY: -100);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 400), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 100), offset);
@ -139,9 +155,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_OffsetY_Positive()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(offsetY: 100);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 400), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -150,9 +167,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomIn_2x()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 2, scaleY: 2);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(600, 600), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -161,9 +179,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomIn_2x_OffsetX_Negative()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 2, scaleY: 2, offsetX: -150);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(600, 600), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(150, 0), offset);
@ -172,9 +191,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomIn_2x_OffsetX_Positive()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 2, scaleY: 2, offsetX: 150);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(600, 600), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -183,9 +203,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomIn_2x_OffsetY_Negative()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 2, scaleY: 2, offsetY: -150);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds,borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(600, 600), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 150), offset);
@ -194,9 +215,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomIn_2x_OffsetY_Positive()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 2, scaleY: 2, offsetY: 150);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(600, 600), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -205,9 +227,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomOut_0_5x()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 0.5, scaleY: 0.5);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 300), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -216,9 +239,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomOut_0_5x_OffsetX_Negative()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 0.5, scaleY: 0.5, offsetX: -200);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(500, 300), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(200, 0), offset);
@ -227,9 +251,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomOut_0_5x_OffsetX_Positive()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 0.5, scaleY: 0.5, offsetX: 200);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(350, 300), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
@ -238,9 +263,10 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomOut_0_5x_OffsetY_Negative()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 0.5, scaleY: 0.5, offsetY: -200);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 500), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 200), offset);
@ -249,11 +275,12 @@ public class ZoomBorderTests
[Fact]
public void CalculateScrollable_ZoomOut_0_5x_OffsetY_Positive()
{
var borderSize = new Size(300, 300);
var bounds = new Rect(0, 0, 300, 300);
var matrix = CreateMatrix(scaleX: 0.5, scaleY: 0.5, offsetY: 200);
ZoomBorder.CalculateScrollable(bounds, matrix, out var extent, out var viewport, out var offset);
ZoomBorder.CalculateScrollable(bounds, borderSize, matrix, out var extent, out var viewport, out var offset);
Assert.Equal(new Size(300, 350), extent);
Assert.Equal(new Size(300, 300), viewport);
Assert.Equal(new Vector(0, 0), offset);
}
}
}