Browse Source

Merge branch 'master' into on-loaded-unloaded

pull/11828/head
Max Katz 3 years ago
committed by GitHub
parent
commit
7238fe7da1
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  2. 12
      samples/ControlCatalog.Android/MainActivity.cs
  3. 66
      samples/ControlCatalog.Android/Resources/drawable-night-v31/avalonia_anim.xml
  4. 71
      samples/ControlCatalog.Android/Resources/drawable-v31/avalonia_anim.xml
  5. 21
      samples/ControlCatalog.Android/Resources/values-v31/styles.xml
  6. 11
      samples/ControlCatalog.Android/Resources/values/styles.xml
  7. 35
      samples/ControlCatalog.Android/SplashActivity.cs
  8. 5
      samples/MobileSandbox.Android/MainActivity.cs
  9. 10
      samples/MobileSandbox.Android/MobileSandbox.Android.csproj
  10. 66
      samples/MobileSandbox.Android/Resources/drawable-night-v31/avalonia_anim.xml
  11. 71
      samples/MobileSandbox.Android/Resources/drawable-v31/avalonia_anim.xml
  12. 4
      samples/MobileSandbox.Android/Resources/values-night/colors.xml
  13. 16
      samples/MobileSandbox.Android/Resources/values-v31/styles.xml
  14. 7
      samples/MobileSandbox.Android/Resources/values/styles.xml
  15. 17
      samples/MobileSandbox.Android/SplashActivity.cs
  16. 4
      samples/SafeAreaDemo.Android/MainActivity.cs
  17. 66
      samples/SafeAreaDemo.Android/Resources/drawable-night-v31/avalonia_anim.xml
  18. 71
      samples/SafeAreaDemo.Android/Resources/drawable-v31/avalonia_anim.xml
  19. 4
      samples/SafeAreaDemo.Android/Resources/values-night/colors.xml
  20. 16
      samples/SafeAreaDemo.Android/Resources/values-v31/styles.xml
  21. 7
      samples/SafeAreaDemo.Android/Resources/values/styles.xml
  22. 13
      samples/SafeAreaDemo.Android/SafeAreaDemo.Android.csproj
  23. 30
      samples/SafeAreaDemo.Android/SplashActivity.cs
  24. 60
      src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs
  25. 88
      src/Android/Avalonia.Android/AvaloniaMainActivity.cs
  26. 40
      src/Android/Avalonia.Android/AvaloniaSplashActivity.cs
  27. 1
      src/Avalonia.Base/Input/Pointer.cs
  28. 4
      src/Avalonia.Base/Media/MediaContext.cs
  29. 2
      src/Avalonia.Base/Platform/IDrawingContextImpl.cs
  30. 4
      src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs
  31. 1
      src/Avalonia.Base/Rendering/RenderLoop.cs
  32. 5
      src/Avalonia.Base/Threading/Dispatcher.Invoke.cs
  33. 15
      src/Avalonia.Controls/LayoutTransformControl.cs
  34. 8
      src/Avalonia.Controls/MenuItem.cs
  35. 2
      src/Avalonia.Diagnostics/Diagnostics/Views/PropertyValueEditorView.cs
  36. 145
      src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml
  37. 46
      src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml.cs
  38. 6
      src/Avalonia.Dialogs/Internal/ManagedFileChooserFilterViewModel.cs
  39. 3
      src/Avalonia.Themes.Simple/Controls/TransitioningContentControl.xaml
  40. 1
      src/tools/Avalonia.Generators/Avalonia.Generators.csproj
  41. 13
      tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs
  42. 19
      tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs
  43. 12
      tests/Avalonia.Controls.UnitTests/MenuItemTests.cs
  44. 1
      tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

9
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -10,6 +10,11 @@
<AndroidPackageFormat>apk</AndroidPackageFormat>
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\drawable-night-v31\avalonia_anim.xml" />
<None Remove="Resources\drawable-v31\avalonia_anim.xml" />
<None Remove="Resources\values-v31\styles.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="..\..\build\Assets\Icon.png">
<Link>Resources\drawable\Icon.png</Link>
@ -37,6 +42,10 @@
<AndroidEnvironment Condition="'$(IsEmulator)'!='True'" Include="environment.device.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />

12
samples/ControlCatalog.Android/MainActivity.cs

