committed by
GitHub
444 changed files with 7474 additions and 7975 deletions
@ -1,7 +1,7 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="HarfBuzzSharp" Version="2.8.2" /> |
<PackageReference Include="HarfBuzzSharp" Version="2.8.2.1-preview.108" /> |
||||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2" /> |
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.Linux" Version="2.8.2.1-preview.108" /> |
||||
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="2.8.2" /> |
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="HarfBuzzSharp.NativeAssets.WebAssembly" Version="2.8.2.1-preview.108" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,5 +1,5 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="ReactiveUI" Version="13.2.10" /> |
<PackageReference Include="ReactiveUI" Version="18.3.1" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -1,7 +1,7 @@ |
|||||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
||||
<ItemGroup> |
<ItemGroup> |
||||
<PackageReference Include="SkiaSharp" Version="2.88.1-preview.1" /> |
<PackageReference Include="SkiaSharp" Version="2.88.1" /> |
||||
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1-preview.1" /> |
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.88.1" /> |
||||
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="2.88.1-preview.1" /> |
<PackageReference Condition="'$(IncludeWasmSkia)' == 'true'" Include="SkiaSharp.NativeAssets.WebAssembly" Version="2.88.1" /> |
||||
</ItemGroup> |
</ItemGroup> |
||||
</Project> |
</Project> |
||||
|
|||||
@ -0,0 +1,57 @@ |
|||||
|
using System.Globalization; |
||||
|
using JetBrains.Annotations; |
||||
|
using Nuke.Common.Tools.DotNet; |
||||
|
// ReSharper disable ReturnValueOfPureMethodIsNotUsed
|
||||
|
|
||||
|
public class DotNetConfigHelper |
||||
|
{ |
||||
|
public DotNetBuildSettings Build; |
||||
|
public DotNetPackSettings Pack; |
||||
|
public DotNetTestSettings Test; |
||||
|
|
||||
|
public DotNetConfigHelper(DotNetBuildSettings s) |
||||
|
{ |
||||
|
Build = s; |
||||
|
} |
||||
|
|
||||
|
public DotNetConfigHelper(DotNetPackSettings s) |
||||
|
{ |
||||
|
Pack = s; |
||||
|
} |
||||
|
|
||||
|
public DotNetConfigHelper(DotNetTestSettings s) |
||||
|
{ |
||||
|
Test = s; |
||||
|
} |
||||
|
|
||||
|
public DotNetConfigHelper AddProperty(string key, bool value) => |
||||
|
AddProperty(key, value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant()); |
||||
|
public DotNetConfigHelper AddProperty(string key, string value) |
||||
|
{ |
||||
|
Build = Build?.AddProperty(key, value); |
||||
|
Pack = Pack?.AddProperty(key, value); |
||||
|
Test = Test?.AddProperty(key, value); |
||||
|
|
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public DotNetConfigHelper SetConfiguration(string configuration) |
||||
|
{ |
||||
|
Build = Build?.SetConfiguration(configuration); |
||||
|
Pack = Pack?.SetConfiguration(configuration); |
||||
|
Test = Test?.SetConfiguration(configuration); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public DotNetConfigHelper SetVerbosity(DotNetVerbosity verbosity) |
||||
|
{ |
||||
|
Build = Build?.SetVerbosity(verbosity); |
||||
|
Pack = Pack?.SetVerbostiy(verbosity); |
||||
|
Test = Test?.SetVerbosity(verbosity); |
||||
|
return this; |
||||
|
} |
||||
|
|
||||
|
public static implicit operator DotNetConfigHelper(DotNetBuildSettings s) => new DotNetConfigHelper(s); |
||||
|
public static implicit operator DotNetConfigHelper(DotNetPackSettings s) => new DotNetConfigHelper(s); |
||||
|
public static implicit operator DotNetConfigHelper(DotNetTestSettings s) => new DotNetConfigHelper(s); |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using System; |
||||
|
using System.Globalization; |
||||
|
using Avalonia; |
||||
|
using Avalonia.Data.Converters; |
||||
|
|
||||
|
namespace ControlCatalog.Converter; |
||||
|
|
||||
|
public class HexConverter : IValueConverter |
||||
|
{ |
||||
|
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture) |
||||
|
{ |
||||
|
var str = value?.ToString(); |
||||
|
if (str == null) |
||||
|
return AvaloniaProperty.UnsetValue; |
||||
|
if (int.TryParse(str, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int x)) |
||||
|
return (decimal)x; |
||||
|
return AvaloniaProperty.UnsetValue; |
||||
|
|
||||
|
} |
||||
|
|
||||
|
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
if (value is decimal d) |
||||
|
return ((int)d).ToString("X8"); |
||||
|
return AvaloniaProperty.UnsetValue; |
||||
|
} |
||||
|
catch |
||||
|
{ |
||||
|
return AvaloniaProperty.UnsetValue; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,14 +1,10 @@ |
|||||
using System; |
namespace ControlCatalog.Models |
||||
using System.Collections.Generic; |
|
||||
using System.Text; |
|
||||
|
|
||||
namespace ControlCatalog.Models |
|
||||
{ |
{ |
||||
public enum CatalogTheme |
public enum CatalogTheme |
||||
{ |
{ |
||||
FluentLight, |
FluentLight, |
||||
FluentDark, |
FluentDark, |
||||
DefaultLight, |
SimpleLight, |
||||
DefaultDark |
SimpleDark |
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -0,0 +1,27 @@ |
|||||
|
using System; |
||||
|
using System.Runtime.InteropServices; |
||||
|
using Avalonia.Controls; |
||||
|
|
||||
|
namespace IntegrationTestApp |
||||
|
{ |
||||
|
public static class MacOSIntegration |
||||
|
{ |
||||
|
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "sel_registerName")] |
||||
|
private static extern IntPtr GetHandle(string name); |
||||
|
|
||||
|
[DllImport("/usr/lib/libobjc.dylib", EntryPoint = "objc_msgSend")] |
||||
|
private static extern long Int64_objc_msgSend(IntPtr receiver, IntPtr selector); |
||||
|
|
||||
|
private static readonly IntPtr s_orderedIndexSelector; |
||||
|
|
||||
|
static MacOSIntegration() |
||||
|
{ |
||||
|
s_orderedIndexSelector = GetHandle("orderedIndex");; |
||||
|
} |
||||
|
|
||||
|
public static long GetOrderedIndex(Window window) |
||||
|
{ |
||||
|
return Int64_objc_msgSend(window.PlatformImpl!.Handle.Handle, s_orderedIndexSelector); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,6 +1,5 @@ |
|||||
<Application xmlns="https://github.com/avaloniaui"> |
<Application xmlns="https://github.com/avaloniaui"> |
||||
<Application.Styles> |
<Application.Styles> |
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> |
<SimpleTheme Mode="Light" /> |
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/> |
|
||||
</Application.Styles> |
</Application.Styles> |
||||
</Application> |
</Application> |
||||
|
|||||
@ -1,6 +1,5 @@ |
|||||
<Application xmlns="https://github.com/avaloniaui"> |
<Application xmlns="https://github.com/avaloniaui"> |
||||
<Application.Styles> |
<Application.Styles> |
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> |
<SimpleTheme Mode="Light" /> |
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/> |
|
||||
</Application.Styles> |
</Application.Styles> |
||||
</Application> |
</Application> |
||||
|
|||||
@ -1,134 +1,141 @@ |
|||||
<UserControl |
<UserControl |
||||
xmlns="https://github.com/avaloniaui" |
xmlns="https://github.com/avaloniaui" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
x:Class="RenderDemo.Pages.DrawingPage"> |
x:Class="RenderDemo.Pages.DrawingPage"> |
||||
<UserControl.Styles> |
<UserControl.Styles> |
||||
<Style> |
<Style> |
||||
<Style.Resources> |
<Style.Resources> |
||||
<DrawingGroup x:Key="Bulb"> |
<DrawingGroup x:Key="Bulb"> |
||||
<DrawingGroup.Transform> |
<DrawingGroup.Transform> |
||||
<MatrixTransform Matrix="1,0,0,1,0,-1028.4" /> |
<MatrixTransform Matrix="1,0,0,1,0,-1028.4" /> |
||||
</DrawingGroup.Transform> |
</DrawingGroup.Transform> |
||||
<DrawingGroup> |
<DrawingGroup> |
||||
<DrawingGroup.Transform> |
<DrawingGroup.Transform> |
||||
<MatrixTransform Matrix="1,0,0,1.25,-10,1031.4" /> |
<MatrixTransform Matrix="1,0,0,1.25,-10,1031.4" /> |
||||
</DrawingGroup.Transform> |
</DrawingGroup.Transform> |
||||
<GeometryDrawing Brush="#FF7F8C8D" |
<GeometryDrawing Brush="#FF7F8C8D" |
||||
Geometry="F1 M24,14 A2,2,0,1,1,20,14 A2,2,0,1,1,24,14 z" /> |
Geometry="F1 M24,14 A2,2,0,1,1,20,14 A2,2,0,1,1,24,14 z" /> |
||||
</DrawingGroup> |
</DrawingGroup> |
||||
<GeometryDrawing Brush="#FFF39C12" |
<GeometryDrawing Brush="#FFF39C12" |
||||
Geometry="F1 M12,1030.4 C8.134,1030.4 5,1033.6 5,1037.6 5,1040.7 8.125,1043.5 9,1045.4 9.875,1047.2 9,1050.4 9,1050.4 L12,1049.9 15,1050.4 C15,1050.4 14.125,1047.2 15,1045.4 15.875,1043.5 19,1040.7 19,1037.6 19,1033.6 15.866,1030.4 12,1030.4 z" /> |
Geometry="F1 M12,1030.4 C8.134,1030.4 5,1033.6 5,1037.6 5,1040.7 8.125,1043.5 9,1045.4 9.875,1047.2 9,1050.4 9,1050.4 L12,1049.9 15,1050.4 C15,1050.4 14.125,1047.2 15,1045.4 15.875,1043.5 19,1040.7 19,1037.6 19,1033.6 15.866,1030.4 12,1030.4 z" /> |
||||
<GeometryDrawing Brush="#FFF1C40F" |
<GeometryDrawing Brush="#FFF1C40F" |
||||
Geometry="F1 M12,1030.4 C15.866,1030.4 19,1033.6 19,1037.6 19,1040.7 15.875,1043.5 15,1045.4 14.125,1047.2 15,1050.4 15,1050.4 L12,1049.9 12,1030.4 z" /> |
Geometry="F1 M12,1030.4 C15.866,1030.4 19,1033.6 19,1037.6 19,1040.7 15.875,1043.5 15,1045.4 14.125,1047.2 15,1050.4 15,1050.4 L12,1049.9 12,1030.4 z" /> |
||||
<GeometryDrawing Brush="#FFE67E22" |
<GeometryDrawing Brush="#FFE67E22" |
||||
Geometry="F1 M9,1036.4 L8,1037.4 12,1049.4 16,1037.4 15,1036.4 14,1037.4 13,1036.4 12,1037.4 11,1036.4 10,1037.4 9,1036.4 z M9,1037.4 L10,1038.4 10.5,1037.9 11,1037.4 11.5,1037.9 12,1038.4 12.5,1037.9 13,1037.4 13.5,1037.9 14,1038.4 15,1037.4 15.438,1037.8 12,1048.1 8.5625,1037.8 9,1037.4 z" /> |
Geometry="F1 M9,1036.4 L8,1037.4 12,1049.4 16,1037.4 15,1036.4 14,1037.4 13,1036.4 12,1037.4 11,1036.4 10,1037.4 9,1036.4 z M9,1037.4 L10,1038.4 10.5,1037.9 11,1037.4 11.5,1037.9 12,1038.4 12.5,1037.9 13,1037.4 13.5,1037.9 14,1038.4 15,1037.4 15.438,1037.8 12,1048.1 8.5625,1037.8 9,1037.4 z" /> |
||||
<DrawingGroup> |
<DrawingGroup> |
||||
<DrawingGroup.Transform> |
<DrawingGroup.Transform> |
||||
<MatrixTransform Matrix="1,0,0,1,9,1045.4" /> |
<MatrixTransform Matrix="1,0,0,1,9,1045.4" /> |
||||
</DrawingGroup.Transform> |
</DrawingGroup.Transform> |
||||
<GeometryDrawing Brush="#FFBDC3C7"> |
<GeometryDrawing Brush="#FFBDC3C7"> |
||||
<GeometryDrawing.Geometry> |
<GeometryDrawing.Geometry> |
||||
<RectangleGeometry Rect="0,0,6,5" /> |
<RectangleGeometry Rect="0,0,6,5" /> |
||||
</GeometryDrawing.Geometry> |
</GeometryDrawing.Geometry> |
||||
</GeometryDrawing> |
</GeometryDrawing> |
||||
</DrawingGroup> |
</DrawingGroup> |
||||
<GeometryDrawing Brush="#FF95A5A6" |
<GeometryDrawing Brush="#FF95A5A6" |
||||
Geometry="F1 M9,1045.4 L9,1050.4 12,1050.4 12,1049.4 15,1049.4 15,1048.4 12,1048.4 12,1047.4 15,1047.4 15,1046.4 12,1046.4 12,1045.4 9,1045.4 z" /> |
Geometry="F1 M9,1045.4 L9,1050.4 12,1050.4 12,1049.4 15,1049.4 15,1048.4 12,1048.4 12,1047.4 15,1047.4 15,1046.4 12,1046.4 12,1045.4 9,1045.4 z" /> |
||||
<GeometryDrawing Brush="#FF7F8C8D" |
<GeometryDrawing Brush="#FF7F8C8D" |
||||
Geometry="F1 M9,1046.4 L9,1047.4 12,1047.4 12,1046.4 9,1046.4 z M9,1048.4 L9,1049.4 12,1049.4 12,1048.4 9,1048.4 z" /> |
Geometry="F1 M9,1046.4 L9,1047.4 12,1047.4 12,1046.4 9,1046.4 z M9,1048.4 L9,1049.4 12,1049.4 12,1048.4 9,1048.4 z" /> |
||||
</DrawingGroup> |
</DrawingGroup> |
||||
</Style.Resources> |
</Style.Resources> |
||||
</Style> |
</Style> |
||||
</UserControl.Styles> |
</UserControl.Styles> |
||||
<Grid RowDefinitions="Auto,Auto,Auto" |
<Grid RowDefinitions="Auto,Auto,Auto" |
||||
ColumnDefinitions="Auto,Auto,Auto,Auto"> |
ColumnDefinitions="Auto,Auto,Auto,Auto"> |
||||
<TextBlock Text="None" |
<TextBlock Text="None" |
||||
Margin="3" /> |
Margin="3" /> |
||||
<Border Grid.Column="0" |
<Border Grid.Column="0" |
||||
Grid.Row="1" |
Grid.Row="1" |
||||
VerticalAlignment="Top" |
VerticalAlignment="Top" |
||||
HorizontalAlignment="Left" |
HorizontalAlignment="Left" |
||||
BorderThickness="1" |
BorderThickness="1" |
||||
BorderBrush="Gray" |
BorderBrush="Gray" |
||||
Margin="5"> |
Margin="5"> |
||||
<DrawingPresenter Drawing="{DynamicResource Bulb}" /> |
<Image> |
||||
</Border> |
<Image.Source> |
||||
<TextBlock Text="Fill" |
<DrawingImage Drawing="{DynamicResource Bulb}" /> |
||||
Margin="3" |
</Image.Source> |
||||
Grid.Column="1" /> |
</Image> |
||||
<Border Grid.Column="1" |
</Border> |
||||
Grid.Row="1" |
<TextBlock Text="Fill" |
||||
VerticalAlignment="Top" |
Margin="3" |
||||
HorizontalAlignment="Left" |
Grid.Column="1" /> |
||||
BorderThickness="1" |
<Border Grid.Column="1" |
||||
BorderBrush="Gray" |
Grid.Row="1" |
||||
Margin="5"> |
VerticalAlignment="Top" |
||||
<DrawingPresenter Drawing="{DynamicResource Bulb}" |
HorizontalAlignment="Left" |
||||
Width="100" |
BorderThickness="1" |
||||
Height="50" |
BorderBrush="Gray" |
||||
Stretch="Fill" /> |
Margin="5"> |
||||
</Border> |
<Image Width="100" Height="50" Stretch="Fill"> |
||||
<TextBlock Text="Uniform" |
<Image.Source> |
||||
Margin="3" |
<DrawingImage Drawing="{DynamicResource Bulb}" /> |
||||
Grid.Column="2" /> |
</Image.Source> |
||||
<Border Grid.Column="2" |
</Image> |
||||
Grid.Row="1" |
</Border> |
||||
VerticalAlignment="Top" |
<TextBlock Text="Uniform" |
||||
HorizontalAlignment="Left" |
Margin="3" |
||||
BorderThickness="1" |
Grid.Column="2" /> |
||||
BorderBrush="Gray" |
<Border Grid.Column="2" |
||||
Margin="5"> |
Grid.Row="1" |
||||
<DrawingPresenter Drawing="{DynamicResource Bulb}" |
VerticalAlignment="Top" |
||||
Width="100" |
HorizontalAlignment="Left" |
||||
Height="50" |
BorderThickness="1" |
||||
Stretch="Uniform" /> |
BorderBrush="Gray" |
||||
</Border> |
Margin="5"> |
||||
<TextBlock Text="UniformToFill" |
<Image Width="100" Height="50" Stretch="Uniform"> |
||||
Margin="3" |
<Image.Source> |
||||
Grid.Column="3" /> |
<DrawingImage Drawing="{DynamicResource Bulb}" /> |
||||
<Border Grid.Column="3" |
</Image.Source> |
||||
Grid.Row="1" |
</Image> |
||||
VerticalAlignment="Top" |
</Border> |
||||
HorizontalAlignment="Left" |
<TextBlock Text="UniformToFill" |
||||
BorderThickness="1" |
Margin="3" |
||||
BorderBrush="Gray" |
Grid.Column="3" /> |
||||
Margin="5"> |
<Border Grid.Column="3" |
||||
<DrawingPresenter Drawing="{DynamicResource Bulb}" |
Grid.Row="1" |
||||
Width="100" |
VerticalAlignment="Top" |
||||
Height="50" |
HorizontalAlignment="Left" |
||||
Stretch="UniformToFill" /> |
BorderThickness="1" |
||||
</Border> |
BorderBrush="Gray" |
||||
|
Margin="5"> |
||||
|
<Image Width="100" Height="50" Stretch="UniformToFill"> |
||||
|
<Image.Source> |
||||
|
<DrawingImage Drawing="{DynamicResource Bulb}" /> |
||||
|
</Image.Source> |
||||
|
</Image> |
||||
|
</Border> |
||||
|
|
||||
<!-- For comparison --> |
<!-- For comparison --> |
||||
|
|
||||
<Ellipse Grid.Row="2" |
<Ellipse Grid.Row="2" |
||||
Grid.Column="0" |
Grid.Column="0" |
||||
Width="100" |
Width="100" |
||||
Height="50" |
Height="50" |
||||
Stretch="None" |
Stretch="None" |
||||
Fill="Blue" |
Fill="Blue" |
||||
Margin="5"/> |
Margin="5"/> |
||||
<Ellipse Grid.Row="2" |
<Ellipse Grid.Row="2" |
||||
Grid.Column="1" |
Grid.Column="1" |
||||
Width="100" |
Width="100" |
||||
Height="50" |
Height="50" |
||||
Stretch="Fill" |
Stretch="Fill" |
||||
Fill="Blue" |
Fill="Blue" |
||||
Margin="5" /> |
Margin="5" /> |
||||
<Ellipse Grid.Row="2" |
<Ellipse Grid.Row="2" |
||||
Grid.Column="2" |
Grid.Column="2" |
||||
Width="100" |
Width="100" |
||||
Height="50" |
Height="50" |
||||
Stretch="Uniform" |
Stretch="Uniform" |
||||
Fill="Blue" |
Fill="Blue" |
||||
Margin="5" /> |
Margin="5" /> |
||||
<Ellipse Grid.Row="2" |
<Ellipse Grid.Row="2" |
||||
Grid.Column="3" |
Grid.Column="3" |
||||
Width="100" |
Width="100" |
||||
Height="50" |
Height="50" |
||||
Stretch="UniformToFill" |
Stretch="UniformToFill" |
||||
Fill="Blue" |
Fill="Blue" |
||||
Margin="5" /> |
Margin="5" /> |
||||
|
|
||||
</Grid> |
</Grid> |
||||
</UserControl> |
</UserControl> |
||||
|
|||||
@ -1,9 +1,7 @@ |
|||||
<Application |
<Application xmlns="https://github.com/avaloniaui" |
||||
xmlns="https://github.com/avaloniaui" |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
x:Class="VirtualizationDemo.App"> |
||||
x:Class="VirtualizationDemo.App"> |
<Application.Styles> |
||||
<Application.Styles> |
<SimpleTheme /> |
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/> |
</Application.Styles> |
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/> |
</Application> |
||||
</Application.Styles> |
|
||||
</Application> |
|
||||
|
|||||
@ -1,6 +1,5 @@ |
|||||
<Application xmlns="https://github.com/avaloniaui"> |
<Application xmlns="https://github.com/avaloniaui"> |
||||
<Application.Styles> |
<Application.Styles> |
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> |
<SimpleTheme Mode="Light" /> |
||||
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/> |
|
||||
</Application.Styles> |
</Application.Styles> |
||||
</Application> |
</Application> |
||||
|
|||||
@ -0,0 +1,251 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
using Android.Views; |
||||
|
|
||||
|
using Avalonia.Android.Platform.SkiaPlatform; |
||||
|
using Avalonia.Collections.Pooled; |
||||
|
using Avalonia.Input; |
||||
|
using Avalonia.Input.Raw; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Android.Platform.Specific.Helpers |
||||
|
{ |
||||
|
internal class AndroidMotionEventsHelper : IDisposable |
||||
|
{ |
||||
|
private static readonly PooledList<RawPointerPoint> s_intermediatePointsPooledList = new(ClearMode.Never); |
||||
|
private static readonly float s_radiansToDegree = (float)(180f * Math.PI); |
||||
|
private readonly TouchDevice _touchDevice; |
||||
|
private readonly MouseDevice _mouseDevice; |
||||
|
private readonly PenDevice _penDevice; |
||||
|
private readonly TopLevelImpl _view; |
||||
|
private bool _disposed; |
||||
|
|
||||
|
public AndroidMotionEventsHelper(TopLevelImpl view) |
||||
|
{ |
||||
|
_touchDevice = new TouchDevice(); |
||||
|
_penDevice = new PenDevice(); |
||||
|
_mouseDevice = new MouseDevice(); |
||||
|
_view = view; |
||||
|
} |
||||
|
|
||||
|
public bool? DispatchMotionEvent(MotionEvent e, out bool callBase) |
||||
|
{ |
||||
|
callBase = true; |
||||
|
if (_disposed) |
||||
|
{ |
||||
|
return null; |
||||
|
} |
||||
|
|
||||
|
var eventTime = (ulong)DateTime.Now.Millisecond; |
||||
|
var inputRoot = _view.InputRoot; |
||||
|
var actionMasked = e.ActionMasked; |
||||
|
var modifiers = GetModifiers(e.MetaState, e.ButtonState); |
||||
|
|
||||
|
if (actionMasked == MotionEventActions.Move) |
||||
|
{ |
||||
|
for (int index = 0; index < e.PointerCount; index++) |
||||
|
{ |
||||
|
var toolType = e.GetToolType(index); |
||||
|
var device = GetDevice(toolType); |
||||
|
var eventType = toolType == MotionEventToolType.Finger ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; |
||||
|
var point = CreatePoint(e, index); |
||||
|
modifiers |= GetToolModifiers(toolType); |
||||
|
|
||||
|
// ButtonState reports only mouse buttons, but not touch or stylus pointer.
|
||||
|
if (toolType != MotionEventToolType.Mouse) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.LeftMouseButton; |
||||
|
} |
||||
|
|
||||
|
var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)) |
||||
|
{ |
||||
|
IntermediatePoints = new Lazy<IReadOnlyList<RawPointerPoint>?>(() => |
||||
|
{ |
||||
|
var site = e.HistorySize; |
||||
|
s_intermediatePointsPooledList.Clear(); |
||||
|
s_intermediatePointsPooledList.Capacity = site; |
||||
|
|
||||
|
for (int pos = 0; pos < site; pos++) |
||||
|
{ |
||||
|
s_intermediatePointsPooledList.Add(CreateHistoricalPoint(e, index, pos)); |
||||
|
} |
||||
|
|
||||
|
return s_intermediatePointsPooledList; |
||||
|
}) |
||||
|
}; |
||||
|
_view.Input(args); |
||||
|
} |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var index = e.ActionIndex; |
||||
|
var toolType = e.GetToolType(index); |
||||
|
var device = GetDevice(toolType); |
||||
|
modifiers |= GetToolModifiers(toolType); |
||||
|
var point = CreatePoint(e, index); |
||||
|
|
||||
|
if (actionMasked == MotionEventActions.Scroll && toolType == MotionEventToolType.Mouse) |
||||
|
{ |
||||
|
var delta = new Vector(e.GetAxisValue(Axis.Hscroll), e.GetAxisValue(Axis.Vscroll)); |
||||
|
var args = new RawMouseWheelEventArgs(device, eventTime, inputRoot, point.Position, delta, RawInputModifiers.None); |
||||
|
_view.Input(args); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
var eventType = GetActionType(e, actionMasked, toolType); |
||||
|
if (eventType >= 0) |
||||
|
{ |
||||
|
var args = new RawTouchEventArgs(device, eventTime, inputRoot, eventType, point, modifiers, e.GetPointerId(index)); |
||||
|
_view.Input(args); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
private static RawInputModifiers GetModifiers(MetaKeyStates metaState, MotionEventButtonState buttonState) |
||||
|
{ |
||||
|
var modifiers = RawInputModifiers.None; |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.ShiftOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Shift; |
||||
|
} |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.CtrlOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Control; |
||||
|
} |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.AltOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Alt; |
||||
|
} |
||||
|
if (metaState.HasAnyFlag(MetaKeyStates.MetaOn)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.Meta; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Primary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.LeftMouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Secondary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.RightMouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Tertiary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.MiddleMouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Back)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.XButton1MouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.Forward)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.XButton2MouseButton; |
||||
|
} |
||||
|
if (buttonState.HasAnyFlag(MotionEventButtonState.StylusPrimary)) |
||||
|
{ |
||||
|
modifiers |= RawInputModifiers.PenBarrelButton; |
||||
|
} |
||||
|
return modifiers; |
||||
|
} |
||||
|
|
||||
|
#pragma warning disable CA1416 // Validate platform compatibility
|
||||
|
private static RawPointerEventType GetActionType(MotionEvent e, MotionEventActions actionMasked, MotionEventToolType toolType) |
||||
|
{ |
||||
|
var isTouch = toolType == MotionEventToolType.Finger; |
||||
|
var isMouse = toolType == MotionEventToolType.Mouse; |
||||
|
switch (actionMasked) |
||||
|
{ |
||||
|
// DOWN
|
||||
|
case MotionEventActions.Down when !isMouse: |
||||
|
case MotionEventActions.PointerDown when !isMouse: |
||||
|
return isTouch ? RawPointerEventType.TouchBegin : RawPointerEventType.LeftButtonDown; |
||||
|
case MotionEventActions.ButtonPress: |
||||
|
return e.ActionButton switch |
||||
|
{ |
||||
|
MotionEventButtonState.Back => RawPointerEventType.XButton1Down, |
||||
|
MotionEventButtonState.Forward => RawPointerEventType.XButton2Down, |
||||
|
MotionEventButtonState.Primary => RawPointerEventType.LeftButtonDown, |
||||
|
MotionEventButtonState.Secondary => RawPointerEventType.RightButtonDown, |
||||
|
MotionEventButtonState.StylusPrimary => RawPointerEventType.LeftButtonDown, |
||||
|
MotionEventButtonState.StylusSecondary => RawPointerEventType.RightButtonDown, |
||||
|
MotionEventButtonState.Tertiary => RawPointerEventType.MiddleButtonDown, |
||||
|
_ => RawPointerEventType.LeftButtonDown |
||||
|
}; |
||||
|
// UP
|
||||
|
case MotionEventActions.Up when !isMouse: |
||||
|
case MotionEventActions.PointerUp when !isMouse: |
||||
|
return isTouch ? RawPointerEventType.TouchEnd : RawPointerEventType.LeftButtonUp; |
||||
|
case MotionEventActions.ButtonRelease: |
||||
|
return e.ActionButton switch |
||||
|
{ |
||||
|
MotionEventButtonState.Back => RawPointerEventType.XButton1Up, |
||||
|
MotionEventButtonState.Forward => RawPointerEventType.XButton2Up, |
||||
|
MotionEventButtonState.Primary => RawPointerEventType.LeftButtonUp, |
||||
|
MotionEventButtonState.Secondary => RawPointerEventType.RightButtonUp, |
||||
|
MotionEventButtonState.StylusPrimary => RawPointerEventType.LeftButtonUp, |
||||
|
MotionEventButtonState.StylusSecondary => RawPointerEventType.RightButtonUp, |
||||
|
MotionEventButtonState.Tertiary => RawPointerEventType.MiddleButtonUp, |
||||
|
_ => RawPointerEventType.LeftButtonUp |
||||
|
}; |
||||
|
// MOVE
|
||||
|
case MotionEventActions.Outside: |
||||
|
case MotionEventActions.HoverMove: |
||||
|
case MotionEventActions.Move: |
||||
|
return isTouch ? RawPointerEventType.TouchUpdate : RawPointerEventType.Move; |
||||
|
// CANCEL
|
||||
|
case MotionEventActions.Cancel: |
||||
|
return isTouch ? RawPointerEventType.TouchCancel : RawPointerEventType.LeaveWindow; |
||||
|
default: |
||||
|
return (RawPointerEventType)(-1); |
||||
|
} |
||||
|
} |
||||
|
#pragma warning restore CA1416 // Validate platform compatibility
|
||||
|
|
||||
|
private IPointerDevice GetDevice(MotionEventToolType type) |
||||
|
{ |
||||
|
return type switch |
||||
|
{ |
||||
|
MotionEventToolType.Mouse => _mouseDevice, |
||||
|
MotionEventToolType.Stylus => _penDevice, |
||||
|
MotionEventToolType.Eraser => _penDevice, |
||||
|
MotionEventToolType.Finger => _touchDevice, |
||||
|
_ => _touchDevice |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private RawPointerPoint CreatePoint(MotionEvent e, int index) |
||||
|
{ |
||||
|
return new RawPointerPoint |
||||
|
{ |
||||
|
Position = new Point(e.GetX(index), e.GetY(index)) / _view.RenderScaling, |
||||
|
Pressure = Math.Min(e.GetPressure(index), 1), // android pressure can depend on the device, can be mixed up with "GetSize", may be larger than 1.0f on some devices
|
||||
|
Twist = e.GetOrientation(index) * s_radiansToDegree |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private RawPointerPoint CreateHistoricalPoint(MotionEvent e, int index, int pos) |
||||
|
{ |
||||
|
return new RawPointerPoint |
||||
|
{ |
||||
|
Position = new Point(e.GetHistoricalX(index, pos), e.GetHistoricalY(index, pos)) / _view.RenderScaling, |
||||
|
Pressure = Math.Min(e.GetHistoricalPressure(index, pos), 1), |
||||
|
Twist = e.GetHistoricalOrientation(index, pos) * s_radiansToDegree |
||||
|
}; |
||||
|
} |
||||
|
|
||||
|
private static RawInputModifiers GetToolModifiers(MotionEventToolType toolType) |
||||
|
{ |
||||
|
// Android "Eraser" indicates Inverted pen OR actual Eraser. So we have to go both here.
|
||||
|
return toolType == MotionEventToolType.Eraser ? RawInputModifiers.PenInverted | RawInputModifiers.PenEraser : RawInputModifiers.None; |
||||
|
} |
||||
|
|
||||
|
public void Dispose() |
||||
|
{ |
||||
|
_disposed = true; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
@ -1,85 +0,0 @@ |
|||||
using System; |
|
||||
using Android.Views; |
|
||||
using Avalonia.Input; |
|
||||
using Avalonia.Input.Raw; |
|
||||
using Avalonia.Platform; |
|
||||
|
|
||||
namespace Avalonia.Android.Platform.Specific.Helpers |
|
||||
{ |
|
||||
public class AndroidTouchEventsHelper<TView> : IDisposable where TView : ITopLevelImpl, IAndroidView |
|
||||
{ |
|
||||
private TView _view; |
|
||||
public bool HandleEvents { get; set; } |
|
||||
|
|
||||
public AndroidTouchEventsHelper(TView view, Func<IInputRoot> getInputRoot, Func<MotionEvent, int, Point> getPointfunc) |
|
||||
{ |
|
||||
this._view = view; |
|
||||
HandleEvents = true; |
|
||||
_getPointFunc = getPointfunc; |
|
||||
_getInputRoot = getInputRoot; |
|
||||
} |
|
||||
|
|
||||
private TouchDevice _touchDevice = new TouchDevice(); |
|
||||
private Func<MotionEvent, int, Point> _getPointFunc; |
|
||||
private Func<IInputRoot> _getInputRoot; |
|
||||
|
|
||||
public bool? DispatchTouchEvent(MotionEvent e, out bool callBase) |
|
||||
{ |
|
||||
if (!HandleEvents) |
|
||||
{ |
|
||||
callBase = true; |
|
||||
return null; |
|
||||
} |
|
||||
|
|
||||
var eventTime = DateTime.Now; |
|
||||
|
|
||||
//Basic touch support
|
|
||||
var pointerEventType = e.Action switch |
|
||||
{ |
|
||||
MotionEventActions.Down => RawPointerEventType.TouchBegin, |
|
||||
MotionEventActions.Up => RawPointerEventType.TouchEnd, |
|
||||
MotionEventActions.Cancel => RawPointerEventType.TouchCancel, |
|
||||
_ => RawPointerEventType.TouchUpdate |
|
||||
}; |
|
||||
|
|
||||
if (e.Action.HasFlag(MotionEventActions.PointerDown)) |
|
||||
{ |
|
||||
pointerEventType = RawPointerEventType.TouchBegin; |
|
||||
} |
|
||||
|
|
||||
if (e.Action.HasFlag(MotionEventActions.PointerUp)) |
|
||||
{ |
|
||||
pointerEventType = RawPointerEventType.TouchEnd; |
|
||||
} |
|
||||
|
|
||||
for (int i = 0; i < e.PointerCount; i++) |
|
||||
{ |
|
||||
//if point is in view otherwise it's possible avalonia not to find the proper window to dispatch the event
|
|
||||
var point = _getPointFunc(e, i); |
|
||||
|
|
||||
double x = _view.View.GetX(); |
|
||||
double y = _view.View.GetY(); |
|
||||
double r = x + _view.View.Width; |
|
||||
double b = y + _view.View.Height; |
|
||||
|
|
||||
if (x <= point.X && r >= point.X && y <= point.Y && b >= point.Y) |
|
||||
{ |
|
||||
var inputRoot = _getInputRoot(); |
|
||||
|
|
||||
var mouseEvent = new RawTouchEventArgs(_touchDevice, (uint)eventTime.Ticks, inputRoot, |
|
||||
i == e.ActionIndex ? pointerEventType : RawPointerEventType.TouchUpdate, point, RawInputModifiers.None, e.GetPointerId(i)); |
|
||||
_view.Input(mouseEvent); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
callBase = true; |
|
||||
//if return false events for move and up are not received!!!
|
|
||||
return e.Action != MotionEventActions.Up; |
|
||||
} |
|
||||
|
|
||||
public void Dispose() |
|
||||
{ |
|
||||
HandleEvents = false; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace Avalonia.Controls.Templates |
||||
|
{ |
||||
|
public interface ITemplateResult |
||||
|
{ |
||||
|
public object? Result { get; } |
||||
|
public INameScope NameScope { get; } |
||||
|
} |
||||
|
} |
||||
@ -1,9 +1,10 @@ |
|||||
namespace Avalonia.Controls.Templates |
namespace Avalonia.Controls.Templates |
||||
{ |
{ |
||||
public class TemplateResult<T> |
public class TemplateResult<T> : ITemplateResult |
||||
{ |
{ |
||||
public T Result { get; } |
public T Result { get; } |
||||
public INameScope NameScope { get; } |
public INameScope NameScope { get; } |
||||
|
object? ITemplateResult.Result => Result; |
||||
|
|
||||
public TemplateResult(T result, INameScope nameScope) |
public TemplateResult(T result, INameScope nameScope) |
||||
{ |
{ |
||||
Some files were not shown because too many files changed in this diff
Loading…
Reference in new issue