Browse Source

Merge branch 'master' into fixes/AddMissingRoutedEventsProperties

pull/8147/head
Max Katz 4 years ago
committed by GitHub
parent
commit
a66bdcf87f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs
  2. 53
      src/Avalonia.Controls/Viewbox.cs
  3. 13
      src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs
  4. 6
      src/Avalonia.FreeDesktop/NativeMethods.cs
  5. 104
      tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

2
src/Avalonia.Controls.DataGrid/Primitives/DataGridCellsPresenter.cs

@ -218,6 +218,8 @@ namespace Avalonia.Controls.Primitives
{
// No explicit height values were set so we can autosize
autoSizeHeight = true;
// We need to invalidate desired height in order to grow or shrink as needed
InvalidateDesiredHeight();
measureHeight = double.PositiveInfinity;
}
else

53
src/Avalonia.Controls/Viewbox.cs

@ -1,4 +1,5 @@
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Metadata;
namespace Avalonia.Controls
@ -8,7 +9,7 @@ namespace Avalonia.Controls
/// </summary>
public class Viewbox : Control
{
private Decorator _containerVisual;
private readonly ViewboxContainer _containerVisual;
/// <summary>
/// Defines the <see cref="Stretch"/> property.
@ -37,9 +38,10 @@ namespace Avalonia.Controls
public Viewbox()
{
_containerVisual = new Decorator();
// The Child control is hosted inside a ViewboxContainer control so that the transform
// can be applied independently of the Viewbox and Child transforms.
_containerVisual = new ViewboxContainer();
_containerVisual.RenderTransformOrigin = RelativePoint.TopLeft;
LogicalChildren.Add(_containerVisual);
VisualChildren.Add(_containerVisual);
}
@ -88,7 +90,22 @@ namespace Avalonia.Controls
if (change.Property == ChildProperty)
{
_containerVisual.Child = change.GetNewValue<IControl>();
var (oldChild, newChild) = change.GetOldAndNewValue<IControl>();
if (oldChild is not null)
{
((ISetLogicalParent)oldChild).SetParent(null);
LogicalChildren.Remove(oldChild);
}
_containerVisual.Child = newChild;
if (newChild is not null)
{
((ISetLogicalParent)newChild).SetParent(this);
LogicalChildren.Add(newChild);
}
InvalidateMeasure();
}
}
@ -120,7 +137,7 @@ namespace Avalonia.Controls
var childSize = child.DesiredSize;
var scale = Stretch.CalculateScaling(finalSize, childSize, StretchDirection);
InternalTransform = new ScaleTransform(scale.X, scale.Y);
InternalTransform = new ImmutableTransform(Matrix.CreateScale(scale.X, scale.Y));
child.Arrange(new Rect(childSize));
@ -129,5 +146,31 @@ namespace Avalonia.Controls
return finalSize;
}
/// <summary>
/// A simple container control which hosts its child as a visual but not logical child.
/// </summary>
private class ViewboxContainer : Control
{
private IControl? _child;
public IControl? Child
{
get => _child;
set
{
if (_child != value)
{
if (_child is not null)
VisualChildren.Remove(_child);
_child = value;
if (_child is not null)
VisualChildren.Add(_child);
}
}
}
}
}
}

13
src/Avalonia.FreeDesktop/LinuxMountedVolumeInfoListener.cs

