Warning cleanup 2 (#13696)
This commit is contained in:
committed by
GitHub
parent
2852c149e8
commit
3fa13d3b64
+1
-1
@@ -6,7 +6,7 @@
|
||||
<PackageReference Include="xunit.extensibility.core" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.extensibility.execution" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.console" Version="2.4.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5" Condition="'$(TargetFramework)' != 'netstandard2.0'" />
|
||||
<PackageReference Include="Xunit.SkippableFact" Version="1.4.13" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -160,7 +160,7 @@ namespace ControlCatalog.Pages
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFolder(await GetStorageProvider().TryGetFolderFromPathAsync(result));
|
||||
SetFolder(await GetStorageProvider().TryGetFolderFromPathAsync(result!));
|
||||
results.ItemsSource = new[] { result };
|
||||
resultsVisible.IsVisible = true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Markup.Xaml;
|
||||
@@ -14,26 +15,54 @@ namespace ControlCatalog.Pages
|
||||
private const string CustomFormat = "application/xxx-avalonia-controlcatalog-custom";
|
||||
public DragAndDropPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
InitializeComponent();
|
||||
_dropState = this.Get<TextBlock>("DropState");
|
||||
|
||||
int textCount = 0;
|
||||
SetupDnd("Text", d => d.Set(DataFormats.Text,
|
||||
$"Text was dragged {++textCount} times"), DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link);
|
||||
|
||||
SetupDnd("Custom", d => d.Set(CustomFormat, "Test123"), DragDropEffects.Move);
|
||||
SetupDnd("Files", async d => d.Set(DataFormats.Files, new[] { await (VisualRoot as TopLevel)!.StorageProvider.TryGetFileFromPathAsync(Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName) }), DragDropEffects.Copy);
|
||||
SetupDnd(
|
||||
"Text",
|
||||
d => d.Set(DataFormats.Text, $"Text was dragged {++textCount} times"),
|
||||
DragDropEffects.Copy | DragDropEffects.Move | DragDropEffects.Link);
|
||||
|
||||
SetupDnd(
|
||||
"Custom",
|
||||
d => d.Set(CustomFormat, "Test123"),
|
||||
DragDropEffects.Move);
|
||||
|
||||
SetupDnd(
|
||||
"Files",
|
||||
async d =>
|
||||
{
|
||||
if (Assembly.GetEntryAssembly()?.GetModules().FirstOrDefault()?.FullyQualifiedName is { } name &&
|
||||
TopLevel.GetTopLevel(this) is { } topLevel &&
|
||||
await topLevel.StorageProvider.TryGetFileFromPathAsync(name) is { } storageFile)
|
||||
{
|
||||
d.Set(DataFormats.Files, new[] { storageFile });
|
||||
}
|
||||
},
|
||||
DragDropEffects.Copy);
|
||||
}
|
||||
|
||||
void SetupDnd(string suffix, Action<DataObject> factory, DragDropEffects effects)
|
||||
private void SetupDnd(string suffix, Action<DataObject> factory, DragDropEffects effects) =>
|
||||
SetupDnd(
|
||||
suffix,
|
||||
o =>
|
||||
{
|
||||
factory(o);
|
||||
return Task.CompletedTask;
|
||||
},
|
||||
effects);
|
||||
|
||||
private void SetupDnd(string suffix, Func<DataObject, Task> factory, DragDropEffects effects)
|
||||
{
|
||||
var dragMe = this.Get<Border>("DragMe" + suffix);
|
||||
var dragState = this.Get<TextBlock>("DragState" + suffix);
|
||||
|
||||
async void DoDrag(object? sender, Avalonia.Input.PointerPressedEventArgs e)
|
||||
async void DoDrag(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
var dragData = new DataObject();
|
||||
factory(dragData);
|
||||
await factory(dragData);
|
||||
|
||||
var result = await DragDrop.DoDragDrop(e, dragData, effects);
|
||||
switch (result)
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace ControlCatalog.ViewModels
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
Items.Remove(item);
|
||||
Items.Remove(item!);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace Generators.Sandbox.Controls;
|
||||
|
||||
public class CustomTextBox : TextBox, IStyleable
|
||||
public class CustomTextBox : TextBox
|
||||
{
|
||||
Type IStyleable.StyleKey => typeof(TextBox);
|
||||
}
|
||||
protected override Type StyleKeyOverride => typeof(TextBox);
|
||||
}
|
||||
|
||||
@@ -20,21 +20,21 @@ namespace GpuInterop.D3DDemo;
|
||||
|
||||
public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
{
|
||||
private D3DDevice _device;
|
||||
private D3D11Swapchain _swapchain;
|
||||
private SharpDX.Direct3D11.DeviceContext _context;
|
||||
private D3DDevice? _device;
|
||||
private D3D11Swapchain? _swapchain;
|
||||
private DeviceContext? _context;
|
||||
private Matrix _view;
|
||||
private PixelSize _lastSize;
|
||||
private Texture2D _depthBuffer;
|
||||
private DepthStencilView _depthView;
|
||||
private Texture2D? _depthBuffer;
|
||||
private DepthStencilView? _depthView;
|
||||
private Matrix _proj;
|
||||
private Buffer _constantBuffer;
|
||||
private Stopwatch _st = Stopwatch.StartNew();
|
||||
private Buffer? _constantBuffer;
|
||||
private readonly Stopwatch _st = Stopwatch.StartNew();
|
||||
|
||||
protected override (bool success, string info) InitializeGraphicsResources(Compositor compositor,
|
||||
CompositionDrawingSurface surface, ICompositionGpuInterop interop)
|
||||
{
|
||||
if (interop?.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
|
||||
if (interop.SupportedImageHandleTypes.Contains(KnownPlatformGraphicsExternalImageHandleTypes
|
||||
.D3D11TextureGlobalSharedHandle) != true)
|
||||
return (false, "DXGI shared handle import is not supported by the current graphics backend");
|
||||
|
||||
@@ -60,8 +60,12 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
|
||||
protected override void FreeGraphicsResources()
|
||||
{
|
||||
_swapchain.DisposeAsync();
|
||||
_swapchain = null!;
|
||||
if (_swapchain is not null)
|
||||
{
|
||||
_swapchain.DisposeAsync().GetAwaiter().GetResult();
|
||||
_swapchain = null;
|
||||
}
|
||||
|
||||
Utilities.Dispose(ref _depthView);
|
||||
Utilities.Dispose(ref _depthBuffer);
|
||||
Utilities.Dispose(ref _constantBuffer);
|
||||
@@ -80,10 +84,10 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
_lastSize = pixelSize;
|
||||
Resize(pixelSize);
|
||||
}
|
||||
using (_swapchain.BeginDraw(pixelSize, out var renderView))
|
||||
using (_swapchain!.BeginDraw(pixelSize, out var renderView))
|
||||
{
|
||||
|
||||
_device.ImmediateContext.OutputMerger.SetTargets(_depthView, renderView);
|
||||
_device!.ImmediateContext.OutputMerger.SetTargets(_depthView, renderView);
|
||||
var viewProj = Matrix.Multiply(_view, _proj);
|
||||
var context = _device.ImmediateContext;
|
||||
|
||||
@@ -101,10 +105,10 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
|
||||
var ypr = Matrix4x4.CreateFromYawPitchRoll(Yaw, Pitch, Roll);
|
||||
// Update WorldViewProj Matrix
|
||||
var worldViewProj = Matrix.RotationX((float)Yaw) * Matrix.RotationY((float)Pitch)
|
||||
* Matrix.RotationZ((float)Roll)
|
||||
* Matrix.Scaling(new Vector3(scaleX, scaleY, 1))
|
||||
* viewProj;
|
||||
var worldViewProj = Matrix.RotationX(Yaw) * Matrix.RotationY(Pitch)
|
||||
* Matrix.RotationZ(Roll)
|
||||
* Matrix.Scaling(new Vector3(scaleX, scaleY, 1))
|
||||
* viewProj;
|
||||
worldViewProj.Transpose();
|
||||
context.UpdateSubresource(ref worldViewProj, _constantBuffer);
|
||||
|
||||
@@ -112,21 +116,25 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
context.Draw(36, 0);
|
||||
|
||||
|
||||
_context.Flush();
|
||||
_context!.Flush();
|
||||
}
|
||||
}
|
||||
|
||||
private void Resize(PixelSize size)
|
||||
{
|
||||
Utilities.Dispose(ref _depthBuffer);
|
||||
|
||||
if (_device is null)
|
||||
return;
|
||||
|
||||
_depthBuffer = new Texture2D(_device,
|
||||
new Texture2DDescription()
|
||||
{
|
||||
Format = Format.D32_Float_S8X24_UInt,
|
||||
ArraySize = 1,
|
||||
MipLevels = 1,
|
||||
Width = (int)size.Width,
|
||||
Height = (int)size.Height,
|
||||
Width = size.Width,
|
||||
Height = size.Height,
|
||||
SampleDescription = new SampleDescription(1, 0),
|
||||
Usage = ResourceUsage.Default,
|
||||
BindFlags = BindFlags.DepthStencil,
|
||||
@@ -138,9 +146,9 @@ public class D3D11DemoControl : DrawingSurfaceDemoBase
|
||||
_depthView = new DepthStencilView(_device, _depthBuffer);
|
||||
|
||||
// Setup targets and viewport for rendering
|
||||
_device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, (int)size.Width, (int)size.Height, 0.0f, 1.0f));
|
||||
_device.ImmediateContext.Rasterizer.SetViewport(new Viewport(0, 0, size.Width, size.Height, 0.0f, 1.0f));
|
||||
|
||||
// Setup new projection matrix with correct aspect ratio
|
||||
_proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, (float)(size.Width / size.Height), 0.1f, 100.0f);
|
||||
_proj = Matrix.PerspectiveFovLH((float)Math.PI / 4.0f, size.Width / (float) size.Height, 0.1f, 100.0f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Numerics;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -13,12 +12,12 @@ public abstract class DrawingSurfaceDemoBase : Control, IGpuDemo
|
||||
{
|
||||
private CompositionSurfaceVisual? _visual;
|
||||
private Compositor? _compositor;
|
||||
private Action _update;
|
||||
private string _info;
|
||||
private readonly Action _update;
|
||||
private string _info = string.Empty;
|
||||
private bool _updateQueued;
|
||||
private bool _initialized;
|
||||
|
||||
protected CompositionDrawingSurface Surface { get; private set; }
|
||||
protected CompositionDrawingSurface? Surface { get; private set; }
|
||||
|
||||
public DrawingSurfaceDemoBase()
|
||||
{
|
||||
@@ -113,7 +112,7 @@ public abstract class DrawingSurfaceDemoBase : Control, IGpuDemo
|
||||
protected abstract void RenderFrame(PixelSize pixelSize);
|
||||
protected virtual bool SupportsDisco => false;
|
||||
|
||||
public void Update(GpuDemo parent, float yaw, float pitch, float roll, float disco)
|
||||
public void Update(GpuDemo? parent, float yaw, float pitch, float roll, float disco)
|
||||
{
|
||||
ParentControl = parent;
|
||||
if (ParentControl != null)
|
||||
|
||||
@@ -80,13 +80,13 @@ public class GpuDemo : UserControl
|
||||
set => SetAndRaise(DiscoVisibleProperty, ref _discoVisible, value);
|
||||
}
|
||||
|
||||
private IGpuDemo _demo;
|
||||
private IGpuDemo? _demo;
|
||||
|
||||
public static readonly DirectProperty<GpuDemo, IGpuDemo> DemoProperty =
|
||||
AvaloniaProperty.RegisterDirect<GpuDemo, IGpuDemo>("Demo", o => o.Demo,
|
||||
public static readonly DirectProperty<GpuDemo, IGpuDemo?> DemoProperty =
|
||||
AvaloniaProperty.RegisterDirect<GpuDemo, IGpuDemo?>("Demo", o => o.Demo,
|
||||
(o, v) => o._demo = v);
|
||||
|
||||
public IGpuDemo Demo
|
||||
public IGpuDemo? Demo
|
||||
{
|
||||
get => _demo;
|
||||
set => SetAndRaise(DemoProperty, ref _demo, value);
|
||||
@@ -102,7 +102,7 @@ public class GpuDemo : UserControl
|
||||
)
|
||||
{
|
||||
if (change.Property == DemoProperty)
|
||||
((IGpuDemo)change.OldValue)?.Update(null, 0, 0, 0, 0);
|
||||
((IGpuDemo?)change.OldValue)?.Update(null, 0, 0, 0, 0);
|
||||
_demo?.Update(this, Yaw, Pitch, Roll, Disco);
|
||||
}
|
||||
|
||||
@@ -112,5 +112,5 @@ public class GpuDemo : UserControl
|
||||
|
||||
public interface IGpuDemo
|
||||
{
|
||||
void Update(GpuDemo parent, float yaw, float pitch, float roll, float disco);
|
||||
void Update(GpuDemo? parent, float yaw, float pitch, float roll, float disco);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Avalonia.Vulkan
|
||||
private readonly CommandPool _commandPool;
|
||||
|
||||
private readonly List<VulkanCommandBuffer> _usedCommandBuffers = new();
|
||||
private object _lock = new object();
|
||||
private readonly object _lock = new();
|
||||
|
||||
public unsafe VulkanCommandBufferPool(Vk api, Device device, Queue queue, uint queueFamilyIndex)
|
||||
{
|
||||
@@ -167,7 +167,7 @@ namespace Avalonia.Vulkan
|
||||
ReadOnlySpan<PipelineStageFlags> waitDstStageMask = default,
|
||||
ReadOnlySpan<Semaphore> signalSemaphores = default,
|
||||
Fence? fence = null,
|
||||
KeyedMutexSubmitInfo keyedMutex = null)
|
||||
KeyedMutexSubmitInfo? keyedMutex = null)
|
||||
{
|
||||
EndRecording();
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ unsafe class VulkanContent : IDisposable
|
||||
{
|
||||
_context = context;
|
||||
var name = typeof(VulkanContent).Assembly.GetManifestResourceNames().First(x => x.Contains("teapot.bin"));
|
||||
using (var sr = new BinaryReader(typeof(VulkanContent).Assembly.GetManifestResourceStream(name)))
|
||||
using (var sr = new BinaryReader(typeof(VulkanContent).Assembly.GetManifestResourceStream(name)!))
|
||||
{
|
||||
var buf = new byte[sr.ReadInt32()];
|
||||
sr.Read(buf, 0, buf.Length);
|
||||
@@ -115,7 +115,7 @@ unsafe class VulkanContent : IDisposable
|
||||
{
|
||||
var name = typeof(VulkanContent).Assembly.GetManifestResourceNames()
|
||||
.First(x => x.Contains((fragment ? "frag" : "vert") + ".spirv"));
|
||||
using (var sr = typeof(VulkanContent).Assembly.GetManifestResourceStream(name))
|
||||
using (var sr = typeof(VulkanContent).Assembly.GetManifestResourceStream(name)!)
|
||||
{
|
||||
using (var mem = new MemoryStream())
|
||||
{
|
||||
@@ -158,7 +158,7 @@ unsafe class VulkanContent : IDisposable
|
||||
var commandBuffer = _context.Pool.CreateCommandBuffer();
|
||||
commandBuffer.BeginRecording();
|
||||
|
||||
_colorAttachment.TransitionLayout(commandBuffer.InternalHandle,
|
||||
_colorAttachment!.TransitionLayout(commandBuffer.InternalHandle,
|
||||
ImageLayout.Undefined, AccessFlags.None,
|
||||
ImageLayout.ColorAttachmentOptimal, AccessFlags.ColorAttachmentWriteBit);
|
||||
|
||||
@@ -251,9 +251,9 @@ unsafe class VulkanContent : IDisposable
|
||||
}
|
||||
};
|
||||
|
||||
api.CmdBlitImage(commandBuffer.InternalHandle, _colorAttachment.InternalHandle.Value,
|
||||
api.CmdBlitImage(commandBuffer.InternalHandle, _colorAttachment.InternalHandle,
|
||||
ImageLayout.TransferSrcOptimal,
|
||||
image.InternalHandle.Value, ImageLayout.TransferDstOptimal, 1, srcBlitRegion, Filter.Linear);
|
||||
image.InternalHandle, ImageLayout.TransferDstOptimal, 1, srcBlitRegion, Filter.Linear);
|
||||
|
||||
commandBuffer.Submit();
|
||||
}
|
||||
@@ -393,7 +393,7 @@ unsafe class VulkanContent : IDisposable
|
||||
|
||||
var view = Matrix4x4.CreateLookAt(new Vector3(25, 25, 25), new Vector3(), new Vector3(0, -1, 0));
|
||||
var projection =
|
||||
Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)((float)size.Width / size.Height),
|
||||
Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)size.Width / size.Height,
|
||||
0.01f, 1000);
|
||||
|
||||
_colorAttachment = new VulkanImage(_context, (uint)Format.R8G8B8A8Unorm, size, false);
|
||||
@@ -808,7 +808,7 @@ unsafe class VulkanContent : IDisposable
|
||||
|
||||
static Stopwatch St = Stopwatch.StartNew();
|
||||
private bool _isInit;
|
||||
private VulkanImage _colorAttachment;
|
||||
private VulkanImage? _colorAttachment;
|
||||
private DescriptorSet _descriptorSet;
|
||||
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)]
|
||||
|
||||
@@ -2,34 +2,31 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using Avalonia;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using Avalonia.Vulkan;
|
||||
using Silk.NET.Core;
|
||||
using Silk.NET.Core.Native;
|
||||
using Silk.NET.Vulkan;
|
||||
using Silk.NET.Vulkan.Extensions.EXT;
|
||||
using Silk.NET.Vulkan.Extensions.KHR;
|
||||
using SilkNetDemo;
|
||||
using SkiaSharp;
|
||||
using D3DDevice = SharpDX.Direct3D11.Device;
|
||||
using DxgiDevice = SharpDX.DXGI.Device;
|
||||
|
||||
namespace GpuInterop.VulkanDemo;
|
||||
|
||||
public unsafe class VulkanContext : IDisposable
|
||||
{
|
||||
public Vk Api { get; init; }
|
||||
public Instance Instance { get; init; }
|
||||
public PhysicalDevice PhysicalDevice { get; init; }
|
||||
public Device Device { get; init; }
|
||||
public Queue Queue { get; init; }
|
||||
public uint QueueFamilyIndex { get; init; }
|
||||
public VulkanCommandBufferPool Pool { get; init; }
|
||||
public GRContext GrContext { get; init; }
|
||||
public DescriptorPool DescriptorPool { get; init; }
|
||||
public D3DDevice? D3DDevice { get; init; }
|
||||
public required Vk Api { get; init; }
|
||||
public required Instance Instance { get; init; }
|
||||
public required PhysicalDevice PhysicalDevice { get; init; }
|
||||
public required Device Device { get; init; }
|
||||
public required Queue Queue { get; init; }
|
||||
public required uint QueueFamilyIndex { get; init; }
|
||||
public required VulkanCommandBufferPool Pool { get; init; }
|
||||
public required GRContext GrContext { get; init; }
|
||||
public required DescriptorPool DescriptorPool { get; init; }
|
||||
public required D3DDevice? D3DDevice { get; init; }
|
||||
|
||||
public static (VulkanContext? result, string info) TryCreate(ICompositionGpuInterop gpuInterop)
|
||||
{
|
||||
@@ -58,10 +55,8 @@ public unsafe class VulkanContext : IDisposable
|
||||
enabledExtensions.Add("VK_EXT_debug_utils");
|
||||
if (IsLayerAvailable(api, "VK_LAYER_KHRONOS_validation"))
|
||||
enabledLayers.Add("VK_LAYER_KHRONOS_validation");
|
||||
|
||||
|
||||
Instance vkInstance = default;
|
||||
Silk.NET.Vulkan.PhysicalDevice physicalDevice = default;
|
||||
|
||||
Device device = default;
|
||||
DescriptorPool descriptorPool = default;
|
||||
VulkanCommandBufferPool? pool = null;
|
||||
@@ -78,7 +73,7 @@ public unsafe class VulkanContext : IDisposable
|
||||
EnabledExtensionCount = pRequiredExtensions.UCount,
|
||||
PpEnabledLayerNames = pEnabledLayers,
|
||||
EnabledLayerCount = pEnabledLayers.UCount
|
||||
}, null, out vkInstance).ThrowOnError();
|
||||
}, null, out var vkInstance).ThrowOnError();
|
||||
|
||||
|
||||
if (api.TryGetInstanceExtension(vkInstance, out ExtDebugUtils debugUtils))
|
||||
@@ -95,7 +90,7 @@ public unsafe class VulkanContext : IDisposable
|
||||
PfnUserCallback = new PfnDebugUtilsMessengerCallbackEXT(LogCallback),
|
||||
};
|
||||
|
||||
debugUtils.CreateDebugUtilsMessenger(vkInstance, debugCreateInfo, null, out var messenger);
|
||||
debugUtils.CreateDebugUtilsMessenger(vkInstance, debugCreateInfo, null, out _);
|
||||
}
|
||||
|
||||
var requireDeviceExtensions = new List<string>
|
||||
@@ -158,11 +153,11 @@ public unsafe class VulkanContext : IDisposable
|
||||
else if (gpuInterop.DeviceUuid != null)
|
||||
{
|
||||
if (!new Span<byte>(physicalDeviceIDProperties.DeviceUuid, 16)
|
||||
.SequenceEqual(gpuInterop?.DeviceUuid))
|
||||
.SequenceEqual(gpuInterop.DeviceUuid))
|
||||
continue;
|
||||
}
|
||||
|
||||
physicalDevice = physicalDevices[c];
|
||||
var physicalDevice = physicalDevices[c];
|
||||
|
||||
var name = Marshal.PtrToStringAnsi(new IntPtr(physicalDeviceProperties2.Properties.DeviceName))!;
|
||||
|
||||
@@ -251,8 +246,7 @@ public unsafe class VulkanContext : IDisposable
|
||||
RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
d3dDevice = D3DMemoryHelper.CreateDeviceByLuid(
|
||||
new Span<byte>(physicalDeviceIDProperties.DeviceLuid, 8));
|
||||
|
||||
var dxgiDevice = d3dDevice?.QueryInterface<DxgiDevice>();
|
||||
|
||||
return (new VulkanContext
|
||||
{
|
||||
Api = api,
|
||||
|
||||
@@ -24,23 +24,23 @@ public unsafe class VulkanImage : IDisposable
|
||||
private ImageLayout _currentLayout;
|
||||
private AccessFlags _currentAccessFlags;
|
||||
private ImageUsageFlags _imageUsageFlags { get; }
|
||||
private ImageView? _imageView { get; set; }
|
||||
private ImageView _imageView { get; set; }
|
||||
private DeviceMemory _imageMemory { get; set; }
|
||||
private SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
|
||||
private readonly SharpDX.Direct3D11.Texture2D? _d3dTexture2D;
|
||||
|
||||
internal Image? InternalHandle { get; private set; }
|
||||
internal Image InternalHandle { get; private set; }
|
||||
internal Format Format { get; }
|
||||
internal ImageAspectFlags AspectFlags { get; private set; }
|
||||
internal ImageAspectFlags AspectFlags { get; }
|
||||
|
||||
public ulong Handle => InternalHandle?.Handle ?? 0;
|
||||
public ulong ViewHandle => _imageView?.Handle ?? 0;
|
||||
public ulong Handle => InternalHandle.Handle;
|
||||
public ulong ViewHandle => _imageView.Handle;
|
||||
public uint UsageFlags => (uint) _imageUsageFlags;
|
||||
public ulong MemoryHandle => _imageMemory.Handle;
|
||||
public DeviceMemory DeviceMemory => _imageMemory;
|
||||
public uint MipLevels { get; private set; }
|
||||
public uint MipLevels { get; }
|
||||
public Vk Api { get; }
|
||||
public PixelSize Size { get; }
|
||||
public ulong MemorySize { get; private set; }
|
||||
public ulong MemorySize { get; }
|
||||
public uint CurrentLayout => (uint) _currentLayout;
|
||||
|
||||
public VulkanImage(VulkanContext vk, uint format, PixelSize size,
|
||||
@@ -93,7 +93,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
.CreateImage(_device, imageCreateInfo, null, out var image).ThrowOnError();
|
||||
InternalHandle = image;
|
||||
|
||||
Api.GetImageMemoryRequirements(_device, InternalHandle.Value,
|
||||
Api.GetImageMemoryRequirements(_device, InternalHandle,
|
||||
out var memoryRequirements);
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
ImportMemoryWin32HandleInfoKHR handleImport = default;
|
||||
if (exportable && RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice, size, Format);
|
||||
_d3dTexture2D = D3DMemoryHelper.CreateMemoryHandle(vk.D3DDevice!, size, Format);
|
||||
using var dxgi = _d3dTexture2D.QueryInterface<SharpDX.DXGI.Resource1>();
|
||||
|
||||
handleImport = new ImportMemoryWin32HandleInfoKHR
|
||||
@@ -141,7 +141,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
|
||||
MemorySize = memoryRequirements.Size;
|
||||
|
||||
Api.BindImageMemory(_device, InternalHandle.Value, _imageMemory, 0).ThrowOnError();
|
||||
Api.BindImageMemory(_device, InternalHandle, _imageMemory, 0).ThrowOnError();
|
||||
var componentMapping = new ComponentMapping(
|
||||
ComponentSwizzle.Identity,
|
||||
ComponentSwizzle.Identity,
|
||||
@@ -155,7 +155,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
var imageViewCreateInfo = new ImageViewCreateInfo
|
||||
{
|
||||
SType = StructureType.ImageViewCreateInfo,
|
||||
Image = InternalHandle.Value,
|
||||
Image = InternalHandle,
|
||||
ViewType = ImageViewType.Type2D,
|
||||
Format = Format,
|
||||
Components = componentMapping,
|
||||
@@ -209,7 +209,7 @@ public unsafe class VulkanImage : IDisposable
|
||||
ImageLayout fromLayout, AccessFlags fromAccessFlags,
|
||||
ImageLayout destinationLayout, AccessFlags destinationAccessFlags)
|
||||
{
|
||||
VulkanMemoryHelper.TransitionLayout(Api, commandBuffer, InternalHandle.Value,
|
||||
VulkanMemoryHelper.TransitionLayout(Api, commandBuffer, InternalHandle,
|
||||
fromLayout,
|
||||
fromAccessFlags,
|
||||
destinationLayout, destinationAccessFlags,
|
||||
@@ -241,8 +241,8 @@ public unsafe class VulkanImage : IDisposable
|
||||
|
||||
public unsafe void Dispose()
|
||||
{
|
||||
Api.DestroyImageView(_device, _imageView.Value, null);
|
||||
Api.DestroyImage(_device, InternalHandle.Value, null);
|
||||
Api.DestroyImageView(_device, _imageView, null);
|
||||
Api.DestroyImage(_device, InternalHandle, null);
|
||||
Api.FreeMemory(_device, _imageMemory, null);
|
||||
|
||||
_imageView = default;
|
||||
|
||||
@@ -146,6 +146,6 @@ class VulkanSwapchainImage : ISwapchainImage
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
_lastPresent = _target.UpdateWithKeyedMutexAsync(_importedImage, 1, 0);
|
||||
else
|
||||
_lastPresent = _target.UpdateWithSemaphoresAsync(_importedImage, _renderCompletedSemaphore, _availableSemaphore);
|
||||
_lastPresent = _target.UpdateWithSemaphoresAsync(_importedImage, _renderCompletedSemaphore!, _availableSemaphore!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,23 +42,20 @@ namespace IntegrationTestApp
|
||||
private void InitializeViewMenu()
|
||||
{
|
||||
var mainTabs = this.Get<TabControl>("MainTabs");
|
||||
var viewMenu = (NativeMenuItem)NativeMenu.GetMenu(this).Items[1];
|
||||
var viewMenu = (NativeMenuItem?)NativeMenu.GetMenu(this)?.Items[1];
|
||||
|
||||
if (mainTabs.Items is not null)
|
||||
foreach (var tabItem in mainTabs.Items.Cast<TabItem>())
|
||||
{
|
||||
foreach (TabItem tabItem in mainTabs.Items)
|
||||
var menuItem = new NativeMenuItem
|
||||
{
|
||||
var menuItem = new NativeMenuItem
|
||||
{
|
||||
Header = (string)tabItem.Header!,
|
||||
ToolTip = (string)tabItem.Header!,
|
||||
IsChecked = tabItem.IsSelected,
|
||||
ToggleType = NativeMenuItemToggleType.Radio,
|
||||
};
|
||||
Header = (string?)tabItem.Header,
|
||||
ToolTip = (string?)tabItem.Header,
|
||||
IsChecked = tabItem.IsSelected,
|
||||
ToggleType = NativeMenuItemToggleType.Radio,
|
||||
};
|
||||
|
||||
menuItem.Click += (s, e) => tabItem.IsSelected = true;
|
||||
viewMenu?.Menu?.Items.Add(menuItem);
|
||||
}
|
||||
menuItem.Click += (_, _) => tabItem.IsSelected = true;
|
||||
viewMenu?.Menu?.Items.Add(menuItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +74,7 @@ namespace IntegrationTestApp
|
||||
var window = new ShowWindowTest
|
||||
{
|
||||
WindowStartupLocation = (WindowStartupLocation)locationComboBox.SelectedIndex,
|
||||
CanResize = canResizeCheckBox.IsChecked.Value,
|
||||
CanResize = canResizeCheckBox.IsChecked ?? false,
|
||||
};
|
||||
|
||||
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime)
|
||||
@@ -227,9 +224,9 @@ namespace IntegrationTestApp
|
||||
var gestureBorder2 = this.GetControl<Border>("GestureBorder2");
|
||||
var lastGesture = this.GetControl<TextBlock>("LastGesture");
|
||||
var resetGestures = this.GetControl<Button>("ResetGestures");
|
||||
gestureBorder.Tapped += (s, e) => lastGesture.Text = "Tapped";
|
||||
gestureBorder.Tapped += (_, _) => lastGesture.Text = "Tapped";
|
||||
|
||||
gestureBorder.DoubleTapped += (s, e) =>
|
||||
gestureBorder.DoubleTapped += (_, _) =>
|
||||
{
|
||||
lastGesture.Text = "DoubleTapped";
|
||||
|
||||
@@ -238,14 +235,14 @@ namespace IntegrationTestApp
|
||||
gestureBorder2.IsVisible = true;
|
||||
};
|
||||
|
||||
gestureBorder2.DoubleTapped += (s, e) =>
|
||||
gestureBorder2.DoubleTapped += (_, _) =>
|
||||
{
|
||||
lastGesture.Text = "DoubleTapped2";
|
||||
};
|
||||
|
||||
Gestures.AddRightTappedHandler(gestureBorder, (s, e) => lastGesture.Text = "RightTapped");
|
||||
Gestures.AddRightTappedHandler(gestureBorder, (_, _) => lastGesture.Text = "RightTapped");
|
||||
|
||||
resetGestures.Click += (s, e) =>
|
||||
resetGestures.Click += (_, _) =>
|
||||
{
|
||||
lastGesture.Text = string.Empty;
|
||||
gestureBorder.IsVisible = true;
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
#nullable enable
|
||||
|
||||
namespace Avalonia.Android
|
||||
{
|
||||
@@ -11,9 +7,9 @@ namespace Avalonia.Android
|
||||
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
|
||||
|
||||
private static AppBuilder? s_appBuilder;
|
||||
internal static object ViewContent;
|
||||
internal static object? ViewContent;
|
||||
|
||||
public object Content
|
||||
public object? Content
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -51,7 +47,7 @@ namespace Avalonia.Android
|
||||
View.Content = ViewContent;
|
||||
}
|
||||
|
||||
if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime)
|
||||
if (Avalonia.Application.Current?.ApplicationLifetime is SingleViewLifetime lifetime)
|
||||
{
|
||||
lifetime.View = View;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.Versioning;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Content.Res;
|
||||
using Android.OS;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
@@ -37,6 +36,7 @@ namespace Avalonia.Android
|
||||
ActivityResult?.Invoke(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("android23.0")]
|
||||
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
|
||||
{
|
||||
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
@@ -47,7 +47,8 @@ namespace Avalonia.Android
|
||||
|
||||
public abstract partial class AvaloniaMainActivity<TApp> : AvaloniaMainActivity where TApp : Application, new()
|
||||
{
|
||||
internal AvaloniaView View;
|
||||
internal AvaloniaView View { get; set; }
|
||||
|
||||
private GlobalLayoutListener _listener;
|
||||
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
@@ -68,9 +69,9 @@ namespace Avalonia.Android
|
||||
base.OnResume();
|
||||
|
||||
// Android only respects LayoutInDisplayCutoutMode value if it has been set once before window becomes visible.
|
||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
||||
if (OperatingSystem.IsAndroidVersionAtLeast(28) && Window is { Attributes: { } attributes })
|
||||
{
|
||||
Window.Attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||
attributes.LayoutInDisplayCutoutMode = LayoutInDisplayCutoutMode.ShortEdges;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +84,9 @@ namespace Avalonia.Android
|
||||
base.OnDestroy();
|
||||
}
|
||||
|
||||
class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
|
||||
private class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
|
||||
{
|
||||
private AvaloniaView _view;
|
||||
private readonly AvaloniaView _view;
|
||||
|
||||
public GlobalLayoutListener(AvaloniaView view)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Runtime.Versioning;
|
||||
using Android.Content;
|
||||
using Android.Content.Res;
|
||||
using Android.Runtime;
|
||||
@@ -46,6 +47,7 @@ namespace Avalonia.Android
|
||||
return _view.View.DispatchKeyEvent(e);
|
||||
}
|
||||
|
||||
[SupportedOSPlatform("android24.0")]
|
||||
public override void OnVisibilityAggregated(bool isVisible)
|
||||
{
|
||||
base.OnVisibilityAggregated(isVisible);
|
||||
|
||||
@@ -30,17 +30,25 @@ namespace Avalonia.Android.Platform
|
||||
{
|
||||
_displayEdgeToEdge = value;
|
||||
|
||||
if(Build.VERSION.SdkInt >= BuildVersionCodes.P)
|
||||
var window = _activity.Window;
|
||||
|
||||
if (OperatingSystem.IsAndroidVersionAtLeast(28) && window?.Attributes is { } attributes)
|
||||
{
|
||||
_activity.Window.Attributes.LayoutInDisplayCutoutMode = value ? LayoutInDisplayCutoutMode.ShortEdges : LayoutInDisplayCutoutMode.Default;
|
||||
attributes.LayoutInDisplayCutoutMode = value ? LayoutInDisplayCutoutMode.ShortEdges : LayoutInDisplayCutoutMode.Default;
|
||||
}
|
||||
|
||||
WindowCompat.SetDecorFitsSystemWindows(_activity.Window, !value);
|
||||
if (window is not null)
|
||||
{
|
||||
WindowCompat.SetDecorFitsSystemWindows(_activity.Window, !value);
|
||||
}
|
||||
|
||||
if(value)
|
||||
{
|
||||
_activity.Window.AddFlags(WindowManagerFlags.TranslucentStatus);
|
||||
_activity.Window.AddFlags(WindowManagerFlags.TranslucentNavigation);
|
||||
if (window is not null)
|
||||
{
|
||||
window.AddFlags(WindowManagerFlags.TranslucentStatus);
|
||||
window.AddFlags(WindowManagerFlags.TranslucentNavigation);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -57,14 +65,17 @@ namespace Avalonia.Android.Platform
|
||||
|
||||
_callback.InsetsManager = this;
|
||||
|
||||
ViewCompat.SetOnApplyWindowInsetsListener(_activity.Window.DecorView, this);
|
||||
if (_activity.Window is { } window)
|
||||
{
|
||||
ViewCompat.SetOnApplyWindowInsetsListener(window.DecorView, this);
|
||||
|
||||
ViewCompat.SetWindowInsetsAnimationCallback(_activity.Window.DecorView, _callback);
|
||||
ViewCompat.SetWindowInsetsAnimationCallback(window.DecorView, _callback);
|
||||
}
|
||||
|
||||
if(Build.VERSION.SdkInt < BuildVersionCodes.R)
|
||||
if (Build.VERSION.SdkInt < BuildVersionCodes.R)
|
||||
{
|
||||
_usesLegacyLayouts = true;
|
||||
_activity.Window.DecorView.ViewTreeObserver.AddOnGlobalLayoutListener(this);
|
||||
_activity.Window?.DecorView.ViewTreeObserver?.AddOnGlobalLayoutListener(this);
|
||||
}
|
||||
|
||||
DisplayEdgeToEdge = false;
|
||||
@@ -74,7 +85,7 @@ namespace Avalonia.Android.Platform
|
||||
{
|
||||
get
|
||||
{
|
||||
var insets = ViewCompat.GetRootWindowInsets(_activity.Window.DecorView);
|
||||
var insets = _activity.Window is { } window ? ViewCompat.GetRootWindowInsets(window.DecorView) : null;
|
||||
|
||||
if (insets != null)
|
||||
{
|
||||
@@ -127,7 +138,7 @@ namespace Avalonia.Android.Platform
|
||||
|
||||
return compat.AppearanceLightStatusBars ? Controls.Platform.SystemBarTheme.Light : Controls.Platform.SystemBarTheme.Dark;
|
||||
}
|
||||
catch (Exception _)
|
||||
catch (Exception)
|
||||
{
|
||||
return Controls.Platform.SystemBarTheme.Light;
|
||||
}
|
||||
@@ -136,8 +147,6 @@ namespace Avalonia.Android.Platform
|
||||
{
|
||||
_statusBarTheme = value;
|
||||
|
||||
var isDefault = _statusBarTheme == null;
|
||||
|
||||
if (!_topLevel.View.IsShown)
|
||||
{
|
||||
return;
|
||||
@@ -150,7 +159,7 @@ namespace Avalonia.Android.Platform
|
||||
_isDefaultSystemBarLightTheme = compat.AppearanceLightStatusBars;
|
||||
}
|
||||
|
||||
if (value == null && _isDefaultSystemBarLightTheme != null)
|
||||
if (value == null)
|
||||
{
|
||||
value = (bool)_isDefaultSystemBarLightTheme ? Controls.Platform.SystemBarTheme.Light : Controls.Platform.SystemBarTheme.Dark;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform;
|
||||
|
||||
@@ -6,7 +8,7 @@ namespace Avalonia.Android.Platform
|
||||
{
|
||||
internal class AndroidSystemNavigationManagerImpl : ISystemNavigationManagerImpl
|
||||
{
|
||||
public event EventHandler<RoutedEventArgs> BackRequested;
|
||||
public event EventHandler<RoutedEventArgs>? BackRequested;
|
||||
|
||||
public AndroidSystemNavigationManagerImpl(IActivityNavigationService? navigationService)
|
||||
{
|
||||
@@ -16,7 +18,7 @@ namespace Avalonia.Android.Platform
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBackRequested(object sender, AndroidBackRequestedEventArgs e)
|
||||
private void OnBackRequested(object? sender, AndroidBackRequestedEventArgs e)
|
||||
{
|
||||
var routedEventArgs = new RoutedEventArgs();
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Android.Content;
|
||||
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.Platform;
|
||||
|
||||
@@ -10,34 +10,34 @@ namespace Avalonia.Android.Platform
|
||||
{
|
||||
internal class ClipboardImpl : IClipboard
|
||||
{
|
||||
private ClipboardManager? _clipboardManager;
|
||||
private readonly ClipboardManager? _clipboardManager;
|
||||
|
||||
internal ClipboardImpl(ClipboardManager? value)
|
||||
{
|
||||
_clipboardManager = value;
|
||||
}
|
||||
|
||||
public Task<string> GetTextAsync()
|
||||
public Task<string?> GetTextAsync()
|
||||
{
|
||||
if (_clipboardManager?.HasPrimaryClip == true)
|
||||
{
|
||||
return Task.FromResult<string>(_clipboardManager.PrimaryClip.GetItemAt(0).Text);
|
||||
return Task.FromResult(_clipboardManager.PrimaryClip?.GetItemAt(0)?.Text);
|
||||
}
|
||||
|
||||
return Task.FromResult<string>(null);
|
||||
return Task.FromResult<string?>(null);
|
||||
}
|
||||
|
||||
public Task SetTextAsync(string text)
|
||||
public Task SetTextAsync(string? text)
|
||||
{
|
||||
if(_clipboardManager == null)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
ClipData clip = ClipData.NewPlainText("text", text);
|
||||
var clip = ClipData.NewPlainText("text", text);
|
||||
_clipboardManager.PrimaryClip = clip;
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task ClearAsync()
|
||||
@@ -49,13 +49,13 @@ namespace Avalonia.Android.Platform
|
||||
|
||||
_clipboardManager.PrimaryClip = null;
|
||||
|
||||
return Task.FromResult<object>(null);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task SetDataObjectAsync(IDataObject data) => throw new PlatformNotSupportedException();
|
||||
|
||||
public Task<string[]> GetFormatsAsync() => throw new PlatformNotSupportedException();
|
||||
|
||||
public Task<object> GetDataAsync(string format) => throw new PlatformNotSupportedException();
|
||||
public Task<object?> GetDataAsync(string format) => throw new PlatformNotSupportedException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
|
||||
{
|
||||
activity.SetTranslucent(true);
|
||||
SetBlurBehind(activity, 0);
|
||||
activity.Window.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
|
||||
activity.Window?.SetBackgroundDrawable(new ColorDrawable(Color.Transparent));
|
||||
}
|
||||
}
|
||||
else if (level == WindowTransparencyLevel.Blur)
|
||||
@@ -448,8 +448,6 @@ namespace Avalonia.Android.Platform.SkiaPlatform
|
||||
{
|
||||
private readonly AvaloniaInputConnection _inputConnection;
|
||||
|
||||
public event EventHandler<int> SelectionChanged;
|
||||
|
||||
public EditableWrapper(AvaloniaInputConnection inputConnection)
|
||||
{
|
||||
_inputConnection = inputConnection;
|
||||
|
||||
+4
-4
@@ -55,7 +55,7 @@ namespace Avalonia.Android.Platform.Specific.Helpers
|
||||
var keySymbol = GetKeySymbol(e.UnicodeChar, physicalKey);
|
||||
|
||||
var rawKeyEvent = new RawKeyEventArgs(
|
||||
AndroidKeyboardDevice.Instance,
|
||||
AndroidKeyboardDevice.Instance!,
|
||||
Convert.ToUInt64(e.EventTime),
|
||||
_view.InputRoot,
|
||||
e.Action == KeyEventActions.Down ? RawKeyEventType.KeyDown : RawKeyEventType.KeyUp,
|
||||
@@ -64,18 +64,18 @@ namespace Avalonia.Android.Platform.Specific.Helpers
|
||||
physicalKey,
|
||||
keySymbol);
|
||||
|
||||
_view.Input(rawKeyEvent);
|
||||
_view.Input?.Invoke(rawKeyEvent);
|
||||
|
||||
if ((e.Action == KeyEventActions.Down && e.UnicodeChar >= 32)
|
||||
|| unicodeTextInput != null)
|
||||
{
|
||||
var rawTextEvent = new RawTextInputEventArgs(
|
||||
AndroidKeyboardDevice.Instance,
|
||||
AndroidKeyboardDevice.Instance!,
|
||||
Convert.ToUInt64(e.EventTime),
|
||||
_view.InputRoot,
|
||||
unicodeTextInput ?? Convert.ToChar(e.UnicodeChar).ToString()
|
||||
);
|
||||
_view.Input(rawTextEvent);
|
||||
_view.Input?.Invoke(rawTextEvent);
|
||||
}
|
||||
|
||||
if (e.Action == KeyEventActions.Up)
|
||||
|
||||
@@ -172,29 +172,29 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
|
||||
{
|
||||
}
|
||||
|
||||
public async Task<IStorageFile?> CreateFileAsync(string name)
|
||||
public Task<IStorageFile?> CreateFileAsync(string name)
|
||||
{
|
||||
var mimeType = MimeTypeMap.Singleton?.GetMimeTypeFromExtension(MimeTypeMap.GetFileExtensionFromUrl(name)) ?? "application/octet-stream";
|
||||
var newFile = Document.CreateFile(mimeType, name);
|
||||
var newFile = Document?.CreateFile(mimeType, name);
|
||||
|
||||
if(newFile == null)
|
||||
{
|
||||
return null;
|
||||
return Task.FromResult<IStorageFile?>(null);
|
||||
}
|
||||
|
||||
return new AndroidStorageFile(Activity, newFile.Uri, this);
|
||||
return Task.FromResult<IStorageFile?>(new AndroidStorageFile(Activity, newFile.Uri, this));
|
||||
}
|
||||
|
||||
public async Task<IStorageFolder?> CreateFolderAsync(string name)
|
||||
public Task<IStorageFolder?> CreateFolderAsync(string name)
|
||||
{
|
||||
var newFolder = Document?.CreateDirectory(name);
|
||||
|
||||
if (newFolder == null)
|
||||
{
|
||||
return null;
|
||||
return Task.FromResult<IStorageFolder?>(null);
|
||||
}
|
||||
|
||||
return new AndroidStorageFolder(Activity, newFolder.Uri, false, this, PermissionRoot);
|
||||
return Task.FromResult<IStorageFolder?>(new AndroidStorageFolder(Activity, newFolder.Uri, false, this, PermissionRoot));
|
||||
}
|
||||
|
||||
public override async Task DeleteAsync()
|
||||
@@ -286,15 +286,15 @@ internal class AndroidStorageFolder : AndroidStorageItem, IStorageBookmarkFolder
|
||||
|
||||
return null;
|
||||
|
||||
async Task<AndroidStorageFolder?> MoveRecursively(AndroidStorageFolder storageFolder, AndroidStorageFolder destination)
|
||||
static async Task<AndroidStorageFolder?> MoveRecursively(AndroidStorageFolder storageFolder, AndroidStorageFolder destination)
|
||||
{
|
||||
destination = await destination.CreateFolderAsync(storageFolder.Name) as AndroidStorageFolder;
|
||||
|
||||
if (destination == null)
|
||||
if (await destination.CreateFolderAsync(storageFolder.Name) is not AndroidStorageFolder newDestination)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
destination = newDestination;
|
||||
|
||||
await foreach (var file in storageFolder.GetItemsAsync())
|
||||
{
|
||||
if (file is AndroidStorageFolder folder)
|
||||
@@ -477,25 +477,32 @@ internal sealed class AndroidStorageFile : AndroidStorageItem, IStorageBookmarkF
|
||||
|
||||
if (Activity != null && destination is AndroidStorageFolder storageFolder)
|
||||
{
|
||||
if (Build.VERSION.SdkInt >= BuildVersionCodes.N)
|
||||
AndroidUri? movedUri = null;
|
||||
|
||||
if (OperatingSystem.IsAndroidVersionAtLeast(24))
|
||||
{
|
||||
try
|
||||
{
|
||||
var uri = DocumentsContract.MoveDocument(Activity.ContentResolver!, Uri, ((await GetParentAsync()) as AndroidStorageFolder)!.Uri, storageFolder.Document!.Uri);
|
||||
|
||||
return new AndroidStorageFile(Activity, uri, storageFolder);
|
||||
if (Activity.ContentResolver is { } contentResolver &&
|
||||
storageFolder.Document?.Uri is { } targetParentUri &&
|
||||
await GetParentAsync() is AndroidStorageFolder parentFolder)
|
||||
{
|
||||
movedUri = DocumentsContract.MoveDocument(contentResolver, Uri, parentFolder.Uri, targetParentUri);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
catch (Exception)
|
||||
{
|
||||
// There are many reason why DocumentContract will fail to move a file. We fallback to copying.
|
||||
return await MoveFileByCopy();
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
if (movedUri is not null)
|
||||
{
|
||||
return await MoveFileByCopy();
|
||||
return new AndroidStorageFile(Activity, movedUri, storageFolder);
|
||||
}
|
||||
|
||||
return await MoveFileByCopy();
|
||||
}
|
||||
|
||||
async Task<AndroidStorageFile?> MoveFileByCopy()
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>net6.0-tizen</TargetFrameworks>
|
||||
<TargetFramework>net6.0-tizen</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
|
||||
|
||||
@@ -3,11 +3,9 @@ using Avalonia.Controls.Embedding;
|
||||
using Avalonia.Controls.Platform;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.TextInput;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using Avalonia.Rendering.Composition.Server;
|
||||
using Avalonia.Threading;
|
||||
using Tizen.NUI;
|
||||
using Tizen.NUI.BaseComponents;
|
||||
|
||||
@@ -22,21 +20,32 @@ public class NuiAvaloniaView : GLView, ITizenView, ITextInputMethodImpl
|
||||
private readonly NuiTouchHandler _touchHandler;
|
||||
private readonly NuiAvaloniaViewTextEditable _textEditor;
|
||||
private TizenRenderTimer? _renderTimer;
|
||||
private TopLevelImpl _topLevelImpl;
|
||||
private EmbeddableControlRoot _topLevel;
|
||||
private TouchDevice _device = new();
|
||||
private ServerCompositionTarget _compositionTargetServer;
|
||||
private TopLevelImpl? _topLevelImpl;
|
||||
private EmbeddableControlRoot? _topLevel;
|
||||
private readonly TouchDevice _device = new();
|
||||
private ServerCompositionTarget? _compositionTargetServer;
|
||||
private IInputRoot? _inputRoot;
|
||||
|
||||
public IInputRoot InputRoot { get; set; }
|
||||
public INativeControlHostImpl NativeControlHost { get; }
|
||||
internal TopLevelImpl TopLevelImpl => _topLevelImpl;
|
||||
public double Scaling => 1;
|
||||
public Size ClientSize => new(Size.Width, Size.Height);
|
||||
|
||||
public IInputRoot InputRoot
|
||||
{
|
||||
get => _inputRoot ?? throw new InvalidOperationException($"{nameof(InputRoot)} hasn't been set");
|
||||
set => _inputRoot = value;
|
||||
}
|
||||
|
||||
private TopLevel TopLevel
|
||||
=> _topLevel ?? throw new InvalidOperationException($"{nameof(NuiAvaloniaView)} hasn't been initialized");
|
||||
|
||||
internal TopLevelImpl TopLevelImpl
|
||||
=> _topLevelImpl ?? throw new InvalidOperationException($"{nameof(NuiAvaloniaView)} hasn't been initialized");
|
||||
|
||||
public Control? Content
|
||||
{
|
||||
get => _topLevel.Content as Control;
|
||||
set => _topLevel.Content = value;
|
||||
get => TopLevel.Content as Control;
|
||||
set => TopLevel.Content = value;
|
||||
}
|
||||
|
||||
internal NuiAvaloniaViewTextEditable TextEditor => _textEditor;
|
||||
@@ -44,7 +53,7 @@ public class NuiAvaloniaView : GLView, ITizenView, ITextInputMethodImpl
|
||||
|
||||
#region Setup
|
||||
|
||||
public event Action OnSurfaceInit;
|
||||
public event Action? OnSurfaceInit;
|
||||
|
||||
public NuiAvaloniaView() : base(ColorFormat.RGBA8888)
|
||||
{
|
||||
@@ -73,7 +82,7 @@ public class NuiAvaloniaView : GLView, ITizenView, ITextInputMethodImpl
|
||||
|
||||
private int GlRenderFrame()
|
||||
{
|
||||
if (_renderTimer == null || _topLevel == null)
|
||||
if (_renderTimer == null || _compositionTargetServer == null)
|
||||
return 0;
|
||||
|
||||
var rev = _compositionTargetServer.Revision;
|
||||
@@ -141,13 +150,13 @@ public class NuiAvaloniaView : GLView, ITizenView, ITextInputMethodImpl
|
||||
|
||||
private bool OnTouchEvent(object source, TouchEventArgs e)
|
||||
{
|
||||
_touchHandler?.Handle(e);
|
||||
_touchHandler.Handle(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool OnWheelEvent(object source, WheelEventArgs e)
|
||||
{
|
||||
_touchHandler?.Handle(e);
|
||||
_touchHandler.Handle(e);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -169,9 +178,9 @@ public class NuiAvaloniaView : GLView, ITizenView, ITextInputMethodImpl
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_topLevel.StopRendering();
|
||||
_topLevel.Dispose();
|
||||
_topLevelImpl.Dispose();
|
||||
_topLevel?.StopRendering();
|
||||
_topLevel?.Dispose();
|
||||
_topLevelImpl?.Dispose();
|
||||
_device.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
|
||||
@@ -20,9 +20,7 @@ internal class NuiAvaloniaViewTextEditable
|
||||
|
||||
public bool IsActive => _client != null && _keyboardPresented;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
public NuiAvaloniaViewTextEditable(NuiAvaloniaView avaloniaView)
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
{
|
||||
_avaloniaView = avaloniaView;
|
||||
_singleLineTextInput = new NuiSingleLineTextInput
|
||||
|
||||
@@ -54,7 +54,7 @@ class GlContext : IGlContext
|
||||
|
||||
public bool IsSharedWith(IGlContext context) => true;
|
||||
public bool CanCreateSharedContext => true;
|
||||
public IGlContext CreateSharedContext(IEnumerable<GlVersion> preferredVersions = null)
|
||||
public IGlContext CreateSharedContext(IEnumerable<GlVersion>? preferredVersions = null)
|
||||
{
|
||||
return this;
|
||||
}
|
||||
@@ -78,7 +78,7 @@ class GlContext : IGlContext
|
||||
}
|
||||
}
|
||||
|
||||
public object TryGetFeature(Type featureType) => null;
|
||||
public object? TryGetFeature(Type featureType) => null;
|
||||
|
||||
public IntPtr GetProcAddress(string procName)
|
||||
{
|
||||
|
||||
@@ -3,7 +3,6 @@ using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Tizen.NUI;
|
||||
using Window = Tizen.NUI.Window;
|
||||
using Avalonia.Logging;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Avalonia.Tizen;
|
||||
|
||||
@@ -23,7 +22,7 @@ public class NuiTizenApplication<TApp> : NUIApplication
|
||||
View = view;
|
||||
}
|
||||
|
||||
public Control MainView
|
||||
public Control? MainView
|
||||
{
|
||||
get => View.Content;
|
||||
set => View.Content = value;
|
||||
@@ -37,9 +36,7 @@ public class NuiTizenApplication<TApp> : NUIApplication
|
||||
Logger.TryGet(LogEventLevel.Debug, LogKey)?.Log(null, "Creating application");
|
||||
|
||||
base.OnCreate();
|
||||
#pragma warning disable CS8601 // Possible null reference assignment.
|
||||
TizenThreadingInterface.MainloopContext = SynchronizationContext.Current;
|
||||
#pragma warning restore CS8601 // Possible null reference assignment.
|
||||
TizenThreadingInterface.MainloopContext = SynchronizationContext.Current!;
|
||||
|
||||
Logger.TryGet(LogEventLevel.Debug, LogKey)?.Log(null, "Setup view");
|
||||
_lifetime = new SingleViewLifetime(new NuiAvaloniaView());
|
||||
@@ -50,7 +47,7 @@ public class NuiTizenApplication<TApp> : NUIApplication
|
||||
|
||||
Window.Instance.RenderingBehavior = RenderingBehaviorType.Continuously;
|
||||
Window.Instance.GetDefaultLayer().Add(_lifetime.View);
|
||||
Window.Instance.KeyEvent += (s, e) => _lifetime?.View?.KeyboardHandler.Handle(e);
|
||||
Window.Instance.KeyEvent += (_, e) => _lifetime?.View.KeyboardHandler.Handle(e);
|
||||
}
|
||||
|
||||
private void ContinueSetupApplication()
|
||||
@@ -64,10 +61,10 @@ public class NuiTizenApplication<TApp> : NUIApplication
|
||||
{
|
||||
CustomizeAppBuilder(builder);
|
||||
|
||||
builder.AfterSetup(_ => _lifetime.View.Initialise());
|
||||
builder.AfterSetup(_ => _lifetime!.View.Initialise());
|
||||
|
||||
Logger.TryGet(LogEventLevel.Debug, LogKey)?.Log(null, "Setup lifetime");
|
||||
builder.SetupWithLifetime(_lifetime);
|
||||
builder.SetupWithLifetime(_lifetime!);
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using Tizen.Applications;
|
||||
using Tizen.Security;
|
||||
|
||||
@@ -33,7 +32,7 @@ internal class Permissions
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPrivilegeDeclared(string tizenPrivilege)
|
||||
public static bool IsPrivilegeDeclared(string? tizenPrivilege)
|
||||
{
|
||||
var tizenPrivileges = tizenPrivilege;
|
||||
|
||||
@@ -48,21 +47,21 @@ internal class Permissions
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void EnsureDeclared(params Privilege[] requiredPrivileges)
|
||||
public static void EnsureDeclared(params Privilege[]? requiredPrivileges)
|
||||
{
|
||||
if (requiredPrivileges?.Any() != true)
|
||||
return;
|
||||
|
||||
foreach (var (tizenPrivilege, isRuntime) in requiredPrivileges)
|
||||
foreach (var (tizenPrivilege, _) in requiredPrivileges)
|
||||
{
|
||||
if (!IsPrivilegeDeclared(tizenPrivilege))
|
||||
throw new SecurityException($"You need to declare the privilege: `{tizenPrivilege}` in your tizen-manifest.xml");
|
||||
}
|
||||
}
|
||||
|
||||
public static Task<bool> CheckPrivilegeAsync(params Privilege[] requiredPrivileges) => CheckPrivilegeAsync(requiredPrivileges, false);
|
||||
public static Task<bool> RequestPrivilegeAsync(params Privilege[] requiredPrivileges) => CheckPrivilegeAsync(requiredPrivileges, true);
|
||||
private static async Task<bool> CheckPrivilegeAsync(Privilege[] requiredPrivileges, bool ask)
|
||||
public static Task<bool> CheckPrivilegeAsync(params Privilege[]? requiredPrivileges) => CheckPrivilegeAsync(requiredPrivileges, false);
|
||||
public static Task<bool> RequestPrivilegeAsync(params Privilege[]? requiredPrivileges) => CheckPrivilegeAsync(requiredPrivileges, true);
|
||||
private static async Task<bool> CheckPrivilegeAsync(Privilege[]? requiredPrivileges, bool ask)
|
||||
{
|
||||
var ret = global::Tizen.System.Information.TryGetValue("http://tizen.org/feature/profile", out string profile);
|
||||
if (!ret || (ret && (!profile.Equals("mobile") || !profile.Equals("wearable"))))
|
||||
@@ -77,7 +76,7 @@ internal class Permissions
|
||||
|
||||
var tizenPrivileges = requiredPrivileges.Where(p => p.IsRuntime);
|
||||
|
||||
foreach (var (tizenPrivilege, isRuntime) in tizenPrivileges)
|
||||
foreach (var (tizenPrivilege, _) in tizenPrivileges)
|
||||
{
|
||||
var checkResult = PrivacyPrivilegeManager.CheckPermission(tizenPrivilege);
|
||||
if (checkResult == CheckResult.Ask)
|
||||
@@ -87,16 +86,21 @@ internal class Permissions
|
||||
var tcs = new TaskCompletionSource<bool>();
|
||||
PrivacyPrivilegeManager.GetResponseContext(tizenPrivilege)
|
||||
.TryGetTarget(out var context);
|
||||
void OnResponseFetched(object sender, RequestResponseEventArgs e)
|
||||
|
||||
void OnResponseFetched(object? sender, RequestResponseEventArgs e)
|
||||
{
|
||||
tcs.TrySetResult(e.result == RequestResult.AllowForever);
|
||||
}
|
||||
context.ResponseFetched += OnResponseFetched;
|
||||
PrivacyPrivilegeManager.RequestPermission(tizenPrivilege);
|
||||
var result = await tcs.Task;
|
||||
context.ResponseFetched -= OnResponseFetched;
|
||||
if (result)
|
||||
continue;
|
||||
|
||||
if (context != null)
|
||||
{
|
||||
context.ResponseFetched += OnResponseFetched;
|
||||
PrivacyPrivilegeManager.RequestPermission(tizenPrivilege);
|
||||
var result = await tcs.Task;
|
||||
context.ResponseFetched -= OnResponseFetched;
|
||||
if (result)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ internal class WindowingPlatformStub : IWindowingPlatform
|
||||
|
||||
public IWindowImpl CreateEmbeddableWindow() => throw new NotSupportedException();
|
||||
|
||||
public ITrayIconImpl CreateTrayIcon() => null;
|
||||
public ITrayIconImpl? CreateTrayIcon() => null;
|
||||
}
|
||||
|
||||
internal class PlatformIconLoaderStub : IPlatformIconLoader
|
||||
|
||||
@@ -1,21 +1,33 @@
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.OpenGL.Egl;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Rendering;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using Avalonia.Tizen.Platform.Input;
|
||||
using Avalonia.Tizen.Platform;
|
||||
using Avalonia.Threading;
|
||||
|
||||
namespace Avalonia.Tizen;
|
||||
|
||||
internal class TizenPlatform
|
||||
{
|
||||
public static readonly TizenPlatform Instance = new();
|
||||
internal static NuiGlPlatform GlPlatform { get; set; }
|
||||
internal static Compositor Compositor { get; private set; }
|
||||
internal static TizenThreadingInterface ThreadingInterface { get; private set; } = new();
|
||||
|
||||
private static NuiGlPlatform? s_glPlatform;
|
||||
private static Compositor? s_compositor;
|
||||
|
||||
internal static NuiGlPlatform GlPlatform
|
||||
{
|
||||
get => s_glPlatform ?? throw new InvalidOperationException($"{nameof(TizenPlatform)} hasn't been initialized");
|
||||
private set => s_glPlatform = value;
|
||||
}
|
||||
|
||||
internal static Compositor Compositor
|
||||
{
|
||||
get => s_compositor ?? throw new InvalidOperationException($"{nameof(TizenPlatform)} hasn't been initialized");
|
||||
private set => s_compositor = value;
|
||||
}
|
||||
|
||||
internal static TizenThreadingInterface ThreadingInterface { get; } = new();
|
||||
|
||||
public static void Initialize()
|
||||
{
|
||||
|
||||
@@ -7,9 +7,13 @@ internal class TizenThreadingInterface : IPlatformThreadingInterface
|
||||
internal event Action? TickExecuted;
|
||||
private bool _signaled;
|
||||
|
||||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
internal static SynchronizationContext MainloopContext { get; set; }
|
||||
#pragma warning restore CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable.
|
||||
private static SynchronizationContext? s_mainloopContext;
|
||||
|
||||
internal static SynchronizationContext MainloopContext
|
||||
{
|
||||
get => s_mainloopContext ?? throw new InvalidOperationException($"{nameof(MainloopContext)} hasn't been set");
|
||||
set => s_mainloopContext = value;
|
||||
}
|
||||
|
||||
public IDisposable StartTimer(DispatcherPriority priority, TimeSpan interval, Action tick)
|
||||
{
|
||||
|
||||
@@ -110,7 +110,7 @@ internal class TopLevelImpl : ITopLevelImpl
|
||||
internal void TextInput(string text)
|
||||
{
|
||||
if (Input == null) return;
|
||||
var args = new RawTextInputEventArgs(TizenKeyboardDevice.Instance, (ulong)DateTime.Now.Ticks, _view.InputRoot, text);
|
||||
var args = new RawTextInputEventArgs(TizenKeyboardDevice.Instance!, (ulong)DateTime.Now.Ticks, _view.InputRoot, text);
|
||||
|
||||
Input(args);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Controls;
|
||||
@@ -12,7 +14,6 @@ using Avalonia.Input.TextInput;
|
||||
using Avalonia.iOS.Storage;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Rendering;
|
||||
using Avalonia.Rendering.Composition;
|
||||
using CoreAnimation;
|
||||
using Foundation;
|
||||
@@ -25,12 +26,15 @@ namespace Avalonia.iOS
|
||||
{
|
||||
public partial class AvaloniaView : UIView, ITextInputMethodImpl
|
||||
{
|
||||
internal IInputRoot InputRoot { get; private set; }
|
||||
private TopLevelImpl _topLevelImpl;
|
||||
private EmbeddableControlRoot _topLevel;
|
||||
private TouchHandler _touches;
|
||||
private TextInputMethodClient _client;
|
||||
private IAvaloniaViewController _controller;
|
||||
internal IInputRoot InputRoot
|
||||
=> _inputRoot ?? throw new InvalidOperationException($"{nameof(IWindowImpl.SetInputRoot)} must have been called");
|
||||
|
||||
private readonly TopLevelImpl _topLevelImpl;
|
||||
private readonly EmbeddableControlRoot _topLevel;
|
||||
private readonly TouchHandler _touches;
|
||||
private TextInputMethodClient? _client;
|
||||
private IAvaloniaViewController? _controller;
|
||||
private IInputRoot? _inputRoot;
|
||||
|
||||
public AvaloniaView()
|
||||
{
|
||||
@@ -60,7 +64,7 @@ namespace Avalonia.iOS
|
||||
public override bool CanResignFirstResponder => true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void TraitCollectionDidChange(UITraitCollection previousTraitCollection)
|
||||
public override void TraitCollectionDidChange(UITraitCollection? previousTraitCollection)
|
||||
{
|
||||
base.TraitCollectionDidChange(previousTraitCollection);
|
||||
|
||||
@@ -91,7 +95,7 @@ namespace Avalonia.iOS
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
internal readonly InsetsManager _insetsManager;
|
||||
private readonly ClipboardImpl _clipboard;
|
||||
private IDisposable _paddingInsets;
|
||||
private IDisposable? _paddingInsets;
|
||||
|
||||
public AvaloniaView View => _view;
|
||||
|
||||
@@ -101,17 +105,17 @@ namespace Avalonia.iOS
|
||||
_nativeControlHost = new NativeControlHostImpl(view);
|
||||
_storageProvider = new IOSStorageProvider(view);
|
||||
_insetsManager = new InsetsManager(view);
|
||||
_insetsManager.DisplayEdgeToEdgeChanged += (sender, edgeToEdge) =>
|
||||
_insetsManager.DisplayEdgeToEdgeChanged += (_, edgeToEdge) =>
|
||||
{
|
||||
// iOS doesn't add any paddings/margins to the application by itself.
|
||||
// Application is fully responsible for safe area paddings.
|
||||
// So, unlikely to android, we need to "fake" safe area insets when edge to edge is disabled.
|
||||
// So, unlikely to android, we need to "fake" safe area insets when edge to edge is disabled.
|
||||
_paddingInsets?.Dispose();
|
||||
if (!edgeToEdge)
|
||||
if (!edgeToEdge && view._controller is { } controller)
|
||||
{
|
||||
_paddingInsets = view._topLevel.SetValue(
|
||||
TemplatedControl.PaddingProperty,
|
||||
view._controller.SafeAreaPadding,
|
||||
controller.SafeAreaPadding,
|
||||
BindingPriority.Style); // lower priority, so it can be redefined by user
|
||||
}
|
||||
};
|
||||
@@ -132,19 +136,19 @@ namespace Avalonia.iOS
|
||||
|
||||
public void SetInputRoot(IInputRoot inputRoot)
|
||||
{
|
||||
_view.InputRoot = inputRoot;
|
||||
_view._inputRoot = inputRoot;
|
||||
}
|
||||
|
||||
public Point PointToClient(PixelPoint point) => new Point(point.X, point.Y);
|
||||
|
||||
public PixelPoint PointToScreen(Point point) => new PixelPoint((int)point.X, (int)point.Y);
|
||||
|
||||
public void SetCursor(ICursorImpl _)
|
||||
public void SetCursor(ICursorImpl? cursor)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
public IPopupImpl CreatePopup()
|
||||
public IPopupImpl? CreatePopup()
|
||||
{
|
||||
// In-window popups
|
||||
return null;
|
||||
@@ -158,18 +162,16 @@ namespace Avalonia.iOS
|
||||
public Size ClientSize => new Size(_view.Bounds.Width, _view.Bounds.Height);
|
||||
public Size? FrameSize => null;
|
||||
public double RenderScaling => _view.ContentScaleFactor;
|
||||
public IEnumerable<object> Surfaces { get; set; }
|
||||
public Action<RawInputEventArgs> Input { get; set; }
|
||||
public Action<Rect> Paint { get; set; }
|
||||
public Action<Size, WindowResizeReason> Resized { get; set; }
|
||||
public Action<double> ScalingChanged { get; set; }
|
||||
public Action<WindowTransparencyLevel> TransparencyLevelChanged { get; set; }
|
||||
public Action Closed { get; set; }
|
||||
public IEnumerable<object> Surfaces { get; set; } = Array.Empty<object>();
|
||||
public Action<RawInputEventArgs>? Input { get; set; }
|
||||
public Action<Rect>? Paint { get; set; }
|
||||
public Action<Size, WindowResizeReason>? Resized { get; set; }
|
||||
public Action<double>? ScalingChanged { get; set; }
|
||||
public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
|
||||
public Action? Closed { get; set; }
|
||||
|
||||
public Action LostFocus { get; set; }
|
||||
public Action? LostFocus { get; set; }
|
||||
|
||||
// legacy no-op
|
||||
public IMouseDevice MouseDevice { get; } = new MouseDevice();
|
||||
public WindowTransparencyLevel TransparencyLevel => WindowTransparencyLevel.None;
|
||||
|
||||
public void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
|
||||
@@ -226,13 +228,13 @@ namespace Avalonia.iOS
|
||||
return new Class(typeof(CAEAGLLayer));
|
||||
}
|
||||
|
||||
public override void TouchesBegan(NSSet touches, UIEvent evt) => _touches.Handle(touches, evt);
|
||||
public override void TouchesBegan(NSSet touches, UIEvent? evt) => _touches.Handle(touches, evt);
|
||||
|
||||
public override void TouchesMoved(NSSet touches, UIEvent evt) => _touches.Handle(touches, evt);
|
||||
public override void TouchesMoved(NSSet touches, UIEvent? evt) => _touches.Handle(touches, evt);
|
||||
|
||||
public override void TouchesEnded(NSSet touches, UIEvent evt) => _touches.Handle(touches, evt);
|
||||
public override void TouchesEnded(NSSet touches, UIEvent? evt) => _touches.Handle(touches, evt);
|
||||
|
||||
public override void TouchesCancelled(NSSet touches, UIEvent evt) => _touches.Handle(touches, evt);
|
||||
public override void TouchesCancelled(NSSet touches, UIEvent? evt) => _touches.Handle(touches, evt);
|
||||
|
||||
public override void LayoutSubviews()
|
||||
{
|
||||
@@ -240,9 +242,9 @@ namespace Avalonia.iOS
|
||||
base.LayoutSubviews();
|
||||
}
|
||||
|
||||
public Control Content
|
||||
public Control? Content
|
||||
{
|
||||
get => (Control)_topLevel.Content;
|
||||
get => (Control?)_topLevel.Content;
|
||||
set => _topLevel.Content = value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ internal sealed class IOSSecurityScopedStream : Stream
|
||||
internal IOSSecurityScopedStream(NSUrl url, FileAccess access)
|
||||
{
|
||||
_document = new UIDocument(url);
|
||||
var path = _document.FileUrl.Path;
|
||||
var path = _document.FileUrl.Path!;
|
||||
_url = url;
|
||||
_url.StartAccessingSecurityScopedResource();
|
||||
_stream = File.Open(path, FileMode.Open, access);
|
||||
|
||||
@@ -47,7 +47,12 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
|
||||
Logger.TryGet(LogEventLevel.Error, LogArea.IOSPlatform)?.
|
||||
Log(this, "GetBasicPropertiesAsync returned an error: {ErrorCode} {ErrorMessage}", error.Code, error.LocalizedFailureReason);
|
||||
}
|
||||
return Task.FromResult(new StorageItemProperties(attributes?.Size, (DateTime)attributes?.CreationDate, (DateTime)attributes?.ModificationDate));
|
||||
|
||||
var properties = attributes is null ?
|
||||
new StorageItemProperties() :
|
||||
new StorageItemProperties(attributes.Size, (DateTime)attributes.CreationDate, (DateTime)attributes.ModificationDate);
|
||||
|
||||
return Task.FromResult(properties);
|
||||
}
|
||||
|
||||
public Task<IStorageFolder?> GetParentAsync()
|
||||
@@ -62,7 +67,7 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
|
||||
: Task.FromException(new NSErrorException(error));
|
||||
}
|
||||
|
||||
public async Task<IStorageItem?> MoveAsync(IStorageFolder destination)
|
||||
public Task<IStorageItem?> MoveAsync(IStorageFolder destination)
|
||||
{
|
||||
if (destination is not IOSStorageFolder folder)
|
||||
{
|
||||
@@ -75,8 +80,8 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
|
||||
if (NSFileManager.DefaultManager.Move(folder.Url, newPath, out var error))
|
||||
{
|
||||
return isDir
|
||||
? new IOSStorageFolder(newPath)
|
||||
: new IOSStorageFile(newPath);
|
||||
? Task.FromResult<IStorageItem?>(new IOSStorageFolder(newPath))
|
||||
: Task.FromResult<IStorageItem?>(new IOSStorageFile(newPath));
|
||||
}
|
||||
|
||||
if (error is not null)
|
||||
@@ -84,7 +89,7 @@ internal abstract class IOSStorageItem : IStorageBookmarkItem
|
||||
throw new NSErrorException(error);
|
||||
}
|
||||
|
||||
return null;
|
||||
return Task.FromResult<IStorageItem?>(null);
|
||||
}
|
||||
|
||||
public Task ReleaseBookmarkAsync()
|
||||
|
||||
@@ -159,17 +159,20 @@ partial class AvaloniaView
|
||||
{
|
||||
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "Triggering key press {key}", key);
|
||||
|
||||
_view._topLevelImpl.Input(new RawKeyEventArgs(KeyboardDevice.Instance!, 0, _view.InputRoot,
|
||||
RawKeyEventType.KeyDown, key, RawInputModifiers.None, physicalKey, keySymbol));
|
||||
if (_view._topLevelImpl.Input is { } input)
|
||||
{
|
||||
input.Invoke(new RawKeyEventArgs(KeyboardDevice.Instance!, 0, _view.InputRoot,
|
||||
RawKeyEventType.KeyDown, key, RawInputModifiers.None, physicalKey, keySymbol));
|
||||
|
||||
_view._topLevelImpl.Input(new RawKeyEventArgs(KeyboardDevice.Instance!, 0, _view.InputRoot,
|
||||
RawKeyEventType.KeyUp, key, RawInputModifiers.None, physicalKey, keySymbol));
|
||||
input.Invoke(new RawKeyEventArgs(KeyboardDevice.Instance!, 0, _view.InputRoot,
|
||||
RawKeyEventType.KeyUp, key, RawInputModifiers.None, physicalKey, keySymbol));
|
||||
}
|
||||
}
|
||||
|
||||
private void TextInput(string text)
|
||||
{
|
||||
Logger.TryGet(LogEventLevel.Debug, ImeLog)?.Log(null, "Triggering text input {text}", text);
|
||||
_view._topLevelImpl.Input(new RawTextInputEventArgs(KeyboardDevice.Instance!, 0, _view.InputRoot, text));
|
||||
_view._topLevelImpl.Input?.Invoke(new RawTextInputEventArgs(KeyboardDevice.Instance!, 0, _view.InputRoot, text));
|
||||
}
|
||||
|
||||
void IUIKeyInput.InsertText(string text)
|
||||
|
||||
@@ -14,8 +14,8 @@ public class DispatcherTests
|
||||
{
|
||||
class SimpleDispatcherImpl : IDispatcherImpl, IDispatcherImplWithPendingInput
|
||||
{
|
||||
private Thread _loopThread = Thread.CurrentThread;
|
||||
private object _lock = new();
|
||||
private readonly Thread _loopThread = Thread.CurrentThread;
|
||||
private readonly object _lock = new();
|
||||
public bool CurrentThreadIsLoopThread => Thread.CurrentThread == _loopThread;
|
||||
public void Signal()
|
||||
{
|
||||
@@ -221,7 +221,8 @@ public class DispatcherTests
|
||||
0 => 1,
|
||||
1 => 4,
|
||||
2 => 8,
|
||||
3 => 10
|
||||
3 => 10,
|
||||
_ => throw new InvalidOperationException($"Unexpected value {c}")
|
||||
};
|
||||
|
||||
Assert.Equal(Enumerable.Range(0, expectedCount), actions);
|
||||
@@ -380,7 +381,7 @@ public class DispatcherTests
|
||||
class WaitHelper : SynchronizationContext, NonPumpingLockHelper.IHelperImpl
|
||||
{
|
||||
public int WaitCount;
|
||||
public int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
|
||||
public override int Wait(IntPtr[] waitHandles, bool waitAll, int millisecondsTimeout)
|
||||
{
|
||||
WaitCount++;
|
||||
return base.Wait(waitHandles, waitAll, millisecondsTimeout);
|
||||
@@ -502,4 +503,4 @@ public class DispatcherTests
|
||||
t.GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,8 @@ public class EffectTests
|
||||
InlineData("drop-shadow ( 10 20 30 #ffff00ff ) ", 10, 20, 30, 0xffff00ff),
|
||||
InlineData("drop-shadow(10 20 30 red)", 10, 20, 30, 0xffff0000),
|
||||
InlineData("drop-shadow ( 10 20 30 red ) ", 10, 20, 30, 0xffff0000),
|
||||
InlineData("drop-shadow(10 20 30 rgba(100, 30, 45, 90%))", 10, 20, 30, 0x90641e2d),
|
||||
InlineData("drop-shadow(10 20 30 rgba(100, 30, 45, 90%) ) ", 10, 20, 30, 0x90641e2d),
|
||||
|
||||
InlineData("drop-shadow(10 20 30 rgba(100, 30, 45, 90%))", 10, 20, 30, 0xe6641e2d),
|
||||
InlineData("drop-shadow(10 20 30 rgba(100, 30, 45, 90%) ) ", 10, 20, 30, 0xe6641e2d)
|
||||
]
|
||||
public void Parse_Parses_DropShadow(string s, double x, double y, double r, uint color)
|
||||
{
|
||||
@@ -36,6 +35,7 @@ public class EffectTests
|
||||
Assert.Equal(y, effect.OffsetY);
|
||||
Assert.Equal(r, effect.BlurRadius);
|
||||
Assert.Equal(1, effect.Opacity);
|
||||
Assert.Equal(color, effect.Color.ToUInt32());
|
||||
}
|
||||
|
||||
[Theory,
|
||||
@@ -44,7 +44,7 @@ public class EffectTests
|
||||
InlineData("blur()"),
|
||||
InlineData("blur(123"),
|
||||
InlineData("blur(aaab)"),
|
||||
InlineData("drop-shadow(-10 -20 -30)"),
|
||||
InlineData("drop-shadow(-10 -20 -30)")
|
||||
]
|
||||
public void Invalid_Effect_Parse_Fails(string b)
|
||||
{
|
||||
@@ -58,10 +58,7 @@ public class EffectTests
|
||||
InlineData("drop-shadow(10 15 5)", 0, 0, 16, 21),
|
||||
InlineData("drop-shadow(0 0 5)", 6, 6, 6, 6),
|
||||
InlineData("drop-shadow(3 3 5)", 3, 3, 9, 9)
|
||||
|
||||
|
||||
]
|
||||
|
||||
public static void PaddingIsCorrectlyCalculated(string effect, double left, double top, double right, double bottom)
|
||||
{
|
||||
var padding = Effect.Parse(effect).GetEffectOutputPadding();
|
||||
@@ -70,4 +67,4 @@ public class EffectTests
|
||||
Assert.Equal(right, padding.Right);
|
||||
Assert.Equal(bottom, padding.Bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,12 +525,12 @@ namespace Avalonia.Base.UnitTests.Styling
|
||||
|
||||
private class TestConverter : IValueConverter
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
return value.ToString() + "bar";
|
||||
return value + "bar";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq;
|
||||
using Avalonia.Automation.Peers;
|
||||
using Avalonia.Automation.Provider;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Platform;
|
||||
using Avalonia.UnitTests;
|
||||
using Avalonia.VisualTree;
|
||||
using Xunit;
|
||||
|
||||
@@ -41,7 +37,7 @@ namespace Avalonia.Controls.UnitTests.Automation
|
||||
{
|
||||
var contentControl = new ContentControl
|
||||
{
|
||||
Template = new FuncControlTemplate<ContentControl>((o, ns) =>
|
||||
Template = new FuncControlTemplate<ContentControl>((o, _) =>
|
||||
new ContentPresenter
|
||||
{
|
||||
Name = "PART_ContentPresenter",
|
||||
@@ -180,50 +176,5 @@ namespace Avalonia.Controls.UnitTests.Automation
|
||||
{
|
||||
return ControlAutomationPeer.CreatePeerForElement(control);
|
||||
}
|
||||
|
||||
private class TestControl : Control
|
||||
{
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new TestAutomationPeer(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class AutomationTestRoot : TestRoot
|
||||
{
|
||||
protected override AutomationPeer OnCreateAutomationPeer()
|
||||
{
|
||||
return new TestRootAutomationPeer(this);
|
||||
}
|
||||
}
|
||||
|
||||
private class TestAutomationPeer : ControlAutomationPeer
|
||||
{
|
||||
public TestAutomationPeer( Control owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class TestRootAutomationPeer : ControlAutomationPeer, IRootProvider
|
||||
{
|
||||
public TestRootAutomationPeer(Control owner)
|
||||
: base(owner)
|
||||
{
|
||||
}
|
||||
|
||||
public ITopLevelImpl PlatformImpl => throw new System.NotImplementedException();
|
||||
public event EventHandler? FocusChanged;
|
||||
|
||||
public AutomationPeer GetFocus()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public AutomationPeer GetPeerFromPoint(Point p)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2424,7 +2424,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
|
||||
set => base.SelectionMode = value;
|
||||
}
|
||||
|
||||
public new bool MoveSelection(NavigationDirection direction, bool wrap)
|
||||
public bool MoveSelection(NavigationDirection direction, bool wrap)
|
||||
{
|
||||
return base.MoveSelection(direction, wrap);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using Avalonia.Data;
|
||||
using Avalonia.UnitTests;
|
||||
|
||||
using Xunit;
|
||||
|
||||
#pragma warning disable CS0618 // Type or member is obsolete -- we're testing these members
|
||||
|
||||
namespace Avalonia.Controls.Primitives.UnitTests
|
||||
{
|
||||
public class ToggleButtonTests
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Avalonia.Markup.Xaml.Converters;
|
||||
using Avalonia.Markup.Xaml.XamlIl.Runtime;
|
||||
@@ -13,8 +12,8 @@ namespace Avalonia.Markup.Xaml.UnitTests.Converters
|
||||
public AvaloniaPropertyConverterTest()
|
||||
{
|
||||
// Ensure properties are registered.
|
||||
var foo = Class1.FooProperty;
|
||||
var attached = AttachedOwner.AttachedProperty;
|
||||
_ = Class1.FooProperty;
|
||||
_ = AttachedOwner.AttachedProperty;
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -114,13 +113,6 @@ namespace Avalonia.Markup.Xaml.UnitTests.Converters
|
||||
{
|
||||
public static readonly StyledProperty<string> FooProperty =
|
||||
AvaloniaProperty.Register<Class1, string>("Foo");
|
||||
|
||||
public ThemeVariant ThemeVariant
|
||||
{
|
||||
get => throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public event EventHandler ThemeVariantChanged;
|
||||
}
|
||||
|
||||
private class AttachedOwner
|
||||
|
||||
+114
-110
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
@@ -48,7 +50,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -74,7 +76,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding StringProperty}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -100,7 +102,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding Path=StringProperty}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -132,7 +134,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</ItemsControl>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<ItemsControl>("itemsControl");
|
||||
var textBlock = window.GetControl<ItemsControl>("itemsControl");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -162,7 +164,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding StaticProperty}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
textBlock.DataContext = new TestDataContext();
|
||||
|
||||
Assert.Equal(TestDataContext.StaticProperty, textBlock.Text);
|
||||
@@ -181,7 +183,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding StringProperty, DataType=local:TestDataContext}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -206,7 +208,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding StringProperty, DataType={x:Type local:TestDataContext}}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -232,7 +234,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding TaskProperty^}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -258,7 +260,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding ObservableProperty^}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
DelayedBinding.ApplyBindings(textBlock);
|
||||
|
||||
@@ -289,7 +291,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding ListProperty[3]}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -315,7 +317,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding ArrayProperty[3]}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -341,7 +343,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding ObservableCollectionProperty[3]}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -371,10 +373,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock DataContext='{CompiledBinding StringProperty}' Text='{CompiledBinding}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
window.ApplyTemplate();
|
||||
window.Presenter.ApplyTemplate();
|
||||
window.Presenter!.ApplyTemplate();
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -400,7 +402,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding NonIntegerIndexerProperty[Test]}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -429,7 +431,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding NonIntegerIndexerInterfaceProperty[Test]}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -463,7 +465,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Name='target' Content='{CompiledBinding StringProperty}' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<ContentControl>("target");
|
||||
var target = window.GetControl<ContentControl>("target");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -473,9 +475,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
window.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
target.Presenter.UpdateChild();
|
||||
target.Presenter!.UpdateChild();
|
||||
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -560,7 +562,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</ItemsControl>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<ItemsControl>("target");
|
||||
var target = window.GetControl<ItemsControl>("target");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -570,9 +572,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
window.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
target.Presenter.ApplyTemplate();
|
||||
target.Presenter!.ApplyTemplate();
|
||||
|
||||
Assert.Equal(dataContext.ListProperty[0], (string)((ContentPresenter)target.Presenter.Panel.Children[0]).Content);
|
||||
Assert.Equal(dataContext.ListProperty[0], (string?)((ContentPresenter)target.Presenter.Panel!.Children[0]).Content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -598,8 +600,8 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</local:DataGridLikeControl.Columns>
|
||||
</local:DataGridLikeControl>
|
||||
</Window>");
|
||||
var target = window.FindControl<DataGridLikeControl>("target");
|
||||
var column = target!.Columns.Single();
|
||||
var target = window.GetControl<DataGridLikeControl>("target");
|
||||
var column = target.Columns.Single();
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -611,13 +613,13 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
target.ApplyTemplate();
|
||||
|
||||
// Assert DataGridLikeColumn.Binding data type.
|
||||
var compiledPath = ((CompiledBindingExtension)column.Binding).Path;
|
||||
var compiledPath = ((CompiledBindingExtension)column.Binding!).Path;
|
||||
var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
|
||||
Assert.Equal(typeof(int), node.Property.PropertyType);
|
||||
|
||||
// Assert DataGridLikeColumn.Template data type by evaluating the template.
|
||||
var firstItem = dataContext.ListProperty[0];
|
||||
var textBlockFromTemplate = (TextBlock)column.Template.Build(firstItem);
|
||||
var textBlockFromTemplate = (TextBlock)column.Template!.Build(firstItem)!;
|
||||
textBlockFromTemplate.DataContext = firstItem;
|
||||
Assert.Equal(firstItem.Length.ToString(), textBlockFromTemplate.Text);
|
||||
}
|
||||
@@ -645,8 +647,8 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</local:DataGridLikeControl.Columns>
|
||||
</local:DataGridLikeControl>
|
||||
</Window>");
|
||||
var target = window.FindControl<DataGridLikeControl>("target");
|
||||
var column = target!.Columns.Single();
|
||||
var target = window.GetControl<DataGridLikeControl>("target");
|
||||
var column = target.Columns.Single();
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
dataContext.ListProperty.Add("Test");
|
||||
@@ -656,13 +658,13 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
target.ApplyTemplate();
|
||||
|
||||
// Assert DataGridLikeColumn.Binding data type.
|
||||
var compiledPath = ((CompiledBindingExtension)column.Binding).Path;
|
||||
var compiledPath = ((CompiledBindingExtension)column.Binding!).Path;
|
||||
var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
|
||||
Assert.Equal(typeof(int), node.Property.PropertyType);
|
||||
|
||||
// Assert DataGridLikeColumn.Template data type by evaluating the template.
|
||||
var firstItem = dataContext.ListProperty[0];
|
||||
var textBlockFromTemplate = (TextBlock)column.Template.Build(firstItem);
|
||||
var textBlockFromTemplate = (TextBlock)column.Template!.Build(firstItem)!;
|
||||
textBlockFromTemplate.DataContext = firstItem;
|
||||
Assert.Equal(firstItem.Length.ToString(), textBlockFromTemplate.Text);
|
||||
}
|
||||
@@ -707,7 +709,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<ContentControl>("target");
|
||||
var target = window.GetControl<ContentControl>("target");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -717,9 +719,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
window.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
target.Presenter.UpdateChild();
|
||||
target.Presenter!.UpdateChild();
|
||||
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,7 +742,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<ContentControl>("target");
|
||||
var target = window.GetControl<ContentControl>("target");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -750,9 +752,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
window.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
target.Presenter.UpdateChild();
|
||||
target.Presenter!.UpdateChild();
|
||||
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -773,7 +775,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl x:DataType='local:TestDataContext' Name='target' Content='{CompiledBinding}' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<ContentControl>("target");
|
||||
var target = window.GetControl<ContentControl>("target");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -783,9 +785,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
window.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
target.Presenter.UpdateChild();
|
||||
target.Presenter!.UpdateChild();
|
||||
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child).Text);
|
||||
Assert.Equal(dataContext.StringProperty, ((TextBlock)target.Presenter.Child!).Text);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -805,7 +807,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</StackPanel>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("text2");
|
||||
var textBlock = window.GetControl<TextBlock>("text2");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -834,7 +836,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</StackPanel>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("text2");
|
||||
var textBlock = window.GetControl<TextBlock>("text2");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -861,10 +863,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding Title, RelativeSource={RelativeSource AncestorType=Window}}' x:Name='text'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<TextBlock>("text");
|
||||
var target = window.GetControl<TextBlock>("text");
|
||||
|
||||
window.ApplyTemplate();
|
||||
window.Presenter.ApplyTemplate();
|
||||
window.Presenter!.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
|
||||
Assert.Equal("test", target.Text);
|
||||
@@ -885,10 +887,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding Title, RelativeSource={RelativeSource AncestorType={x:Type Window}}}' x:Name='text'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<TextBlock>("text");
|
||||
var target = window.GetControl<TextBlock>("text");
|
||||
|
||||
window.ApplyTemplate();
|
||||
window.Presenter.ApplyTemplate();
|
||||
window.Presenter!.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
|
||||
Assert.Equal("test", target.Text);
|
||||
@@ -1003,10 +1005,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding Length, Source=Test}' x:Name='text'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var target = window.FindControl<TextBlock>("text");
|
||||
var target = window.GetControl<TextBlock>("text");
|
||||
|
||||
window.ApplyTemplate();
|
||||
window.Presenter.ApplyTemplate();
|
||||
window.Presenter!.ApplyTemplate();
|
||||
target.ApplyTemplate();
|
||||
|
||||
Assert.Equal("Test".Length.ToString(), target.Text);
|
||||
@@ -1030,7 +1032,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
Assert.Equal("foobar", textBlock.Text);
|
||||
}
|
||||
@@ -1054,7 +1056,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
Assert.Equal("foobar", textBlock.Text);
|
||||
}
|
||||
@@ -1079,7 +1081,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
Assert.Equal("foobar", textBlock.Text);
|
||||
}
|
||||
@@ -1105,7 +1107,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
Assert.Equal("foobar", textBlock.Text);
|
||||
}
|
||||
@@ -1125,7 +1127,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
Assert.Equal(Brushes.Red.Color, contentControl.Content);
|
||||
}
|
||||
@@ -1145,7 +1147,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{Binding StringProperty}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1188,7 +1190,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding $parent.Title}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
Assert.Equal("foo", contentControl.Content);
|
||||
}
|
||||
@@ -1208,7 +1210,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
window.DataContext = new TestDataContext() { StringProperty = "Foo" };
|
||||
|
||||
@@ -1230,7 +1232,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
</Window>";
|
||||
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
window.DataContext = new TestDataContext() { StringProperty = "Foo" };
|
||||
|
||||
@@ -1267,7 +1269,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
|
||||
@@ -1290,7 +1292,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext)}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
var dataContext = "foo";
|
||||
|
||||
@@ -1313,7 +1315,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1339,7 +1341,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding $parent.DataContext(local:TestDataContext).StringProperty}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1365,7 +1367,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding ((local:TestData)ObjectsArrayProperty[0]).StringProperty}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
var data = new TestData()
|
||||
{
|
||||
@@ -1395,7 +1397,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ContentControl Content='{CompiledBinding $parent.((local:TestDataContext)DataContext).StringProperty}' Name='contentControl' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var contentControl = window.FindControl<ContentControl>("contentControl");
|
||||
var contentControl = window.GetControl<ContentControl>("contentControl");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1425,7 +1427,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1451,7 +1453,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding StringFormat=bar-\{0\}}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1477,7 +1479,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding .}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1503,7 +1505,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Text='{CompiledBinding Path=., StringFormat=bar-\{0\}}' Name='textBlock' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext
|
||||
{
|
||||
@@ -1550,10 +1552,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Name='textBlock' Text='{CompiledBinding $self.Name}' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
window.ApplyTemplate();
|
||||
window.Presenter.ApplyTemplate();
|
||||
window.Presenter!.ApplyTemplate();
|
||||
|
||||
Assert.Equal(textBlock.Name, textBlock.Text);
|
||||
}
|
||||
@@ -1577,10 +1579,10 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<Button Name='button' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var button = window.FindControl<Button>("button");
|
||||
var button = window.GetControl<Button>("button");
|
||||
|
||||
window.ApplyTemplate();
|
||||
window.Presenter.ApplyTemplate();
|
||||
window.Presenter!.ApplyTemplate();
|
||||
|
||||
Assert.True(button.IsVisible);
|
||||
|
||||
@@ -1612,12 +1614,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
window.DataContext = new MethodDataContext();
|
||||
|
||||
Assert.IsAssignableFrom(typeof(Action), window.FindControl<ContentControl>("action").Content);
|
||||
Assert.IsAssignableFrom(typeof(Func<int>), window.FindControl<ContentControl>("func").Content);
|
||||
Assert.IsAssignableFrom(typeof(Action<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.FindControl<ContentControl>("action16").Content);
|
||||
Assert.IsAssignableFrom(typeof(Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.FindControl<ContentControl>("func16").Content);
|
||||
Assert.True(typeof(Delegate).IsAssignableFrom(window.FindControl<ContentControl>("customvoid").Content.GetType()));
|
||||
Assert.True(typeof(Delegate).IsAssignableFrom(window.FindControl<ContentControl>("customint").Content.GetType()));
|
||||
Assert.IsAssignableFrom(typeof(Action), window.GetControl<ContentControl>("action").Content);
|
||||
Assert.IsAssignableFrom(typeof(Func<int>), window.GetControl<ContentControl>("func").Content);
|
||||
Assert.IsAssignableFrom(typeof(Action<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.GetControl<ContentControl>("action16").Content);
|
||||
Assert.IsAssignableFrom(typeof(Func<int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int, int>), window.GetControl<ContentControl>("func16").Content);
|
||||
Assert.True(typeof(Delegate).IsAssignableFrom(window.GetControl<ContentControl>("customvoid").Content!.GetType()));
|
||||
Assert.True(typeof(Delegate).IsAssignableFrom(window.GetControl<ContentControl>("customint").Content!.GetType()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1634,7 +1636,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<Button Name='button' Command='{CompiledBinding Method}'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var button = window.FindControl<Button>("button");
|
||||
var button = window.GetControl<Button>("button");
|
||||
var vm = new MethodAsCommandDataContext();
|
||||
|
||||
button.DataContext = vm;
|
||||
@@ -1659,7 +1661,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<Button Name='button' Command='{CompiledBinding Method1}' CommandParameter='5'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var button = window.FindControl<Button>("button");
|
||||
var button = window.GetControl<Button>("button");
|
||||
var vm = new MethodAsCommandDataContext();
|
||||
|
||||
button.DataContext = vm;
|
||||
@@ -1684,7 +1686,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Name='textBlock' Text='{CompiledBinding Method}'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
var vm = new MethodAsCommandDataContext();
|
||||
|
||||
textBlock.DataContext = vm;
|
||||
@@ -1710,7 +1712,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<Button Name='button' Command='{CompiledBinding Do}' CommandParameter='{CompiledBinding Parameter, Mode=OneTime}'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var button = window.FindControl<Button>("button");
|
||||
var button = window.GetControl<Button>("button");
|
||||
var vm = new MethodAsCommandDataContext()
|
||||
{
|
||||
Parameter = commandParameter
|
||||
@@ -1738,7 +1740,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<Button Name='button' Command='{CompiledBinding Do}'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var button = window.FindControl<Button>("button");
|
||||
var button = window.GetControl<Button>("button");
|
||||
var vm = new MethodAsCommandDataContext()
|
||||
{
|
||||
Parameter = null,
|
||||
@@ -1770,7 +1772,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
x:DataType='local:TestDataContext'
|
||||
X='{CompiledBinding StringProperty}' />";
|
||||
var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var compiledPath = ((CompiledBindingExtension)control.X).Path;
|
||||
var compiledPath = ((CompiledBindingExtension)control.X!).Path;
|
||||
|
||||
var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
|
||||
Assert.Equal(typeof(string), node.Property.PropertyType);
|
||||
@@ -1788,7 +1790,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
xmlns:local='clr-namespace:Avalonia.Markup.Xaml.UnitTests.MarkupExtensions;assembly=Avalonia.Markup.Xaml.UnitTests'
|
||||
X='{CompiledBinding StringProperty, DataType=local:TestDataContext}' />";
|
||||
var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var compiledPath = ((CompiledBindingExtension)control.X).Path;
|
||||
var compiledPath = ((CompiledBindingExtension)control.X!).Path;
|
||||
|
||||
var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
|
||||
Assert.Equal(typeof(string), node.Property.PropertyType);
|
||||
@@ -1807,7 +1809,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
X='{CompiledBinding StringProperty, DataType=local:TestDataContext}' />";
|
||||
var control = (AssignBindingControl)AvaloniaRuntimeXamlLoader.Load(new RuntimeXamlLoaderDocument(xaml),
|
||||
new RuntimeXamlLoaderConfiguration { UseCompiledBindingsByDefault = true });
|
||||
var compiledPath = ((CompiledBindingExtension)control.X).Path;
|
||||
var compiledPath = ((CompiledBindingExtension)control.X!).Path;
|
||||
|
||||
var node = Assert.IsType<PropertyElement>(Assert.Single(compiledPath.Elements));
|
||||
Assert.Equal(typeof(string), node.Property.PropertyType);
|
||||
@@ -1830,7 +1832,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<ComboBox x:Name='comboBox' ItemsSource='{Binding GenericProperty}' SelectedItem='{Binding GenericProperty.CurrentItem}' />
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var comboBox = window.FindControl<ComboBox>("comboBox");
|
||||
var comboBox = window.GetControl<ComboBox>("comboBox");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
dataContext.GenericProperty.Add(123);
|
||||
@@ -1857,7 +1859,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
<TextBlock Name='textBlock' Text='{{Binding DecimalValue, StringFormat=c2}}'/>
|
||||
</Window>";
|
||||
var window = (Window)AvaloniaRuntimeXamlLoader.Load(xaml);
|
||||
var textBlock = window.FindControl<TextBlock>("textBlock");
|
||||
var textBlock = window.GetControl<TextBlock>("textBlock");
|
||||
|
||||
var dataContext = new TestDataContext();
|
||||
window.DataContext = dataContext;
|
||||
@@ -1887,7 +1889,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
public interface IHasProperty
|
||||
{
|
||||
string StringProperty { get; set; }
|
||||
string? StringProperty { get; set; }
|
||||
}
|
||||
|
||||
public interface IHasPropertyDerived : IHasProperty
|
||||
@@ -1902,34 +1904,34 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
{
|
||||
public static IValueConverter Instance { get; } = new AppendConverter();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
=> string.Format("{0}+{1}+{2}", value, parameter, culture);
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
}
|
||||
|
||||
public class TestData
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
public string? StringProperty { get; set; }
|
||||
}
|
||||
|
||||
public class TestDataContextBaseClass {}
|
||||
|
||||
public class TestDataContext : TestDataContextBaseClass, IHasPropertyDerived, IHasExplicitProperty
|
||||
{
|
||||
public string StringProperty { get; set; }
|
||||
public string? StringProperty { get; set; }
|
||||
|
||||
public Task<string> TaskProperty { get; set; }
|
||||
public Task<string>? TaskProperty { get; set; }
|
||||
|
||||
public IObservable<string> ObservableProperty { get; set; }
|
||||
public IObservable<string>? ObservableProperty { get; set; }
|
||||
|
||||
public ObservableCollection<string> ObservableCollectionProperty { get; set; } = new ObservableCollection<string>();
|
||||
|
||||
public string[] ArrayProperty { get; set; }
|
||||
public string[]? ArrayProperty { get; set; }
|
||||
|
||||
public object[] ObjectsArrayProperty { get; set; }
|
||||
public object[]? ObjectsArrayProperty { get; set; }
|
||||
|
||||
public List<string> ListProperty { get; set; } = new List<string>();
|
||||
|
||||
@@ -1966,7 +1968,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
public class ListItemCollectionView<T> : List<T>
|
||||
{
|
||||
public T CurrentItem { get; set; }
|
||||
public T? CurrentItem { get; set; }
|
||||
}
|
||||
|
||||
public class MethodDataContext
|
||||
@@ -1983,15 +1985,16 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
|
||||
public class MethodAsCommandDataContext : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
public string Method() => Value = "Called";
|
||||
public string Method1(int i) => Value = $"Called {i}";
|
||||
public string Method2(int i, int j) => Value = $"Called {i},{j}";
|
||||
public string Value { get; private set; } = "Not called";
|
||||
|
||||
object _parameter;
|
||||
public object Parameter
|
||||
private object? _parameter;
|
||||
|
||||
public object? Parameter
|
||||
{
|
||||
get => _parameter;
|
||||
set
|
||||
@@ -2010,7 +2013,7 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
Value = $"Do {parameter}";
|
||||
}
|
||||
|
||||
[Metadata.DependsOn(nameof(Parameter))]
|
||||
[DependsOn(nameof(Parameter))]
|
||||
public bool CanDo(object parameter)
|
||||
{
|
||||
return ReferenceEquals(null, Parameter) == false;
|
||||
@@ -2020,22 +2023,22 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
public class CustomDataTemplate : IDataTemplate
|
||||
{
|
||||
[DataType]
|
||||
public Type FancyDataType { get; set; }
|
||||
public Type? FancyDataType { get; set; }
|
||||
|
||||
[Content]
|
||||
[TemplateContent]
|
||||
public object Content { get; set; }
|
||||
public object? Content { get; set; }
|
||||
|
||||
public bool Match(object data) => FancyDataType?.IsInstanceOfType(data) ?? true;
|
||||
public bool Match(object? data) => FancyDataType?.IsInstanceOfType(data) ?? true;
|
||||
|
||||
public Control Build(object data) => TemplateContent.Load(Content)?.Result;
|
||||
public Control? Build(object? data) => TemplateContent.Load(Content)?.Result;
|
||||
}
|
||||
|
||||
public class CustomDataTemplateInherit : CustomDataTemplate { }
|
||||
|
||||
public class AssignBindingControl : Control
|
||||
{
|
||||
[AssignBinding] public IBinding X { get; set; }
|
||||
[AssignBinding] public IBinding? X { get; set; }
|
||||
}
|
||||
|
||||
public class DataGridLikeControl : Control
|
||||
@@ -2046,8 +2049,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
x => x.Items,
|
||||
(x, v) => x.Items = v);
|
||||
|
||||
private IEnumerable _items;
|
||||
public IEnumerable Items
|
||||
private IEnumerable? _items;
|
||||
|
||||
public IEnumerable? Items
|
||||
{
|
||||
get => _items;
|
||||
set => SetAndRaise(ItemsProperty, ref _items, value);
|
||||
@@ -2060,9 +2064,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
{
|
||||
[AssignBinding]
|
||||
[InheritDataTypeFromItems(nameof(DataGridLikeControl.Items), AncestorType = typeof(DataGridLikeControl))]
|
||||
public IBinding Binding { get; set; }
|
||||
public IBinding? Binding { get; set; }
|
||||
|
||||
[InheritDataTypeFromItems(nameof(DataGridLikeControl.Items), AncestorType = typeof(DataGridLikeControl))]
|
||||
public IDataTemplate Template { get; set; }
|
||||
public IDataTemplate? Template { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.UnitTests;
|
||||
using Xunit;
|
||||
@@ -40,9 +41,9 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
{
|
||||
var compiled = AvaloniaRuntimeXamlLoader.LoadGroup(documents);
|
||||
var userControl = Assert.IsType<UserControl>(compiled[1]);
|
||||
var border = userControl.FindControl<Border>("border");
|
||||
var border = userControl.GetControl<Border>("border");
|
||||
|
||||
var brush = (ISolidColorBrush)border.Background;
|
||||
var brush = (ISolidColorBrush)border.Background!;
|
||||
Assert.Equal(0xff506070, brush.Color.ToUInt32());
|
||||
}
|
||||
}
|
||||
@@ -130,17 +131,21 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||
{
|
||||
private readonly Dictionary<object, IResourceProvider> _langs = new();
|
||||
|
||||
public IResourceHost Owner { get; private set; }
|
||||
public IResourceHost? Owner { get; private set; }
|
||||
|
||||
public bool HasResources => true;
|
||||
|
||||
public event EventHandler OwnerChanged;
|
||||
public event EventHandler? OwnerChanged
|
||||
{
|
||||
add { }
|
||||
remove { }
|
||||
}
|
||||
|
||||
public void AddOwner(IResourceHost owner) => Owner = owner;
|
||||
|
||||
public void RemoveOwner(IResourceHost owner) => Owner = null;
|
||||
|
||||
public bool TryGetResource(object key, ThemeVariant theme, out object? value)
|
||||
public bool TryGetResource(object key, ThemeVariant? theme, out object? value)
|
||||
{
|
||||
if (_langs.TryGetValue("English", out var res))
|
||||
{
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Platform.Surfaces;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
using Xunit;
|
||||
using Path = System.IO.Path;
|
||||
|
||||
#pragma warning disable CS0649
|
||||
|
||||
#if AVALONIA_SKIA
|
||||
@@ -69,7 +69,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
|
||||
var fmt = new PixelFormat(fmte);
|
||||
var testName = nameof(FramebufferRenderResultsShouldBeUsableAsBitmap) + "_" + fmt;
|
||||
var fb = new Framebuffer(fmt, new PixelSize(80, 80));
|
||||
var r = Avalonia.AvaloniaLocator.Current.GetRequiredService<IPlatformRenderInterface>();
|
||||
var r = AvaloniaLocator.Current.GetRequiredService<IPlatformRenderInterface>();
|
||||
using(var cpuContext = r.CreateBackendContext(null))
|
||||
using (var target = cpuContext.CreateRenderTarget(new object[] { fb }))
|
||||
using (var ctx = target.CreateDrawingContext())
|
||||
@@ -94,7 +94,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
|
||||
var rc = new Rect(0, 0, 60, 60);
|
||||
ctx.DrawBitmap(bmp.PlatformImpl, 1, rc, rc);
|
||||
}
|
||||
rtb.Save(System.IO.Path.Combine(OutputPath, testName + ".out.png"));
|
||||
rtb.Save(Path.Combine(OutputPath, testName + ".out.png"));
|
||||
}
|
||||
CompareImagesNoRenderer(testName);
|
||||
}
|
||||
@@ -123,7 +123,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
|
||||
|
||||
var name = nameof(WriteableBitmapShouldBeUsable) + "_" + fmt;
|
||||
|
||||
writeableBitmap.Save(System.IO.Path.Combine(OutputPath, name + ".out.png"));
|
||||
writeableBitmap.Save(Path.Combine(OutputPath, name + ".out.png"));
|
||||
CompareImagesNoRenderer(name);
|
||||
|
||||
}
|
||||
@@ -177,7 +177,7 @@ namespace Avalonia.Direct2D1.RenderTests.Media
|
||||
|
||||
var testName = nameof(BitmapsShouldSupportTranscoders_Lenna) + "_" + formatName + names[step];
|
||||
|
||||
var path = System.IO.Path.Combine(OutputPath, testName + ".out.png");
|
||||
var path = Path.Combine(OutputPath, testName + ".out.png");
|
||||
fixed (byte* pData = data)
|
||||
{
|
||||
Bitmap? b = null;
|
||||
|
||||
@@ -44,7 +44,6 @@ public class DrawingBrushTests: TestBase
|
||||
|
||||
#if AVALONIA_SKIA
|
||||
[Fact]
|
||||
#endif
|
||||
public async Task DrawingBrushIsProperlyUpscaled()
|
||||
{
|
||||
Decorator target = new Decorator
|
||||
@@ -66,6 +65,7 @@ public class DrawingBrushTests: TestBase
|
||||
await RenderToFile(target);
|
||||
CompareImages();
|
||||
}
|
||||
#endif
|
||||
|
||||
GeometryDrawing CreateDrawing()
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace Avalonia.Direct2D1.RenderTests
|
||||
get;
|
||||
}
|
||||
|
||||
protected async Task RenderToFile(Control target, [CallerMemberName] string testName = "", double dpi = 96)
|
||||
protected Task RenderToFile(Control target, [CallerMemberName] string testName = "", double dpi = 96)
|
||||
{
|
||||
if (!Directory.Exists(OutputPath))
|
||||
{
|
||||
@@ -124,6 +124,8 @@ namespace Avalonia.Direct2D1.RenderTests
|
||||
}
|
||||
writableBitmap.Save(compositedPath);
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
class BitmapFramebufferSurface : IFramebufferPlatformSurface
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Media.TextFormatting;
|
||||
using Avalonia.Media.TextFormatting.Unicode;
|
||||
using Avalonia.UnitTests;
|
||||
@@ -30,10 +31,14 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Single(textLine.TextRuns);
|
||||
|
||||
var textRun = textLine.TextRuns[0];
|
||||
|
||||
Assert.NotNull(textRun.Properties);
|
||||
|
||||
Assert.Equal(defaultProperties.Typeface, textRun.Properties.Typeface);
|
||||
|
||||
Assert.Equal(defaultProperties.ForegroundBrush, textRun.Properties.ForegroundBrush);
|
||||
@@ -57,6 +62,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(5, textLine.TextRuns.Count);
|
||||
|
||||
Assert.Equal(50, textLine.Length);
|
||||
@@ -120,6 +127,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(5, textLine.TextRuns.Count);
|
||||
|
||||
Assert.Equal(14, textLine.Length);
|
||||
@@ -153,6 +162,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine = formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(text.Length, textLine.Length);
|
||||
|
||||
for (var i = 0; i < GenericTextRunPropertiesRuns.Length; i++)
|
||||
@@ -186,6 +197,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(numberOfRuns, textLine.TextRuns.Count);
|
||||
}
|
||||
}
|
||||
@@ -207,6 +220,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(1, textLine.TextRuns.Count);
|
||||
}
|
||||
}
|
||||
@@ -228,6 +243,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var firstRun = textLine.TextRuns[0];
|
||||
|
||||
Assert.Equal(4, firstRun.Length);
|
||||
@@ -249,7 +266,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
|
||||
var formatter = new TextFormatterImpl();
|
||||
|
||||
var line = formatter.FormatLine(textSource, 0, 33, paragraphProperties);
|
||||
formatter.FormatLine(textSource, 0, 33, paragraphProperties);
|
||||
|
||||
textSource = new SingleBufferTextSource(text, defaultProperties);
|
||||
|
||||
@@ -262,6 +279,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, currentPosition, 1, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
if (text.Length - currentPosition > expectedCharactersPerLine)
|
||||
{
|
||||
Assert.Equal(expectedCharactersPerLine, textLine.Length);
|
||||
@@ -318,6 +337,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, currentPosition, paragraphWidth,
|
||||
new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.Wrap));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var end = textLine.FirstTextSourceIndex + textLine.Length - 1;
|
||||
|
||||
Assert.True(expected.Contains(end));
|
||||
@@ -351,6 +372,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties, lineHeight: 50));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(50, textLine.Height);
|
||||
}
|
||||
}
|
||||
@@ -381,6 +404,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, textSourceIndex, 200, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.True(textLine.Width <= 200);
|
||||
|
||||
textSourceIndex += textLine.Length;
|
||||
@@ -407,6 +432,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, textSourceIndex, 3, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.NotEqual(0, textLine.Length);
|
||||
|
||||
textSourceIndex += textLine.Length;
|
||||
@@ -454,6 +481,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, currentPosition, 300,
|
||||
new GenericTextParagraphProperties(defaultProperties, textWrap: TextWrapping.WrapWithOverflow));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
currentPosition += textLine.Length;
|
||||
|
||||
if (textLine.Width > 300 || currentHeight + textLine.Height > 240)
|
||||
@@ -502,6 +531,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, 0, 100, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var expectedOffset = 0d;
|
||||
|
||||
switch (textAlignment)
|
||||
@@ -534,13 +565,15 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var formatter = new TextFormatterImpl();
|
||||
|
||||
var textPosition = 87;
|
||||
TextLineBreak lastBreak = null;
|
||||
TextLineBreak? lastBreak = null;
|
||||
|
||||
while (textPosition < text.Length)
|
||||
{
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, textPosition, 50, paragraphProperties, lastBreak);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(textLine.Length, textLine.TextRuns.Sum(x => x.Length));
|
||||
|
||||
textPosition += textLine.Length;
|
||||
@@ -564,6 +597,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, 0, 33, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var remainingRunsLineBreak = Assert.IsType<WrappingTextLineBreak>(textLine.TextLineBreak);
|
||||
var remainingRuns = remainingRunsLineBreak.AcquireRemainingRuns();
|
||||
Assert.NotNull(remainingRuns);
|
||||
@@ -592,6 +627,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var expectedTextLine = formatter.FormatLine(new SingleBufferTextSource(text, defaultProperties),
|
||||
0, double.PositiveInfinity, paragraphProperties);
|
||||
|
||||
Assert.NotNull(expectedTextLine);
|
||||
|
||||
var expectedRuns = expectedTextLine.TextRuns.Cast<ShapedTextRun>().ToList();
|
||||
|
||||
var expectedGlyphs = expectedRuns
|
||||
@@ -613,6 +650,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var shapedRuns = textLine.TextRuns.Cast<ShapedTextRun>().ToList();
|
||||
|
||||
var actualGlyphs = shapedRuns
|
||||
@@ -637,6 +676,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
TextFormatter.Current.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(3, textLine.TextRuns.Count);
|
||||
|
||||
Assert.True(textLine.TextRuns[1] is RectangleRun);
|
||||
@@ -655,6 +696,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
TextFormatter.Current.FormatLine(textSource, 0, double.PositiveInfinity, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.NotNull(textLine.TextLineBreak);
|
||||
|
||||
Assert.Equal(TextRun.DefaultTextSourceLength, textLine.Length);
|
||||
@@ -690,20 +733,22 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
|
||||
var pos = 0;
|
||||
|
||||
TextLineBreak previousLineBreak = null;
|
||||
TextLine textLine = null;
|
||||
TextLineBreak? previousLineBreak = null;
|
||||
TextLine? textLine = null;
|
||||
|
||||
while (pos < text.Length)
|
||||
{
|
||||
textLine = TextFormatter.Current.FormatLine(textSource, pos, 30, paragraphProperties, previousLineBreak);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
pos += textLine.Length;
|
||||
|
||||
previousLineBreak = textLine.TextLineBreak;
|
||||
}
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.NotNull(textLine.TextLineBreak);
|
||||
Assert.NotNull(textLine.TextLineBreak.TextEndOfLine);
|
||||
}
|
||||
}
|
||||
@@ -729,6 +774,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
TextFormatter.Current.FormatLine(source, 0, double.PositiveInfinity, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
void VerifyHit(int offset)
|
||||
{
|
||||
var glyphCenter = textLine.GetTextBounds(offset, 1)[0].Rectangle.Center;
|
||||
@@ -756,6 +803,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var textLine =
|
||||
TextFormatter.Current.FormatLine(source, 0, double.PositiveInfinity, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var bounds = textLine.GetTextBounds(0, 3);
|
||||
|
||||
Assert.Equal(1, bounds.Count);
|
||||
@@ -779,6 +828,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
{
|
||||
var source = new ListTextSource(new RectangleRun(new Rect(0, 0, 200, 10), Brushes.Aqua));
|
||||
var textLine = TextFormatter.Current.FormatLine(source, 0, 100, paragraphProperties);
|
||||
Assert.NotNull(textLine);
|
||||
Assert.Equal(200d, textLine.WidthIncludingTrailingWhitespace);
|
||||
}
|
||||
}
|
||||
@@ -822,6 +872,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
if (textLine.TextLineBreak is {} eol && eol.TextEndOfLine is TextEndOfParagraph)
|
||||
break;
|
||||
}
|
||||
|
||||
Assert.NotEmpty(lines);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,13 +884,13 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
DefaultTextRunProperties = defaultTextRunProperties;
|
||||
}
|
||||
|
||||
public override FlowDirection FlowDirection { get; }
|
||||
public override TextAlignment TextAlignment { get; }
|
||||
public override double LineHeight { get; }
|
||||
public override bool FirstLineInParagraph { get; }
|
||||
public override FlowDirection FlowDirection => default;
|
||||
public override TextAlignment TextAlignment => default;
|
||||
public override double LineHeight => default;
|
||||
public override bool FirstLineInParagraph => default;
|
||||
public override TextRunProperties DefaultTextRunProperties { get; }
|
||||
public override TextWrapping TextWrapping { get; }
|
||||
public override double Indent { get; }
|
||||
public override TextWrapping TextWrapping => default;
|
||||
public override double Indent => default;
|
||||
public override double DefaultIncrementalTab => 64;
|
||||
}
|
||||
|
||||
@@ -858,12 +910,12 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
var source = new ListTextSource(text);
|
||||
|
||||
var textLine = TextFormatter.Current.FormatLine(source, 0, double.PositiveInfinity, paragraphProperties);
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var backspaceHit = textLine.GetBackspaceCaretCharacterHit(new CharacterHit(2));
|
||||
Assert.Equal(1, backspaceHit.FirstCharacterIndex);
|
||||
Assert.Equal(0, backspaceHit.TrailingLength);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -878,6 +930,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
|
||||
var textLine = TextFormatter.Current.FormatLine(new SimpleTextSource(text, defaultRunProperties), 0, 120, paragraphProperties);
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
Assert.Equal(3, textLine.TextRuns.Count);
|
||||
}
|
||||
}
|
||||
@@ -913,7 +966,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
|
||||
private class EmptyTextSource : ITextSource
|
||||
{
|
||||
public TextRun GetTextRun(int textSourceIndex)
|
||||
public TextRun? GetTextRun(int textSourceIndex)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -936,7 +989,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
_text = text;
|
||||
}
|
||||
|
||||
public TextRun GetTextRun(int textSourceIndex)
|
||||
public TextRun? GetTextRun(int textSourceIndex)
|
||||
{
|
||||
if (textSourceIndex >= _text.Length + TextRun.DefaultTextSourceLength + _text.Length)
|
||||
{
|
||||
@@ -954,7 +1007,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
|
||||
private class ListTextSource : ITextSource
|
||||
{
|
||||
private List<TextRun> _runs = new();
|
||||
private readonly List<TextRun> _runs;
|
||||
|
||||
public ListTextSource(params TextRun[] runs) : this((IEnumerable<TextRun>)runs)
|
||||
{
|
||||
@@ -966,7 +1019,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
_runs = runs.ToList();
|
||||
}
|
||||
|
||||
public TextRun GetTextRun(int textSourceIndex)
|
||||
public TextRun? GetTextRun(int textSourceIndex)
|
||||
{
|
||||
var off = 0;
|
||||
for (var c = 0; c < _runs.Count; c++)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System;
|
||||
#nullable enable
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
@@ -33,6 +35,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, currentIndex, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var firstCharacterHit = textLine.GetPreviousCaretCharacterHit(new CharacterHit(int.MinValue));
|
||||
|
||||
Assert.Equal(textLine.FirstTextSourceIndex, firstCharacterHit.FirstCharacterIndex);
|
||||
@@ -61,6 +65,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, currentIndex, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var lastCharacterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(int.MaxValue));
|
||||
|
||||
Assert.Equal(textLine.FirstTextSourceIndex + textLine.Length,
|
||||
@@ -88,6 +94,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var clusters = new List<int>();
|
||||
|
||||
foreach (var textRun in textLine.TextRuns.OrderBy(x => TextTestHelper.GetStartCharIndex(x.Text)))
|
||||
@@ -135,6 +143,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var clusters = new List<int>();
|
||||
|
||||
foreach (var textRun in textLine.TextRuns.OrderBy(x => TextTestHelper.GetStartCharIndex(x.Text)))
|
||||
@@ -187,6 +197,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var clusters = BuildGlyphClusters(textLine);
|
||||
|
||||
var nextCharacterHit = new CharacterHit(0);
|
||||
@@ -246,6 +258,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var clusters = textLine.TextRuns
|
||||
.Cast<ShapedTextRun>()
|
||||
.SelectMany(x => x.ShapedBuffer, (_, glyph) => glyph.GlyphCluster)
|
||||
@@ -296,6 +310,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var currentDistance = 0.0;
|
||||
|
||||
foreach (var run in textLine.TextRuns)
|
||||
@@ -341,6 +357,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var isRightToLeft = IsRightToLeft(textLine);
|
||||
var rects = BuildRects(textLine);
|
||||
var glyphClusters = BuildGlyphClusters(textLine);
|
||||
@@ -394,6 +412,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.False(textLine.HasCollapsed);
|
||||
|
||||
TextCollapsingProperties collapsingProperties = trimming.CreateCollapsingProperties(new TextCollapsingCreateInfo(width, defaultProperties, FlowDirection.LeftToRight));
|
||||
@@ -427,6 +447,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(4, textLine.TextRuns.Count);
|
||||
|
||||
var currentHit = textLine.GetNextCaretCharacterHit(new CharacterHit(0));
|
||||
@@ -465,6 +487,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
Assert.Equal(4, textLine.TextRuns.Count);
|
||||
|
||||
var currentHit = textLine.GetPreviousCaretCharacterHit(new CharacterHit(3, 1));
|
||||
@@ -503,6 +527,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var characterHit = textLine.GetCharacterHitFromDistance(50);
|
||||
|
||||
Assert.Equal(5, characterHit.FirstCharacterIndex);
|
||||
@@ -529,6 +555,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var distance = textLine.GetDistanceFromCharacterHit(new CharacterHit(1));
|
||||
|
||||
Assert.Equal(14, distance);
|
||||
@@ -553,6 +581,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var distance = textLine.GetDistanceFromCharacterHit(new CharacterHit(10));
|
||||
|
||||
Assert.Equal(72.01171875, distance);
|
||||
@@ -585,6 +615,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, 10);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
@@ -625,6 +657,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, Environment.NewLine.Length);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
@@ -652,13 +686,15 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textRuns = textLine.TextRuns.Cast<ShapedTextRun>().ToList();
|
||||
|
||||
var lineWidth = textLine.WidthIncludingTrailingWhitespace;
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, text.Length);
|
||||
|
||||
TextBounds lastBounds = null;
|
||||
TextBounds? lastBounds = null;
|
||||
|
||||
var runBounds = textBounds.SelectMany(x => x.TextRunBounds).ToList();
|
||||
|
||||
@@ -711,6 +747,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, 1000,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var characterHit = textLine.GetCharacterHitFromDistance(1000);
|
||||
|
||||
Assert.Equal(10, characterHit.FirstCharacterIndex);
|
||||
@@ -732,6 +770,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var characterHit = textLine.GetNextCaretCharacterHit(new CharacterHit(9, 1));
|
||||
|
||||
Assert.Equal(10, characterHit.FirstCharacterIndex);
|
||||
@@ -784,6 +824,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var characterHit = textLine.GetPreviousCaretCharacterHit(new CharacterHit(20, 1));
|
||||
|
||||
Assert.Equal(20, characterHit.FirstCharacterIndex);
|
||||
@@ -836,6 +878,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 20, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var characterHit = textLine.GetCharacterHitFromDistance(double.PositiveInfinity);
|
||||
|
||||
Assert.Equal(40, characterHit.FirstCharacterIndex + characterHit.TrailingLength);
|
||||
@@ -866,7 +910,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
{
|
||||
private const string Text = "_A_A";
|
||||
|
||||
public TextRun GetTextRun(int textSourceIndex)
|
||||
public TextRun? GetTextRun(int textSourceIndex)
|
||||
{
|
||||
switch (textSourceIndex)
|
||||
{
|
||||
@@ -1004,6 +1048,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
formatter.FormatLine(textSource, 0, double.PositiveInfinity,
|
||||
new GenericTextParagraphProperties(defaultProperties));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, textLine.Length);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
@@ -1047,16 +1093,18 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, 3);
|
||||
|
||||
var firstRun = textLine.TextRuns[0] as ShapedTextRun;
|
||||
var firstRun = Assert.IsType<ShapedTextRun>(textLine.TextRuns[0]);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
Assert.Equal(firstRun.Size.Width, textBounds.Sum(x => x.Rectangle.Width));
|
||||
|
||||
textBounds = textLine.GetTextBounds(3, 4);
|
||||
|
||||
var secondRun = textLine.TextRuns[1] as ShapedTextRun;
|
||||
var secondRun = Assert.IsType<ShapedTextRun>(textLine.TextRuns[1]);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
Assert.Equal(secondRun.Size.Width, textBounds.Sum(x => x.Rectangle.Width));
|
||||
@@ -1094,16 +1142,18 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.RightToLeft, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, 4);
|
||||
|
||||
var secondRun = textLine.TextRuns[1] as ShapedTextRun;
|
||||
var secondRun = Assert.IsType<ShapedTextRun>(textLine.TextRuns[1]);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
Assert.Equal(secondRun.Size.Width, textBounds.Sum(x => x.Rectangle.Width));
|
||||
|
||||
textBounds = textLine.GetTextBounds(4, 3);
|
||||
|
||||
var firstRun = textLine.TextRuns[0] as ShapedTextRun;
|
||||
var firstRun = Assert.IsType<ShapedTextRun>(textLine.TextRuns[0]);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
|
||||
@@ -1146,6 +1196,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(0, 1);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
@@ -1173,6 +1225,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var textBounds = textLine.GetTextBounds(3, 1);
|
||||
|
||||
Assert.Equal(1, textBounds.Count);
|
||||
@@ -1200,6 +1254,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var bounds = textLine.GetTextBounds(6, 1);
|
||||
|
||||
Assert.Equal(1, bounds.Count);
|
||||
@@ -1249,6 +1305,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var bounds = textLine.GetTextBounds(0, text.Length);
|
||||
|
||||
Assert.Equal(4, bounds.Count);
|
||||
@@ -1259,8 +1317,6 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
[Fact]
|
||||
public void Should_GetPreviousCharacterHit_Non_Trailing()
|
||||
{
|
||||
@@ -1278,6 +1334,8 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
new GenericTextParagraphProperties(FlowDirection.LeftToRight, TextAlignment.Left,
|
||||
true, true, defaultProperties, TextWrapping.NoWrap, 0, 0, 0));
|
||||
|
||||
Assert.NotNull(textLine);
|
||||
|
||||
var characterHit = textLine.GetPreviousCaretCharacterHit(new CharacterHit(10, 1));
|
||||
}
|
||||
}
|
||||
@@ -1291,7 +1349,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting
|
||||
_textRuns = textRuns;
|
||||
}
|
||||
|
||||
public TextRun GetTextRun(int textSourceIndex)
|
||||
public TextRun? GetTextRun(int textSourceIndex)
|
||||
{
|
||||
var currentPosition = 0;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user