@ -5,8 +5,16 @@ using Avalonia.Android;
namespace ControlCatalog.Android
{
[Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.Main", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity
[Activity(Label = "ControlCatalog.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity<App>
{
protected override Avalonia.AppBuilder CustomizeAppBuilder(Avalonia.AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.AfterSetup(_ =>
{
Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
});
}
}
}

66
samples/ControlCatalog.Android/Resources/drawable-night-v31/avalonia_anim.xml

@ -0,0 +1,66 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

71
samples/ControlCatalog.Android/Resources/drawable-v31/avalonia_anim.xml

@ -0,0 +1,71 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="500"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

21
samples/ControlCatalog.Android/Resources/values-v31/styles.xml

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MyTheme">
</style>
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowSplashScreenBackground">@color/splash_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/avalonia_anim</item>
<item name="android:windowSplashScreenAnimationDuration">1000</item>
<item name="postSplashScreenTheme">@style/MyTheme.Main</item>
</style>
<style name="MyTheme.Main"
parent ="MyTheme.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
</style>
</resources>

11
samples/ControlCatalog.Android/Resources/values/styles.xml

@ -6,16 +6,7 @@
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.DayNight.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="MyTheme.Splash" parent ="MyTheme.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowContentOverlay">@null</item>
</style>
<style name="MyTheme.Main" parent ="MyTheme.NoActionBar">
<item name="android:windowIsTranslucent">true</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

35
samples/ControlCatalog.Android/SplashActivity.cs

@ -1,35 +0,0 @@
using Android.App;
using Android.Content;
using Android.Content.PM;
using Android.OS;
using Avalonia.Android;
namespace ControlCatalog.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : AvaloniaSplashActivity<App>
{
protected override Avalonia.AppBuilder CustomizeAppBuilder(Avalonia.AppBuilder builder)
{
return base.CustomizeAppBuilder(builder)
.AfterSetup(_ =>
{
Pages.EmbedSample.Implementation = new EmbedSampleAndroid();
});
}
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
protected override void OnResume()
{
base.OnResume();
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
Finish();
}
}
}

5
samples/MobileSandbox.Android/MainActivity.cs

@ -1,12 +1,11 @@
using Android.App;
using Android.Content.PM;
using Avalonia;
using Avalonia.Android;
namespace MobileSandbox.Android
{
[Activity(Label = "MobileSandbox.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity
[Activity(Label = "MobileSandbox.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize)]
public class MainActivity : AvaloniaMainActivity<App>
{
}
}

10
samples/MobileSandbox.Android/MobileSandbox.Android.csproj

@ -10,6 +10,12 @@
<AndroidPackageFormat>apk</AndroidPackageFormat>
<MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\drawable-night-v31\avalonia_anim.xml" />
<None Remove="Resources\drawable-v31\avalonia_anim.xml" />
<None Remove="Resources\values-v31\styles.xml" />
<None Remove="Resources\values-night\colors.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="..\..\build\Assets\Icon.png">
<Link>Resources\drawable\Icon.png</Link>
@ -37,6 +43,10 @@
<AndroidEnvironment Condition="'$(IsEmulator)'!='True'" Include="environment.device.txt" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Xamarin.AndroidX.Core.SplashScreen" Version="1.0.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" />
<ProjectReference Include="..\MobileSandbox\MobileSandbox.csproj" />

66
samples/MobileSandbox.Android/Resources/drawable-night-v31/avalonia_anim.xml

@ -0,0 +1,66 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

71
samples/MobileSandbox.Android/Resources/drawable-v31/avalonia_anim.xml

@ -0,0 +1,71 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="500"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

4
samples/MobileSandbox.Android/Resources/values-night/colors.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_background">#212121</color>
</resources>

16
samples/MobileSandbox.Android/Resources/values-v31/styles.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MyTheme">
</style>
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowSplashScreenBackground">@color/splash_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/avalonia_anim</item>
<item name="android:windowSplashScreenAnimationDuration">1000</item>
</style>
</resources>

7
samples/MobileSandbox.Android/Resources/values/styles.xml

@ -6,12 +6,7 @@
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="MyTheme.Splash" parent ="MyTheme.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

17
samples/MobileSandbox.Android/SplashActivity.cs

@ -1,17 +0,0 @@
using Android.App;
using Android.Content;
using Avalonia.Android;
namespace MobileSandbox.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : AvaloniaSplashActivity<App>
{
protected override void OnResume()
{
base.OnResume();
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
}
}
}

4
samples/SafeAreaDemo.Android/MainActivity.cs

@ -4,8 +4,8 @@ using Avalonia.Android;
namespace SafeAreaDemo.Android
{
[Activity(Label = "SafeAreaDemo.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity
[Activity(Label = "SafeAreaDemo.Android", Theme = "@style/MyTheme.NoActionBar", Icon = "@drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize | ConfigChanges.UiMode)]
public class MainActivity : AvaloniaMainActivity<App>
{
}
}

66
samples/SafeAreaDemo.Android/Resources/drawable-night-v31/avalonia_anim.xml

@ -0,0 +1,66 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="1000"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

71
samples/SafeAreaDemo.Android/Resources/drawable-v31/avalonia_anim.xml

@ -0,0 +1,71 @@
<animated-vector
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt">
<aapt:attr name="android:drawable">
<vector
android:name="vector"
android:width="128dp"
android:height="128dp"
android:viewportWidth="128"
android:viewportHeight="128">
<group
android:name="wrapper"
android:translateX="21"
android:translateY="21">
<group android:name="group">
<path
android:name="path"
android:pathData="M 74.853 85.823 L 75.368 85.823 C 80.735 85.823 85.144 81.803 85.761 76.602 L 85.836 41.76 C 85.225 18.593 66.254 0 42.939 0 C 19.24 0 0.028 19.212 0.028 42.912 C 0.028 66.357 18.831 85.418 42.18 85.823 L 74.853 85.823 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
<path
android:name="path_1"
android:pathData="M 43.059 14.614 C 29.551 14.614 18.256 24.082 15.445 36.743 C 18.136 37.498 20.109 39.968 20.109 42.899 C 20.109 45.831 18.136 48.301 15.445 49.055 C 18.256 61.716 29.551 71.184 43.059 71.184 C 47.975 71.184 52.599 69.93 56.628 67.723 L 56.628 70.993 L 71.344 70.993 L 71.344 44.072 C 71.357 43.714 71.344 43.26 71.344 42.899 C 71.344 27.278 58.68 14.614 43.059 14.614 Z M 29.51 42.899 C 29.51 35.416 35.576 29.35 43.059 29.35 C 50.541 29.35 56.607 35.416 56.607 42.899 C 56.607 50.382 50.541 56.448 43.059 56.448 C 35.576 56.448 29.51 50.382 29.51 42.899 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"
android:fillType="evenOdd"/>
<path
android:name="path_2"
android:pathData="M 18.105 42.88 C 18.105 45.38 16.078 47.407 13.579 47.407 C 11.079 47.407 9.052 45.38 9.052 42.88 C 9.052 40.381 11.079 38.354 13.579 38.354 C 16.078 38.354 18.105 40.381 18.105 42.88 Z"
android:fillColor="#00ffffff"
android:strokeWidth="1"/>
</group>
</group>
</vector>
</aapt:attr>
<target android:name="path_2">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:duration="500"
android:valueFrom="#00ffffff"
android:valueTo="#f9f9fb"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
<target android:name="path_1">
<aapt:attr name="android:animation">
<objectAnimator
android:propertyName="fillColor"
android:startOffset="100"
android:duration="900"
android:valueFrom="#00ffffff"
android:valueTo="#161c2d"
android:valueType="colorType"
android:interpolator="@android:interpolator/fast_out_slow_in"/>
</aapt:attr>
</target>
</animated-vector>

4
samples/SafeAreaDemo.Android/Resources/values-night/colors.xml

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="splash_background">#212121</color>
</resources>

16
samples/SafeAreaDemo.Android/Resources/values-v31/styles.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8" ?>
<resources>
<style name="MyTheme">
</style>
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowBackground">@null</item>
<item name="android:windowNoTitle">true</item>
<item name="android:windowSplashScreenBackground">@color/splash_background</item>
<item name="android:windowSplashScreenAnimatedIcon">@drawable/avalonia_anim</item>
<item name="android:windowSplashScreenAnimationDuration">1000</item>
</style>
</resources>

7
samples/SafeAreaDemo.Android/Resources/values/styles.xml

@ -6,12 +6,7 @@
<style name="MyTheme.NoActionBar" parent="@style/Theme.AppCompat.NoActionBar">
<item name="android:windowActionBar">false</item>
<item name="android:windowNoTitle">true</item>
</style>
<style name="MyTheme.Splash" parent ="MyTheme.NoActionBar">
<item name="android:windowBackground">@drawable/splash_screen</item>
<item name="android:windowContentOverlay">@null</item>
<item name="android:windowNoTitle">true</item>
</style>
</resources>

13
samples/SafeAreaDemo.Android/SafeAreaDemo.Android.csproj

@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0-android</TargetFramework>
@ -12,13 +12,14 @@
</PropertyGroup>
<ItemGroup>
<AndroidResource Include="Icon.png">
<Link>Resources\drawable\Icon.png</Link>
</AndroidResource>
<ProjectReference Include="..\SafeAreaDemo\SafeAreaDemo.csproj" />
<ProjectReference Include="..\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SafeAreaDemo\SafeAreaDemo.csproj" />
<ProjectReference Include="..\..\src\Android\Avalonia.Android\Avalonia.Android.csproj" />
<AndroidResource Include="..\..\build\Assets\Icon.png">
<Link>Resources\drawable\Icon.png</Link>
</AndroidResource>
</ItemGroup>
</Project>

30
samples/SafeAreaDemo.Android/SplashActivity.cs

@ -1,30 +0,0 @@
using Android.App;
using Android.Content;
using Android.OS;
using Avalonia;
using Avalonia.Android;
using Application = Android.App.Application;
namespace SafeAreaDemo.Android
{
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : AvaloniaSplashActivity<App>
{
protected override AppBuilder CustomizeAppBuilder(AppBuilder builder)
{
return base.CustomizeAppBuilder(builder);
}
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
}
protected override void OnResume()
{
base.OnResume();
StartActivity(new Intent(Application.Context, typeof(MainActivity)));
}
}
}

60
src/Android/Avalonia.Android/AvaloniaMainActivity.App.cs

@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Android
{
partial class AvaloniaMainActivity<TApp> where TApp : Application, new()
{
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
private static AppBuilder? s_appBuilder;
internal static object ViewContent;
public object Content
{
get
{
return ViewContent;
}
set
{
ViewContent = value;
if (View != null)
View.Content = value;
}
}
protected AppBuilder CreateAppBuilder()
{
var builder = AppBuilder.Configure<TApp>();
return CustomizeAppBuilder(builder);
}
private void InitializeApp()
{
if (s_appBuilder == null)
{
var builder = CreateAppBuilder();
builder.SetupWithLifetime(new SingleViewLifetime());
s_appBuilder = builder;
}
View = new AvaloniaView(this);
if (ViewContent != null)
{
View.Content = ViewContent;
}
if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime)
{
lifetime.View = View;
}
}
}
}

88
src/Android/Avalonia.Android/AvaloniaMainActivity.cs

@ -11,27 +11,49 @@ using AndroidX.AppCompat.App;
namespace Avalonia.Android
{
public abstract class AvaloniaMainActivity : AppCompatActivity, IActivityResultHandler, IActivityNavigationService
public class AvaloniaMainActivity : AppCompatActivity, IActivityResultHandler, IActivityNavigationService
{
internal static object ViewContent;
public Action<int, Result, Intent> ActivityResult { get; set; }
public Action<int, string[], Permission[]> RequestPermissionsResult { get; set; }
public event EventHandler<AndroidBackRequestedEventArgs> BackRequested;
public override void OnBackPressed()
{
var eventArgs = new AndroidBackRequestedEventArgs();
BackRequested?.Invoke(this, eventArgs);
if (!eventArgs.Handled)
{
base.OnBackPressed();
}
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
ActivityResult?.Invoke(requestCode, resultCode, data);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
RequestPermissionsResult?.Invoke(requestCode, permissions, grantResults);
}
}
public abstract partial class AvaloniaMainActivity<TApp> : AvaloniaMainActivity where TApp : Application, new()
{
internal AvaloniaView View;
private GlobalLayoutListener _listener;
protected override void OnCreate(Bundle savedInstanceState)
{
View = new AvaloniaView(this);
if (ViewContent != null)
{
View.Content = ViewContent;
}
InitializeApp();
if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime)
{
lifetime.View = View;
}
base.OnCreate(savedInstanceState);
SetContentView(View);
@ -41,20 +63,6 @@ namespace Avalonia.Android
View.ViewTreeObserver?.AddOnGlobalLayoutListener(_listener);
}
public object Content
{
get
{
return ViewContent;
}
set
{
ViewContent = value;
if (View != null)
View.Content = value;
}
}
protected override void OnResume()
{
base.OnResume();
@ -66,20 +74,6 @@ namespace Avalonia.Android
}
}
public event EventHandler<AndroidBackRequestedEventArgs> BackRequested;
public override void OnBackPressed()
{
var eventArgs = new AndroidBackRequestedEventArgs();
BackRequested?.Invoke(this, eventArgs);
if (!eventArgs.Handled)
{
base.OnBackPressed();
}
}
protected override void OnDestroy()
{
View.Content = null;
@ -89,20 +83,6 @@ namespace Avalonia.Android
base.OnDestroy();
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
ActivityResult?.Invoke(requestCode, resultCode, data);
}
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Permission[] grantResults)
{
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
RequestPermissionsResult?.Invoke(requestCode, permissions, grantResults);
}
class GlobalLayoutListener : Java.Lang.Object, ViewTreeObserver.IOnGlobalLayoutListener
{
private AvaloniaView _view;

40
src/Android/Avalonia.Android/AvaloniaSplashActivity.cs

@ -1,40 +0,0 @@
using Android.OS;
using AndroidX.AppCompat.App;
namespace Avalonia.Android
{
public abstract class AvaloniaSplashActivity : AppCompatActivity
{
protected abstract AppBuilder CreateAppBuilder();
private static AppBuilder s_appBuilder;
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (s_appBuilder == null)
{
var builder = CreateAppBuilder();
var lifetime = new SingleViewLifetime();
builder.SetupWithLifetime(lifetime);
s_appBuilder = builder;
}
}
}
public abstract class AvaloniaSplashActivity<TApp> : AvaloniaSplashActivity where TApp : Application, new()
{
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
protected override AppBuilder CreateAppBuilder()
{
var builder = AppBuilder.Configure<TApp>();
return CustomizeAppBuilder(builder);
}
}
}

1
src/Avalonia.Base/Input/Pointer.cs

@ -88,7 +88,6 @@ namespace Avalonia.Input
/// Captures pointer input to the specified gesture recognizer.
/// </summary>
/// <param name="gestureRecognizer">The gesture recognizer.</param>
/// </remarks>
internal void CaptureGestureRecognizer(GestureRecognizer? gestureRecognizer)
{
if (CapturedGestureRecognizer != gestureRecognizer)

4
src/Avalonia.Base/Media/MediaContext.cs

@ -213,10 +213,10 @@ internal partial class MediaContext : ICompositorScheduler
}
/// <summary>
/// Executes the <param name="callback">callback</param> in the next iteration of the current UI-thread
/// Executes the <paramref name="callback">callback</paramref> in the next iteration of the current UI-thread
/// render loop / layout pass that.
/// </summary>
/// <param name="callback">Code to execute.</param>
/// <param name="callback"></param>
public void BeginInvokeOnRender(Action callback)
{
if (_invokeOnRenderCallbacks == null)

2
src/Avalonia.Base/Platform/IDrawingContextImpl.cs

@ -161,7 +161,7 @@ namespace Avalonia.Platform
void PopGeometryClip();
/// <summary>
/// Get Fetaure from type
/// <summary>
/// Attempts to get an optional feature from the drawing context implementation
/// </summary>

4
src/Avalonia.Base/PropertyStore/EffectiveValue`1.cs

@ -216,7 +216,7 @@ namespace Avalonia.PropertyStore
valueChanged = !EqualityComparer<T>.Default.Equals(Value, v);
Value = v;
Priority = priority;
if (_uncommon is not null)
if (!isCoercedDefaultValue && _uncommon is not null)
_uncommon._uncoercedValue = value;
}
@ -225,7 +225,7 @@ namespace Avalonia.PropertyStore
baseValueChanged = !EqualityComparer<T>.Default.Equals(_baseValue, v);
_baseValue = v;
BasePriority = priority;
if (_uncommon is not null)
if (!isCoercedDefaultValue && _uncommon is not null)
_uncommon._uncoercedBaseValue = value;
}

1
src/Avalonia.Base/Rendering/RenderLoop.cs

@ -42,7 +42,6 @@ namespace Avalonia.Rendering
/// Initializes a new instance of the <see cref="RenderLoop"/> class.
/// </summary>
/// <param name="timer">The render timer.</param>
/// <param name="dispatcher">The UI thread dispatcher.</param>
public RenderLoop(IRenderTimer timer)
{
_timer = timer;

5
src/Avalonia.Base/Threading/Dispatcher.Invoke.cs

@ -581,11 +581,6 @@ public partial class Dispatcher
/// <param name="action">
/// A Func&lt;Task&lt;TResult&gt;&gt; delegate to invoke through the dispatcher.
/// </param>
/// <param name="priority">
/// The priority that determines in what order the specified
/// callback is invoked relative to the other pending operations
/// in the Dispatcher.
/// </param>
/// <returns>
/// An task that completes after the task returned from callback finishes
/// </returns>

15
src/Avalonia.Controls/LayoutTransformControl.cs

@ -215,7 +215,7 @@ namespace Avalonia.Controls
/// <summary>
/// Transformation matrix corresponding to _matrixTransform.
/// </summary>
private Matrix _transformation;
private Matrix _transformation = Matrix.Identity;
private IDisposable? _transformChangedEvent;
/// <summary>
@ -256,13 +256,16 @@ namespace Avalonia.Controls
/// </remarks>
private void ApplyLayoutTransform()
{
if (LayoutTransform == null)
return;
// Get the transform matrix and apply it
_transformation = RoundMatrix(LayoutTransform.Value, DecimalsAfterRound);
var matrix = LayoutTransform is null ?
Matrix.Identity :
RoundMatrix(LayoutTransform.Value, DecimalsAfterRound);
if (_transformation == matrix)
return;
_matrixTransform.Matrix = _transformation;
_transformation = matrix;
_matrixTransform.Matrix = matrix;
// New transform means re-layout is necessary
InvalidateMeasure();

8
src/Avalonia.Controls/MenuItem.cs

@ -394,6 +394,14 @@ namespace Avalonia.Controls
_isEmbeddedInMenu = parent?.FindLogicalAncestorOfType<IMenu>(true) != null;
}
/// <inheritdoc />
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnAttachedToVisualTree(e);
TryUpdateCanExecute();
}
protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
{
// This will cause the hotkey manager to dispose the observer and the reference to this control

2
src/Avalonia.Diagnostics/Diagnostics/Views/PropertyValueEditorView.cs

@ -265,7 +265,7 @@ namespace Avalonia.Diagnostics.Views
static bool IsValidNumeric(Type? type)
{
if (type == null)
if (type == null || type.IsEnum == true)
{
return false;
}

145
src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml

@ -6,106 +6,71 @@
MinWidth="430"
MinHeight="475"
Title="About Avalonia"
Background="Purple"
FontFamily="/Assets/Roboto-Light.ttf#Roboto"
x:Class="Avalonia.Dialogs.AboutAvaloniaDialog"
x:DataType="dialogs:AboutAvaloniaDialog">
<Window.Styles>
<Style>
<Style.Resources>
<DrawingGroup x:Key="AvaloniaLogo">
<GeometryDrawing Geometry="m 150.66581 0.66454769 c -54.77764 0 -101.0652 38.86360031 -112.62109 90.33008031 a 26.1 26.1 0 0 1 18.92187 25.070312 26.1 26.1 0 0 1 -18.91992 25.08202 c 11.56024 51.46073 57.8456 90.31837 112.61914 90.31837 63.37832 0 115.40039 -52.02207 115.40039 -115.40039 0 -63.378322 -52.02207 -115.40039231 -115.40039 -115.40039231 z m 0 60.00000031 c 30.95192 0 55.40039 24.44847 55.40039 55.400392 0 30.9519 -24.44847 55.40039 -55.40039 55.40039 -30.95191 0 -55.40039 -24.44848 -55.40039 -55.40039 0 -30.951922 24.44848 -55.400392 55.40039 -55.400392 z">
<GeometryDrawing.Brush>
<LinearGradientBrush StartPoint="272,411" EndPoint="435,248">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#B0B0B0" Offset="0" />
<GradientStop Color="#FFFFFF" Offset="0.6784" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</GeometryDrawing.Brush>
</GeometryDrawing>
<GeometryDrawing Brush="#B0B0B0">
<GeometryDrawing.Geometry>
<EllipseGeometry Rect="9.6,95.8,40.6,40.6" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="White">
<GeometryDrawing.Geometry>
<RectangleGeometry Rect="206.06355, 114.56503,60,116.2" />
</GeometryDrawing.Geometry>
</GeometryDrawing>
<GeometryDrawing Brush="#FF8B44AC" Geometry="M215 246.5h1.5a30 30 0 0 0 29.8-26.5l.2-100a123.2 123.2 0 1 0-125.4 126.5H215Z"/>
<GeometryDrawing Brush="#FFF9F9FB" Geometry="M123.7 42a81.3 81.3 0 0 0-79.3 63.5 18.4 18.4 0 0 1 0 35.4 81.3 81.3 0 0 0 118.2 53.6v9.4H205v-80.7A81.2 81.2 0 0 0 123.7 42Zm-39 81.2a39 39 0 1 1 77.9 0 39 39 0 0 1-77.8 0Z"/>
<GeometryDrawing Brush="#FFF9F9FB" Geometry="M52 123.2a13 13 0 1 1-26 0 13 13 0 0 1 26 0Z"/>
</DrawingGroup>
</Style.Resources>
</Style>
<Style Selector="Rectangle.Abstract">
<Setter Property="Fill" Value="White" />
<Setter Property="Width" Value="750" />
<Setter Property="Height" Value="700" />
</Style>
<Style Selector="Button.Hyperlink">
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Margin" Value="-5"/>
<Setter Property="Foreground" Value="#419df2" />
<Setter Property="Command" Value="{Binding OpenBrowser}" />
<Setter Property="Content" Value="{Binding $self.CommandParameter}" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Cursor" Value="Hand" />
</Style>
</Window.Styles>
<Grid Background="#4A255D">
<Canvas>
<Rectangle Classes="Abstract" Canvas.Top="90" Opacity="0.132">
<Rectangle.RenderTransform>
<RotateTransform Angle="-2" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Classes="Abstract" Canvas.Top="95" Opacity="0.3">
<Rectangle.RenderTransform>
<RotateTransform Angle="-4" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Classes="Abstract" Canvas.Top="100" Opacity="0.3">
<Rectangle.RenderTransform>
<RotateTransform Angle="-8" />
</Rectangle.RenderTransform>
</Rectangle>
<Rectangle Classes="Abstract" Canvas.Top="105" Opacity="0.7">
<Rectangle.RenderTransform>
<RotateTransform Angle="-12" />
</Rectangle.RenderTransform>
</Rectangle>
</Canvas>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="18">
<Border Height="70" Width="70">
<Image>
<Image.Source>
<DrawingImage Drawing="{DynamicResource AvaloniaLogo}"/>
</Image.Source>
</Image>
</Border>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10,-10,0,0">
<TextBlock Text="{Binding Version, StringFormat=Avalonia {0}}" FontSize="40" Foreground="White" />
<TextBlock Text="Development Build" IsVisible="{Binding IsDevelopmentBuild}" Margin="0,-10,0,0" FontSize="15" Foreground="White" />
</StackPanel>
</StackPanel>
<StackPanel HorizontalAlignment="Stretch" VerticalAlignment="Center" Spacing="20" Margin="10 60 10 0">
<TextBlock Text="This product is built with the Avalonia cross-platform UI Framework. &#x0A;&#x0A;Avalonia is made possible by the generous support of it's contributors and community." TextWrapping="Wrap" TextAlignment="Center" HorizontalAlignment="Center" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
<TextBlock Text="Main source repository | " />
<Button Classes="Hyperlink" CommandParameter="https://github.com/AvaloniaUI/Avalonia/" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
<TextBlock Text="Documentation and Information | " />
<Button Classes="Hyperlink" CommandParameter="https://avaloniaui.net/" />
</StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
<TextBlock Text="Chat Room | " />
<Button Classes="Hyperlink" CommandParameter="https://t.me/Avalonia" />
</StackPanel>
</StackPanel>
<StackPanel VerticalAlignment="Bottom" Margin="10">
<TextBlock Text="© 2022 The Avalonia Project" TextWrapping="Wrap" HorizontalAlignment="Center" />
</StackPanel>
<Grid RowDefinitions="Auto, *" Margin="35,35,35,15">
<!-- Header -->
<Grid RowDefinitions="*, Auto, Auto">
<Image Width="130"
Margin="0, 0,0, 20"
Grid.Row="0">
<Image.Source>
<DrawingImage Drawing="{DynamicResource AvaloniaLogo}"/>
</Image.Source>
</Image>
<TextBlock Text="Avalonia"
FontWeight="Bold"
HorizontalAlignment="Center"
FontSize="32"
Grid.Row="1"/>
<TextBlock Text="{Binding Version}"
FontWeight="Regular"
HorizontalAlignment="Center"
FontSize="14"
Grid.Row="2"/>
</Grid>
<Grid RowDefinitions="Auto, Auto, *, Auto" Grid.Row="1" Margin="0, 30,0,0">
<TextBlock Grid.Row="0"
Text="This product is built with Avalonia, a cross-platform UI framework."
TextWrapping="Wrap"/>
<TextBlock Grid.Row="1"
Text="Avalonia is made possible by the generous support of its contributors and community."
TextWrapping="Wrap"
Margin="0,15,0,0"/>
<Button Grid.Row="2" Background="#8B44AC"
Foreground="White"
VerticalAlignment="Center"
Padding="12"
Content="Learn more about Avalonia"
Click="Button_OnClick"
HorizontalAlignment="Center"/>
<TextBlock Grid.Row="4" VerticalAlignment="Bottom"
Text="{Binding Copyright}"
HorizontalAlignment="Center"/>
</Grid>
</Grid>
</Window>

46
src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml.cs

@ -3,6 +3,7 @@ using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace Avalonia.Dialogs
@ -11,35 +12,19 @@ namespace Avalonia.Dialogs
{
private static readonly Version s_version = typeof(AboutAvaloniaDialog).Assembly.GetName().Version;
public static string Version { get; } = s_version.ToString(2);
public static string Version { get; } = $@"v{s_version.ToString(2)}";
public static bool IsDevelopmentBuild { get; } = s_version.Revision == 999;
public static string Copyright { get; } = $"© {DateTime.Now.Year} The Avalonia Project";
public AboutAvaloniaDialog()
{
AvaloniaXamlLoader.Load(this);
DataContext = this;
}
public static void OpenBrowser(string url)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// If no associated application/json MimeType is found xdg-open opens retrun error
// but it tries to open it anyway using the console editor (nano, vim, other..)
ShellExec($"xdg-open {url}", waitForExit: false);
}
else
{
using Process process = Process.Start(new ProcessStartInfo
{
FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? url : "open",
Arguments = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? $"{url}" : "",
CreateNoWindow = true,
UseShellExecute = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
});
}
}
private static void ShellExec(string cmd, bool waitForExit = true)
{
@ -64,5 +49,26 @@ namespace Avalonia.Dialogs
}
}
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
var url = "https://www.avaloniaui.net/";
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
// If no associated application/json MimeType is found xdg-open opens retrun error
// but it tries to open it anyway using the console editor (nano, vim, other..)
ShellExec($"xdg-open {url}", waitForExit: false);
}
else
{
using Process process = Process.Start(new ProcessStartInfo
{
FileName = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? url : "open",
Arguments = RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? $"{url}" : "",
CreateNoWindow = true,
UseShellExecute = RuntimeInformation.IsOSPlatform(OSPlatform.Windows)
});
}
}
}
}

6
src/Avalonia.Dialogs/Internal/ManagedFileChooserFilterViewModel.cs

@ -18,9 +18,9 @@ namespace Avalonia.Dialogs.Internal
return;
}
_patterns = filter.Patterns?
.Select(e => new Regex(Regex.Escape(e).Replace(@"\*", ".*").Replace(@"\?", "."), RegexOptions.Singleline | RegexOptions.IgnoreCase))
.ToArray();
_patterns = filter.Patterns?
.Select(e => new Regex("^" + Regex.Escape(e).Replace("\\*", ".*") + "$", RegexOptions.Singleline | RegexOptions.IgnoreCase))
.ToArray();
}
public bool Match(string filename)

3
src/Avalonia.Themes.Simple/Controls/TransitioningContentControl.xaml

@ -13,11 +13,10 @@
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
<ContentPresenter Name="PART_TransitionContentPresenter"
<ContentPresenter Name="PART_ContentPresenter2"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"

1
src/tools/Avalonia.Generators/Avalonia.Generators.csproj

@ -6,6 +6,7 @@
<DefineConstants>$(DefineConstants);XAMLX_INTERNAL</DefineConstants>
<IsPackable>true</IsPackable>
<IsRoslynComponent>true</IsRoslynComponent>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
</PropertyGroup>
<ItemGroup>

13
tests/Avalonia.Base.UnitTests/AvaloniaObjectTests_Coercion.cs

@ -243,6 +243,19 @@ namespace Avalonia.Base.UnitTests
Assert.Equal(new[] { 11 }, target.CoerceFooInvocations);
}
[Fact]
public void Second_Coerce_Of_Default_Value_Is_Passed_Uncoerced_Value()
{
var target = new Class1();
target.MinFoo = 20;
target.CoerceFooInvocations.Clear();
target.CoerceValue(Class1.FooProperty);
target.CoerceValue(Class1.FooProperty);
Assert.Equal(new[] { 11, 11 }, target.CoerceFooInvocations);
}
[Fact]
public void ClearValue_Respects_Coerced_Default_Value()
{

19
tests/Avalonia.Controls.UnitTests/LayoutTransformControlTests.cs

@ -169,6 +169,25 @@ namespace Avalonia.Controls.UnitTests
new Rect(0, 100, 100, 25));
}
[Fact]
public void Bounds_On_Transform_Applied_Then_Removed_Are_Correct()
{
using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface);
var control = CreateWithChildAndMeasureAndTransform(
100,
25,
new RotateTransform { Angle = 90 });
Assert.Equal(new Size(25, 100), control.DesiredSize);
control.LayoutTransform = null;
control.Measure(Size.Infinity);
control.Arrange(new Rect(control.DesiredSize));
Assert.Equal(new Size(100, 25), control.DesiredSize);
}
[Fact]
public void Should_Generate_RotateTransform_90_degrees()
{

12
tests/Avalonia.Controls.UnitTests/MenuItemTests.cs

@ -209,13 +209,13 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(0, canExecuteCallCount);
contextMenu.Open();
Assert.Equal(2, canExecuteCallCount);//2 because popup is changing logical child
Assert.Equal(3, canExecuteCallCount);// 3 because popup is changing logical child and moreover we need to invalidate again after the item is attached to the visual tree
command.RaiseCanExecuteChanged();
Assert.Equal(3, canExecuteCallCount);
Assert.Equal(4, canExecuteCallCount);
target.CommandParameter = true;
Assert.Equal(4, canExecuteCallCount);
Assert.Equal(5, canExecuteCallCount);
}
}
@ -249,13 +249,13 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(0, canExecuteCallCount);
flyout.ShowAt(button);
Assert.Equal(1, canExecuteCallCount);
Assert.Equal(2, canExecuteCallCount); // 2 because we need to invalidate after the item is attached to the visual tree
command.RaiseCanExecuteChanged();
Assert.Equal(2, canExecuteCallCount);
Assert.Equal(3, canExecuteCallCount);
target.CommandParameter = true;
Assert.Equal(3, canExecuteCallCount);
Assert.Equal(4, canExecuteCallCount);
}
}

1
tests/Avalonia.UnitTests/Avalonia.UnitTests.csproj

@ -22,5 +22,4 @@
<Import Project="..\..\build\HarfBuzzSharp.props" />
<Import Project="..\..\build\XUnit.props" />
<Import Project="..\..\build\SharedVersion.props" />
<Import Project="..\..\build\AvaloniaPublicKey.props" />
</Project>

Loading…
Cancel
Save