@ -36,6 +36,13 @@ namespace Avalonia.FreeDesktop
private string GetSymlinkTarget(string x) => Path.GetFullPath(Path.Combine(DevByLabelDir, NativeMethods.ReadLink(x)));
private string UnescapeString(string input, string regexText, int escapeBase) =>
new Regex(regexText).Replace(input, m => Convert.ToChar(Convert.ToByte(m.Groups[1].Value, escapeBase)).ToString());
private string UnescapePathFromProcMounts(string input) => UnescapeString(input, @"\\(\d{3})", 8);
private string UnescapeDeviceLabel(string input) => UnescapeString(input, @"\\x([0-9a-f]{2})", 16);
private void Poll(long _)
{
var fProcPartitions = File.ReadAllLines(ProcPartitionsDir)
@ -47,14 +54,14 @@ namespace Avalonia.FreeDesktop
var fProcMounts = File.ReadAllLines(ProcMountsDir)
.Select(x => x.Split(' '))
.Select(x => (x[0], x[1]))
.Select(x => (x[0], UnescapePathFromProcMounts(x[1])))
.Where(x => !x.Item2.StartsWith("/snap/", StringComparison.InvariantCultureIgnoreCase));
var labelDirEnum = Directory.Exists(DevByLabelDir) ?
new DirectoryInfo(DevByLabelDir).GetFiles() : Enumerable.Empty<FileInfo>();
var labelDevPathPairs = labelDirEnum
.Select(x => (GetSymlinkTarget(x.FullName), x.Name));
.Select(x => (GetSymlinkTarget(x.FullName), UnescapeDeviceLabel(x.Name)));
var q1 = from mount in fProcMounts
join device in fProcPartitions on mount.Item1 equals device.Item2
@ -64,7 +71,7 @@ namespace Avalonia.FreeDesktop
{
VolumePath = mount.Item2,
VolumeSizeBytes = device.Item1,
VolumeLabel = x.Name
VolumeLabel = x.Item2
};
var mountVolInfos = q1.ToArray();

6
src/Avalonia.FreeDesktop/NativeMethods.cs

@ -14,15 +14,15 @@ namespace Avalonia.FreeDesktop
public static string ReadLink(string path)
{
var symlinkMaxSize = Encoding.ASCII.GetMaxByteCount(path.Length);
var symlinkSize = Encoding.UTF8.GetByteCount(path);
var bufferSize = 4097; // PATH_MAX is (usually?) 4096, but we need to know if the result was truncated
var symlink = ArrayPool<byte>.Shared.Rent(symlinkMaxSize + 1);
var symlink = ArrayPool<byte>.Shared.Rent(symlinkSize + 1);
var buffer = ArrayPool<byte>.Shared.Rent(bufferSize);
try
{
var symlinkSize = Encoding.UTF8.GetBytes(path, 0, path.Length, symlink, 0);
Encoding.UTF8.GetBytes(path, 0, path.Length, symlink, 0);
symlink[symlinkSize] = 0;
var size = readlink(symlink, buffer, bufferSize);

104
tests/Avalonia.Controls.UnitTests/ViewboxTests.cs

@ -1,4 +1,5 @@
using Avalonia.Controls.Shapes;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.UnitTests;
using Xunit;
@ -18,11 +19,10 @@ namespace Avalonia.Controls.UnitTests
target.Arrange(new Rect(new Point(0, 0), target.DesiredSize));
Assert.Equal(new Size(200, 100), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(2.0, scaleTransform.ScaleX);
Assert.Equal(2.0, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(2.0, scale.X);
Assert.Equal(2.0, scale.Y);
}
[Fact]
@ -36,11 +36,10 @@ namespace Avalonia.Controls.UnitTests
target.Arrange(new Rect(new Point(0, 0), target.DesiredSize));
Assert.Equal(new Size(100, 50), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(1.0, scaleTransform.ScaleX);
Assert.Equal(1.0, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(1.0, scale.X);
Assert.Equal(1.0, scale.Y);
}
[Fact]
@ -54,11 +53,10 @@ namespace Avalonia.Controls.UnitTests
target.Arrange(new Rect(new Point(0, 0), target.DesiredSize));
Assert.Equal(new Size(200, 200), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(2.0, scaleTransform.ScaleX);
Assert.Equal(4.0, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(2.0, scale.X);
Assert.Equal(4.0, scale.Y);
}
[Fact]
@ -72,11 +70,10 @@ namespace Avalonia.Controls.UnitTests
target.Arrange(new Rect(new Point(0, 0), target.DesiredSize));
Assert.Equal(new Size(200, 200), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(4.0, scaleTransform.ScaleX);
Assert.Equal(4.0, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(4.0, scale.X);
Assert.Equal(4.0, scale.Y);
}
[Fact]
@ -90,11 +87,10 @@ namespace Avalonia.Controls.UnitTests
target.Arrange(new Rect(new Point(0, 0), target.DesiredSize));
Assert.Equal(new Size(400, 200), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(4.0, scaleTransform.ScaleX);
Assert.Equal(4.0, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(4.0, scale.X);
Assert.Equal(4.0, scale.Y);
}
[Fact]
@ -108,11 +104,10 @@ namespace Avalonia.Controls.UnitTests
target.Arrange(new Rect(new Point(0, 0), target.DesiredSize));
Assert.Equal(new Size(200, 100), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(2.0, scaleTransform.ScaleX);
Assert.Equal(2.0, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(2.0, scale.X);
Assert.Equal(2.0, scale.Y);
}
[Theory]
@ -136,11 +131,9 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.NotNull(scaleTransform);
Assert.Equal(expectedScale, scaleTransform.ScaleX);
Assert.Equal(expectedScale, scaleTransform.ScaleY);
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(expectedScale, scale.X);
Assert.Equal(expectedScale, scale.Y);
}
[Theory]
@ -164,11 +157,44 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(new Size(expectedWidth, expectedHeight), target.DesiredSize);
var scaleTransform = target.InternalTransform as ScaleTransform;
Assert.True(TryGetScale(target, out Vector scale));
Assert.Equal(expectedScale, scale.X);
Assert.Equal(expectedScale, scale.Y);
}
[Fact]
public void Child_Should_Be_Logical_Child_Of_Viewbox()
{
var target = new Viewbox();
Assert.Empty(target.GetLogicalChildren());
var child = new Canvas();
target.Child = child;
Assert.Single(target.GetLogicalChildren(), child);
Assert.Same(child.GetLogicalParent(), target);
target.Child = null;
Assert.Empty(target.GetLogicalChildren());
Assert.Null(child.GetLogicalParent());
}
private bool TryGetScale(Viewbox viewbox, out Vector scale)
{
if (viewbox.InternalTransform is null)
{
scale = default;
return false;
}
var matrix = viewbox.InternalTransform.Value;
Matrix.TryDecomposeTransform(matrix, out var decomposed);
Assert.NotNull(scaleTransform);
Assert.Equal(expectedScale, scaleTransform.ScaleX);
Assert.Equal(expectedScale, scaleTransform.ScaleY);
scale = decomposed.Scale;
return true;
}
}
}

Loading…
Cancel
Save