Browse Source

Merge branch 'master' into upd-links

pull/9104/head
Max Katz 4 years ago
committed by GitHub
parent
commit
8b463008e2
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      .editorconfig
  2. 1
      .gitignore
  3. 3
      .gitmodules
  4. 0
      .nuke
  5. 148
      .nuke/build.schema.json
  6. 4
      .nuke/parameters.json
  7. 45
      Avalonia.sln
  8. 5
      azure-pipelines-integrationtests.yml
  9. 44
      azure-pipelines.yml
  10. 7
      build.cmd
  11. 50
      build.ps1
  12. 60
      build.sh
  13. 5
      build/NetAnalyzers.props
  14. 3
      dirs.proj
  15. 4
      global.json
  16. 20
      nukebuild/Build.cs
  17. 4
      nukebuild/BuildParameters.cs
  18. 12
      nukebuild/BuildTasksPatcher.cs
  19. 4
      nukebuild/DotNetConfigHelper.cs
  20. 14
      nukebuild/MicroComGen.cs
  21. 15
      nukebuild/Shims.cs
  22. 41
      nukebuild/_build.csproj
  23. 1
      nukebuild/il-repack
  24. 12
      samples/ControlCatalog.Android/MainActivity.cs
  25. 13
      samples/ControlCatalog.Android/SplashActivity.cs
  26. 0
      samples/ControlCatalog.Blazor.Web/App.razor
  27. 17
      samples/ControlCatalog.Blazor.Web/App.razor.cs
  28. 29
      samples/ControlCatalog.Blazor.Web/ControlCatalog.Blazor.Web.csproj
  29. 0
      samples/ControlCatalog.Blazor.Web/Pages/Index.razor
  30. 29
      samples/ControlCatalog.Blazor.Web/Program.cs
  31. 0
      samples/ControlCatalog.Blazor.Web/Properties/launchSettings.json
  32. 0
      samples/ControlCatalog.Blazor.Web/Shared/MainLayout.razor
  33. 3
      samples/ControlCatalog.Blazor.Web/_Imports.razor
  34. 0
      samples/ControlCatalog.Blazor.Web/wwwroot/css/app.css
  35. 0
      samples/ControlCatalog.Blazor.Web/wwwroot/favicon.ico
  36. 0
      samples/ControlCatalog.Blazor.Web/wwwroot/index.html
  37. 20
      samples/ControlCatalog.Web/App.razor.cs
  38. 68
      samples/ControlCatalog.Web/ControlCatalog.Web.csproj
  39. 32
      samples/ControlCatalog.Web/EmbedSample.Browser.cs
  40. 5
      samples/ControlCatalog.Web/Logo.svg
  41. 37
      samples/ControlCatalog.Web/Program.cs
  42. 6
      samples/ControlCatalog.Web/Roots.xml
  43. 49
      samples/ControlCatalog.Web/app.css
  44. 11
      samples/ControlCatalog.Web/embed.js
  45. BIN
      samples/ControlCatalog.Web/favicon.ico
  46. 31
      samples/ControlCatalog.Web/index.html
  47. 19
      samples/ControlCatalog.Web/main.js
  48. 11
      samples/ControlCatalog.Web/runtimeconfig.template.json
  49. 4
      samples/MobileSandbox.Android/MainActivity.cs
  50. 4
      samples/MobileSandbox.Android/SplashActivity.cs
  51. 105
      src/Android/Avalonia.Android/AvaloniaActivity.cs
  52. 72
      src/Android/Avalonia.Android/AvaloniaMainActivity.cs
  53. 34
      src/Android/Avalonia.Android/AvaloniaSplashActivity.cs
  54. 11
      src/Android/Avalonia.Android/AvaloniaViewModel.cs
  55. 6
      src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs
  56. 11
      src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs
  57. 4
      src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs
  58. 26
      src/Android/Avalonia.Android/SingleViewLifetime.cs
  59. 2
      src/Avalonia.Base/Input/Cursor.cs
  60. 35
      src/Avalonia.Base/Logging/LogArea.cs
  61. 2
      src/Avalonia.Base/Media/PreciseEllipticArcHelper.cs
  62. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/BinaryReaderExtensions.cs
  63. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs
  64. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreak.cs
  65. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs
  66. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.Constants.cs
  67. 2
      src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs
  68. 2
      src/Avalonia.Base/Platform/Storage/IStorageFile.cs
  69. 1
      src/Avalonia.Base/Properties/AssemblyInfo.cs
  70. 2
      src/Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs
  71. 2
      src/Avalonia.Base/Utilities/BinarySearchExtension.cs
  72. 7
      src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj
  73. 1
      src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs
  74. 359
      src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs
  75. 2
      src/Avalonia.Controls/AutoCompleteBox.cs
  76. 2
      src/Avalonia.Controls/Calendar/Calendar.cs
  77. 2
      src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs
  78. 2
      src/Avalonia.Controls/Calendar/CalendarButton.cs
  79. 2
      src/Avalonia.Controls/Calendar/CalendarDateRange.cs
  80. 2
      src/Avalonia.Controls/Calendar/CalendarDayButton.cs
  81. 2
      src/Avalonia.Controls/Calendar/CalendarExtensions.cs
  82. 2
      src/Avalonia.Controls/Calendar/CalendarItem.cs
  83. 2
      src/Avalonia.Controls/Calendar/DateTimeHelper.cs
  84. 2
      src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs
  85. 2
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs
  86. 2
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerDateValidationErrorEventArgs.cs
  87. 2
      src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerFormat.cs
  88. 28
      src/Avalonia.Controls/ComboBox.cs
  89. 2
      src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs
  90. 91
      src/Avalonia.Controls/TextBox.cs
  91. 2
      src/Avalonia.Controls/TextBoxTextInputMethodClient.cs
  92. 20
      src/Avalonia.Controls/TextChangedEventArgs.cs
  93. 20
      src/Avalonia.Controls/TextChangingEventArgs.cs
  94. 2
      src/Avalonia.Controls/Utils/ISelectionAdapter.cs
  95. 2
      src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs
  96. 2
      src/Avalonia.Native/IconLoader.cs
  97. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Bold.ttf
  98. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-ExtraLight.ttf
  99. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Light.ttf
  100. BIN
      src/Avalonia.Themes.Fluent/Assets/Inter-Medium.ttf

3
.editorconfig

@ -134,6 +134,9 @@ csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false csharp_space_between_square_brackets = false
space_within_single_line_array_initializer_braces = true space_within_single_line_array_initializer_braces = true
#Net Analyzer
dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
# Wrapping preferences # Wrapping preferences
csharp_wrap_before_ternary_opsigns = false csharp_wrap_before_ternary_opsigns = false

1
.gitignore

@ -215,3 +215,4 @@ src/Web/Avalonia.Web.Blazor/Interop/Typescript/*.js
node_modules node_modules
src/Web/Avalonia.Web.Blazor/webapp/package-lock.json src/Web/Avalonia.Web.Blazor/webapp/package-lock.json
src/Web/Avalonia.Web.Blazor/wwwroot src/Web/Avalonia.Web.Blazor/wwwroot
src/Web/Avalonia.Web/wwwroot

3
.gitmodules

@ -4,3 +4,6 @@
[submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"] [submodule "src/Markup/Avalonia.Markup.Xaml/XamlIl/xamlil.github"]
path = src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github path = src/Markup/Avalonia.Markup.Xaml.Loader/xamlil.github
url = https://github.com/kekekeks/XamlX.git url = https://github.com/kekekeks/XamlX.git
[submodule "nukebuild/il-repack"]
path = nukebuild/il-repack
url = https://github.com/Gillibald/il-repack

0
.nuke

148
.nuke/build.schema.json

@ -0,0 +1,148 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Build Schema",
"$ref": "#/definitions/build",
"definitions": {
"build": {
"type": "object",
"properties": {
"Configuration": {
"type": "string",
"description": "configuration"
},
"Continue": {
"type": "boolean",
"description": "Indicates to continue a previously failed build attempt"
},
"ForceNugetVersion": {
"type": "string",
"description": "force-nuget-version"
},
"Help": {
"type": "boolean",
"description": "Shows the help text for this build assembly"
},
"Host": {
"type": "string",
"description": "Host for execution. Default is 'automatic'",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
},
"NoLogo": {
"type": "boolean",
"description": "Disables displaying the NUKE logo"
},
"Partition": {
"type": "string",
"description": "Partition to use on CI"
},
"Plan": {
"type": "boolean",
"description": "Shows the execution plan (HTML)"
},
"Profile": {
"type": "array",
"description": "Defines the profiles to load",
"items": {
"type": "string"
}
},
"Root": {
"type": "string",
"description": "Root directory during build execution"
},
"Skip": {
"type": "array",
"description": "List of targets to be skipped. Empty list skips all dependencies",
"items": {
"type": "string",
"enum": [
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"GenerateCppHeaders",
"Package",
"RunCoreLibsTests",
"RunDesignerTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"ZipFiles"
]
}
},
"SkipPreviewer": {
"type": "boolean",
"description": "skip-previewer"
},
"SkipTests": {
"type": "boolean",
"description": "skip-tests"
},
"Solution": {
"type": "string",
"description": "Path to a solution file that is automatically loaded. Default is Avalonia.sln"
},
"Target": {
"type": "array",
"description": "List of targets to be invoked. Default is '{default_target}'",
"items": {
"type": "string",
"enum": [
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"GenerateCppHeaders",
"Package",
"RunCoreLibsTests",
"RunDesignerTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"ZipFiles"
]
}
},
"Verbosity": {
"type": "string",
"description": "Logging verbosity during build execution. Default is 'Normal'",
"enum": [
"Minimal",
"Normal",
"Quiet",
"Verbose"
]
}
}
}
}
}

4
.nuke/parameters.json

@ -0,0 +1,4 @@
{
"$schema": "./build.schema.json",
"Solution": ""
}

45
Avalonia.sln

@ -90,6 +90,7 @@ EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
build\ApiDiff.props = build\ApiDiff.props build\ApiDiff.props = build\ApiDiff.props
build\AvaloniaPublicKey.props = build\AvaloniaPublicKey.props
build\Base.props = build\Base.props build\Base.props = build\Base.props
build\Binding.props = build\Binding.props build\Binding.props = build\Binding.props
build\CoreLibraries.props = build\CoreLibraries.props build\CoreLibraries.props = build\CoreLibraries.props
@ -102,8 +103,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\Microsoft.CSharp.props = build\Microsoft.CSharp.props build\Microsoft.CSharp.props = build\Microsoft.CSharp.props
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props build\Moq.props = build\Moq.props
build\NetAnalyzers.props = build\NetAnalyzers.props
build\NetCore.props = build\NetCore.props build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props build\NetFX.props = build\NetFX.props
build\NullableEnable.props = build\NullableEnable.props
build\ReactiveUI.props = build\ReactiveUI.props build\ReactiveUI.props = build\ReactiveUI.props
build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props
build\Rx.props = build\Rx.props build\Rx.props = build\Rx.props
@ -198,8 +201,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Web", "Web", "{86A3F706-DC3
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Blazor", "src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj", "{25831348-EB2A-483E-9576-E8F6528674A5}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web.Blazor", "src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj", "{25831348-EB2A-483E-9576-E8F6528674A5}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Web", "samples\ControlCatalog.Web\ControlCatalog.Web.csproj", "{C08E9894-AA92-426E-BF56-033E262CAD3E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "samples\interop\WindowsInteropTest\WindowsInteropTest.csproj", "{26A98DA1-D89D-4A95-8152-349F404DA2E2}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsInteropTest", "samples\interop\WindowsInteropTest\WindowsInteropTest.csproj", "{26A98DA1-D89D-4A95-8152-349F404DA2E2}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlSamples", "samples\SampleControls\ControlSamples.csproj", "{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270}"
@ -212,15 +213,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Controls.ColorPick
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Tests", "tests\Avalonia.DesignerSupport.Tests\Avalonia.DesignerSupport.Tests.csproj", "{EABE2161-989B-42BF-BD8D-1E34B20C21F1}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Tests", "tests\Avalonia.DesignerSupport.Tests\Avalonia.DesignerSupport.Tests.csproj", "{EABE2161-989B-42BF-BD8D-1E34B20C21F1}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DevGenerators", "src\tools\DevGenerators\DevGenerators.csproj", "{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DevGenerators", "src\tools\DevGenerators\DevGenerators.csproj", "{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Web", "src\Web\Avalonia.Web\Avalonia.Web.csproj", "{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox", "samples\MobileSandbox\MobileSandbox.csproj", "{3B8519C1-2F51-4F12-A348-120AB91D4532}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox", "samples\MobileSandbox\MobileSandbox.csproj", "{3B8519C1-2F51-4F12-A348-120AB91D4532}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Android", "samples\MobileSandbox.Android\MobileSandbox.Android.csproj", "{C90FE60B-B01E-4F35-91D6-379D6966030F}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.Android", "samples\MobileSandbox.Android\MobileSandbox.Android.csproj", "{C90FE60B-B01E-4F35-91D6-379D6966030F}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.iOS", "samples\MobileSandbox.iOS\MobileSandbox.iOS.csproj", "{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.iOS", "samples\MobileSandbox.iOS\MobileSandbox.iOS.csproj", "{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MobileSandbox.Desktop", "samples\MobileSandbox.Desktop\MobileSandbox.Desktop.csproj", "{62D392C9-81CF-487F-92E8-598B2AF3FDCE}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Blazor.Web", "samples\ControlCatalog.Blazor.Web\ControlCatalog.Blazor.Web.csproj", "{6A710364-AE6D-40BD-968B-024311527AC2}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.Web", "samples\ControlCatalog.Web\ControlCatalog.Web.csproj", "{8B3E8405-DE18-4048-A459-9CA4AC3319A2}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -407,9 +414,7 @@ Global
{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|Any CPU.ActiveCfg = Release|Any CPU {BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|Any CPU.Build.0 = Release|Any CPU {BF28998D-072C-439A-AFBB-2FE5021241E0}.Release|Any CPU.Build.0 = Release|Any CPU
{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3F00BC43-5095-477F-93D8-E65B08179A00}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU {3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F00BC43-5095-477F-93D8-E65B08179A00}.Release|Any CPU.Build.0 = Release|Any CPU
{41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.Build.0 = Debug|Any CPU {41B02319-965D-4945-8005-C1A3D1224165}.Debug|Any CPU.Build.0 = Debug|Any CPU
{41B02319-965D-4945-8005-C1A3D1224165}.Release|Any CPU.ActiveCfg = Release|Any CPU {41B02319-965D-4945-8005-C1A3D1224165}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -478,10 +483,6 @@ Global
{25831348-EB2A-483E-9576-E8F6528674A5}.Debug|Any CPU.Build.0 = Debug|Any CPU {25831348-EB2A-483E-9576-E8F6528674A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.ActiveCfg = Release|Any CPU {25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.Build.0 = Release|Any CPU {25831348-EB2A-483E-9576-E8F6528674A5}.Release|Any CPU.Build.0 = Release|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C08E9894-AA92-426E-BF56-033E262CAD3E}.Release|Any CPU.Build.0 = Release|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU {26A98DA1-D89D-4A95-8152-349F404DA2E2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26A98DA1-D89D-4A95-8152-349F404DA2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU {26A98DA1-D89D-4A95-8152-349F404DA2E2}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -510,6 +511,10 @@ Global
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Debug|Any CPU.Build.0 = Debug|Any CPU {1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.ActiveCfg = Release|Any CPU {1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.Build.0 = Release|Any CPU {1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB}.Release|Any CPU.Build.0 = Release|Any CPU
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76D39FF6-6B4F-46C4-93CD-E6FC4665739E}.Release|Any CPU.Build.0 = Release|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.Build.0 = Debug|Any CPU {3B8519C1-2F51-4F12-A348-120AB91D4532}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3B8519C1-2F51-4F12-A348-120AB91D4532}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B8519C1-2F51-4F12-A348-120AB91D4532}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -526,6 +531,14 @@ Global
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU {62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU {62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.Build.0 = Release|Any CPU {62D392C9-81CF-487F-92E8-598B2AF3FDCE}.Release|Any CPU.Build.0 = Release|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A710364-AE6D-40BD-968B-024311527AC2}.Release|Any CPU.Build.0 = Release|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8B3E8405-DE18-4048-A459-9CA4AC3319A2}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -569,6 +582,7 @@ Global
{41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} {41B02319-965D-4945-8005-C1A3D1224165} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098} {D775DECB-4E00-4ED5-A75A-5FCE58ADFF0B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {AF915D5C-AB00-4EA0-B5E6-001F4AE84E68} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {351337F5-D66F-461B-A957-4EF60BDB4BA6} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C} {909A8CBD-7D0E-42FD-B841-022AD8925820} = {8B6A8209-894F-4BA1-B880-965FD453982C}
{11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098} {11BE52AF-E2DD-4CF0-B19A-05285ACAF571} = {9B9E3891-2366-4253-A952-D08BCEB71098}
@ -576,18 +590,19 @@ Global
{676D6BFD-029D-4E43-BFC7-3892265CE251} = {9B9E3891-2366-4253-A952-D08BCEB71098} {676D6BFD-029D-4E43-BFC7-3892265CE251} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{F2CE566B-E7F6-447A-AB1A-3F574A6FE43A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {F2CE566B-E7F6-447A-AB1A-3F574A6FE43A} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268} {25831348-EB2A-483E-9576-E8F6528674A5} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{C08E9894-AA92-426E-BF56-033E262CAD3E} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{26A98DA1-D89D-4A95-8152-349F404DA2E2} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9} {26A98DA1-D89D-4A95-8152-349F404DA2E2} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{A0D0A6A4-5C72-4ADA-9B27-621C7D94F270} = {9B9E3891-2366-4253-A952-D08BCEB71098} {A0D0A6A4-5C72-4ADA-9B27-621C7D94F270} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{70B9F5CC-E2F9-4314-9514-EDE762ACCC4B} = {9B9E3891-2366-4253-A952-D08BCEB71098} {70B9F5CC-E2F9-4314-9514-EDE762ACCC4B} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {2B390431-288C-435C-BB6B-A374033BD8D1} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B} {EABE2161-989B-42BF-BD8D-1E34B20C21F1} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
{1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {1BBFAD42-B99E-47E0-B00A-A4BC6B6BB4BB} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{4D36CEC8-53F2-40A5-9A37-79AAE356E2DA} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B} {76D39FF6-6B4F-46C4-93CD-E6FC4665739E} = {86A3F706-DC3C-43C6-BE1B-B98F5BAAA268}
{3B8519C1-2F51-4F12-A348-120AB91D4532} = {9B9E3891-2366-4253-A952-D08BCEB71098} {3B8519C1-2F51-4F12-A348-120AB91D4532} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{C90FE60B-B01E-4F35-91D6-379D6966030F} = {9B9E3891-2366-4253-A952-D08BCEB71098} {C90FE60B-B01E-4F35-91D6-379D6966030F} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{FED9A71D-00D7-4F40-A9E4-1229EEA28EEB} = {9B9E3891-2366-4253-A952-D08BCEB71098} {FED9A71D-00D7-4F40-A9E4-1229EEA28EEB} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{62D392C9-81CF-487F-92E8-598B2AF3FDCE} = {9B9E3891-2366-4253-A952-D08BCEB71098} {62D392C9-81CF-487F-92E8-598B2AF3FDCE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{6A710364-AE6D-40BD-968B-024311527AC2} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{8B3E8405-DE18-4048-A459-9CA4AC3319A2} = {9B9E3891-2366-4253-A952-D08BCEB71098}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A} SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

5
azure-pipelines-integrationtests.yml

@ -41,9 +41,9 @@ jobs:
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.202' displayName: 'Use .NET Core SDK 6.0.401'
inputs: inputs:
version: 6.0.202 version: 6.0.401
- task: Windows Application Driver@0 - task: Windows Application Driver@0
inputs: inputs:
@ -57,6 +57,7 @@ jobs:
projects: 'samples/IntegrationTestApp/IntegrationTestApp.csproj' projects: 'samples/IntegrationTestApp/IntegrationTestApp.csproj'
- task: DotNetCoreCLI@2 - task: DotNetCoreCLI@2
retryCountOnTaskFailure: 3
inputs: inputs:
command: 'test' command: 'test'
projects: 'tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj' projects: 'tests/Avalonia.IntegrationTests.Appium/Avalonia.IntegrationTests.Appium.csproj'

44
azure-pipelines.yml

@ -6,7 +6,6 @@ jobs:
variables: variables:
SolutionDir: '$(Build.SourcesDirectory)' SolutionDir: '$(Build.SourcesDirectory)'
steps: steps:
- task: PowerShell@2 - task: PowerShell@2
displayName: Get PR Number displayName: Get PR Number
inputs: inputs:
@ -31,14 +30,20 @@ jobs:
vmImage: 'ubuntu-20.04' vmImage: 'ubuntu-20.04'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 3.1.418' displayName: 'Use .NET Core SDK 6.0.401'
inputs: inputs:
version: 3.1.418 version: 6.0.401
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.202' displayName: 'Use .NET Core SDK 7.0.100-rc.1.22431.12'
inputs:
version: 7.0.100-rc.1.22431.12
- task: CmdLine@2
displayName: 'Install Workloads'
inputs: inputs:
version: 6.0.202 script: |
dotnet workload install wasm-tools wasm-experimental
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Run Build' displayName: 'Run Build'
@ -62,22 +67,21 @@ jobs:
vmImage: 'macos-12' vmImage: 'macos-12'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 3.1.418' displayName: 'Use .NET Core SDK 6.0.401'
inputs: inputs:
version: 3.1.418 version: 6.0.401
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.202' displayName: 'Use .NET Core SDK 7.0.100-rc.1.22431.12'
inputs: inputs:
version: 6.0.202 version: 7.0.100-rc.1.22431.12
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Install Mono 5.18' displayName: 'Install Workloads'
inputs: inputs:
script: | script: |
curl -o ./mono.pkg https://download.mono-project.com/archive/5.18.0/macos-10-universal/MonoFramework-MDK-5.18.0.225.macos10.xamarin.universal.pkg dotnet workload install wasm-tools wasm-experimental
sudo installer -verbose -pkg ./mono.pkg -target /
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Generate avalonia-native' displayName: 'Generate avalonia-native'
inputs: inputs:
@ -134,26 +138,26 @@ jobs:
SolutionDir: '$(Build.SourcesDirectory)' SolutionDir: '$(Build.SourcesDirectory)'
steps: steps:
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 3.1.418' displayName: 'Use .NET Core SDK 6.0.401'
inputs: inputs:
version: 3.1.418 version: 6.0.401
- task: UseDotNet@2 - task: UseDotNet@2
displayName: 'Use .NET Core SDK 6.0.202' displayName: 'Use .NET Core SDK 7.0.100-rc.1.22431.12'
inputs: inputs:
version: 6.0.202 version: 7.0.100-rc.1.22431.12
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Install Workloads' displayName: 'Install Workloads'
inputs: inputs:
script: | script: |
dotnet workload install android ios dotnet workload install android ios wasm-tools wasm-experimental
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Install Nuke' displayName: 'Install Nuke'
inputs: inputs:
script: | script: |
dotnet tool install --global Nuke.GlobalTool --version 0.24.0 dotnet tool install --global Nuke.GlobalTool --version 6.2.1
- task: CmdLine@2 - task: CmdLine@2
displayName: 'Run Nuke' displayName: 'Run Nuke'

7
build.cmd

@ -0,0 +1,7 @@
:; set -eo pipefail
:; SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
:; ${SCRIPT_DIR}/build.sh "$@"
:; exit $?
@ECHO OFF
powershell -ExecutionPolicy ByPass -NoProfile -File "%~dp0build.ps1" %*

50
build.ps1

@ -1,13 +1,12 @@
[CmdletBinding()] [CmdletBinding()]
Param( Param(
#[switch]$CustomParam,
[Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)] [Parameter(Position=0,Mandatory=$false,ValueFromRemainingArguments=$true)]
[string[]]$BuildArguments [string[]]$BuildArguments
) )
Write-Output "Windows PowerShell $($Host.Version)" Write-Output "PowerShell $($PSVersionTable.PSEdition) version $($PSVersionTable.PSVersion)"
Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { exit 1 } Set-StrictMode -Version 2.0; $ErrorActionPreference = "Stop"; $ConfirmPreference = "None"; trap { Write-Error $_ -ErrorAction Continue; exit 1 }
$PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
########################################################################### ###########################################################################
@ -15,15 +14,15 @@ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent
########################################################################### ###########################################################################
$BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj" $BuildProjectFile = "$PSScriptRoot\nukebuild\_build.csproj"
$TempDirectory = "$PSScriptRoot\\.tmp" $TempDirectory = "$PSScriptRoot\\.nuke\temp"
$DotNetGlobalFile = "$PSScriptRoot\\global.json" $DotNetGlobalFile = "$PSScriptRoot\\global.json"
$DotNetInstallUrl = "https://raw.githubusercontent.com/dotnet/cli/master/scripts/obtain/dotnet-install.ps1" $DotNetInstallUrl = "https://dot.net/v1/dotnet-install.ps1"
$DotNetChannel = "Current" $DotNetChannel = "Current"
$env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1 $env:DOTNET_SKIP_FIRST_TIME_EXPERIENCE = 1
$env:DOTNET_CLI_TELEMETRY_OPTOUT = 1 $env:DOTNET_CLI_TELEMETRY_OPTOUT = 1
$env:NUGET_XMLDOC_MODE = "skip" $env:DOTNET_MULTILEVEL_LOOKUP = 0
########################################################################### ###########################################################################
# EXECUTION # EXECUTION
@ -34,38 +33,37 @@ function ExecSafe([scriptblock] $cmd) {
if ($LASTEXITCODE) { exit $LASTEXITCODE } if ($LASTEXITCODE) { exit $LASTEXITCODE }
} }
# If global.json exists, load expected version # If dotnet CLI is installed globally and it matches requested version, use for execution
if (Test-Path $DotNetGlobalFile) {
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
$DotNetVersion = $DotNetGlobal.sdk.version
}
}
# If dotnet is installed locally, and expected version is not set or installation matches the expected version
if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and ` if ($null -ne (Get-Command "dotnet" -ErrorAction SilentlyContinue) -and `
(!(Test-Path variable:DotNetVersion) -or $(& dotnet --version) -eq $DotNetVersion)) { $(dotnet --version) -and $LASTEXITCODE -eq 0) {
$env:DOTNET_EXE = (Get-Command "dotnet").Path $env:DOTNET_EXE = (Get-Command "dotnet").Path
} }
else { else {
$DotNetDirectory = "$TempDirectory\dotnet-win"
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
# Download install script # Download install script
$DotNetInstallFile = "$TempDirectory\dotnet-install.ps1" $DotNetInstallFile = "$TempDirectory\dotnet-install.ps1"
mkdir -force $TempDirectory > $null New-Item -ItemType Directory -Path $TempDirectory -Force | Out-Null
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile) (New-Object System.Net.WebClient).DownloadFile($DotNetInstallUrl, $DotNetInstallFile)
# If global.json exists, load expected version
if (Test-Path $DotNetGlobalFile) {
$DotNetGlobal = $(Get-Content $DotNetGlobalFile | Out-String | ConvertFrom-Json)
if ($DotNetGlobal.PSObject.Properties["sdk"] -and $DotNetGlobal.sdk.PSObject.Properties["version"]) {
$DotNetVersion = $DotNetGlobal.sdk.version
}
}
# Install by channel or version # Install by channel or version
$DotNetDirectory = "$TempDirectory\dotnet-win"
if (!(Test-Path variable:DotNetVersion)) { if (!(Test-Path variable:DotNetVersion)) {
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath } ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Channel $DotNetChannel -NoPath }
} else { } else {
ExecSafe { & $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath } ExecSafe { & powershell $DotNetInstallFile -InstallDir $DotNetDirectory -Version $DotNetVersion -NoPath }
} }
$env:DOTNET_EXE = "$DotNetDirectory\dotnet.exe"
$env:PATH="$DotNetDirectory;$env:PATH"
} }
Write-Output "Microsoft (R) .NET Core SDK version $(& $env:DOTNET_EXE --version)" Write-Output "Microsoft (R) .NET SDK version $(& $env:DOTNET_EXE --version)"
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile -- $BuildArguments } ExecSafe { & $env:DOTNET_EXE build $BuildProjectFile /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet }
ExecSafe { & $env:DOTNET_EXE run --project $BuildProjectFile --no-build -- $BuildArguments }

60
build.sh

@ -1,16 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
echo $(bash --version 2>&1 | head -n 1) bash --version 2>&1 | head -n 1
#CUSTOMPARAM=0
BUILD_ARGUMENTS=()
for i in "$@"; do
case $(echo $1 | awk '{print tolower($0)}') in
# -custom-param) CUSTOMPARAM=1;;
*) BUILD_ARGUMENTS+=("$1") ;;
esac
shift
done
set -eo pipefail set -eo pipefail
SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd) SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
@ -20,11 +10,53 @@ SCRIPT_DIR=$(cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd)
########################################################################### ###########################################################################
BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj" BUILD_PROJECT_FILE="$SCRIPT_DIR/nukebuild/_build.csproj"
TEMP_DIRECTORY="$SCRIPT_DIR//.nuke/temp"
DOTNET_GLOBAL_FILE="$SCRIPT_DIR//global.json"
DOTNET_INSTALL_URL="https://dot.net/v1/dotnet-install.sh"
DOTNET_CHANNEL="Current"
export DOTNET_CLI_TELEMETRY_OPTOUT=1 export DOTNET_CLI_TELEMETRY_OPTOUT=1
export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1 export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=1
export NUGET_XMLDOC_MODE="skip" export DOTNET_MULTILEVEL_LOOKUP=0
dotnet --info ###########################################################################
# EXECUTION
###########################################################################
dotnet run --project "$BUILD_PROJECT_FILE" -- ${BUILD_ARGUMENTS[@]} function FirstJsonValue {
perl -nle 'print $1 if m{"'"$1"'": "([^"]+)",?}' <<< "${@:2}"
}
# If dotnet CLI is installed globally and it matches requested version, use for execution
if [ -x "$(command -v dotnet)" ] && dotnet --version &>/dev/null; then
export DOTNET_EXE="$(command -v dotnet)"
else
# Download install script
DOTNET_INSTALL_FILE="$TEMP_DIRECTORY/dotnet-install.sh"
mkdir -p "$TEMP_DIRECTORY"
curl -Lsfo "$DOTNET_INSTALL_FILE" "$DOTNET_INSTALL_URL"
chmod +x "$DOTNET_INSTALL_FILE"
# If global.json exists, load expected version
if [[ -f "$DOTNET_GLOBAL_FILE" ]]; then
DOTNET_VERSION=$(FirstJsonValue "version" "$(cat "$DOTNET_GLOBAL_FILE")")
if [[ "$DOTNET_VERSION" == "" ]]; then
unset DOTNET_VERSION
fi
fi
# Install by channel or version
DOTNET_DIRECTORY="$TEMP_DIRECTORY/dotnet-unix"
if [[ -z ${DOTNET_VERSION+x} ]]; then
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --channel "$DOTNET_CHANNEL" --no-path
else
"$DOTNET_INSTALL_FILE" --install-dir "$DOTNET_DIRECTORY" --version "$DOTNET_VERSION" --no-path
fi
export DOTNET_EXE="$DOTNET_DIRECTORY/dotnet"
fi
echo "Microsoft (R) .NET SDK version $("$DOTNET_EXE" --version)"
"$DOTNET_EXE" build "$BUILD_PROJECT_FILE" /nodeReuse:false /p:UseSharedCompilation=false -nologo -clp:NoSummary --verbosity quiet
"$DOTNET_EXE" run --project "$BUILD_PROJECT_FILE" --no-build -- "$@"

5
build/NetAnalyzers.props

@ -0,0 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>
</Project>

3
dirs.proj

@ -23,12 +23,13 @@
<ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" /> <ProjectReference Remove="samples/ControlCatalog.Desktop/*.*proj" />
</ItemGroup> </ItemGroup>
<!-- Build android and iOS projects only on Windows, where we have installed android workload --> <!-- Build android and iOS projects only on Windows, where we have installed android workload -->
<ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))"> <ItemGroup Condition="!$([MSBuild]::IsOsPlatform('Windows'))">
<ProjectReference Remove="src/Android/**/*.*proj" /> <ProjectReference Remove="src/Android/**/*.*proj" />
<ProjectReference Remove="src/iOS/**/*.*proj" /> <ProjectReference Remove="src/iOS/**/*.*proj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="SlnGen" Version="2.0.40" PrivateAssets="all" /> <PackageReference Include="Microsoft.VisualStudio.SlnGen" Version="8.5.17" PrivateAssets="all" />
</ItemGroup> </ItemGroup>
</Project> </Project>

4
global.json

@ -1,8 +1,4 @@
{ {
"sdk": {
"version": "6.0.202",
"rollForward": "latestFeature"
},
"msbuild-sdks": { "msbuild-sdks": {
"Microsoft.Build.Traversal": "1.0.43", "Microsoft.Build.Traversal": "1.0.43",
"MSBuild.Sdk.Extras": "3.0.22", "MSBuild.Sdk.Extras": "3.0.22",

20
nukebuild/Build.cs

@ -23,6 +23,7 @@ using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
using static Nuke.Common.Tools.DotNet.DotNetTasks; using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.Xunit.XunitTasks; using static Nuke.Common.Tools.Xunit.XunitTasks;
using static Nuke.Common.Tools.VSWhere.VSWhereTasks; using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
using MicroCom.CodeGenerator;
/* /*
Before editing this file, install support plugin for your IDE, Before editing this file, install support plugin for your IDE,
@ -163,7 +164,7 @@ partial class Build : NukeBuild
.EnableNoBuild() .EnableNoBuild()
.EnableNoRestore() .EnableNoRestore()
.When(Parameters.PublishTestResults, _ => _ .When(Parameters.PublishTestResults, _ => _
.SetLogger("trx") .SetLoggers("trx")
.SetResultsDirectory(Parameters.TestResultsRoot))); .SetResultsDirectory(Parameters.TestResultsRoot)));
} }
} }
@ -215,8 +216,6 @@ partial class Build : NukeBuild
RunCoreTest("Avalonia.DesignerSupport.Tests"); RunCoreTest("Avalonia.DesignerSupport.Tests");
}); });
[PackageExecutable("JetBrains.dotMemoryUnit", "dotMemoryUnit.exe")] readonly Tool DotMemoryUnit;
Target RunLeakTests => _ => _ Target RunLeakTests => _ => _
.OnlyWhenStatic(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows) .OnlyWhenStatic(() => !Parameters.SkipTests && Parameters.IsRunningOnWindows)
.DependsOn(Compile) .DependsOn(Compile)
@ -224,12 +223,9 @@ partial class Build : NukeBuild
{ {
void DoMemoryTest() void DoMemoryTest()
{ {
var testAssembly = "tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"; RunCoreTest("Avalonia.LeakTests");
DotMemoryUnit(
$"{XunitPath.DoubleQuoteIfNeeded()} --propagate-exit-code -- {testAssembly}",
timeout: 120_000);
} }
ControlFlow.ExecuteWithRetry(DoMemoryTest, waitInSeconds: 3); ControlFlow.ExecuteWithRetry(DoMemoryTest, delay: TimeSpan.FromMilliseconds(3));
}); });
Target ZipFiles => _ => _ Target ZipFiles => _ => _
@ -283,6 +279,14 @@ partial class Build : NukeBuild
.DependsOn(Package) .DependsOn(Package)
.DependsOn(ZipFiles); .DependsOn(ZipFiles);
Target GenerateCppHeaders => _ => _.Executes(() =>
{
var file = MicroComCodeGenerator.Parse(
File.ReadAllText(RootDirectory / "src" / "Avalonia.Native" / "avn.idl"));
File.WriteAllText(RootDirectory / "native" / "Avalonia.Native" / "inc" / "avalonia-native.h",
file.GenerateCppHeader());
});
public static int Main() => public static int Main() =>
RuntimeInformation.IsOSPlatform(OSPlatform.Windows) RuntimeInformation.IsOSPlatform(OSPlatform.Windows)

4
nukebuild/BuildParameters.cs

@ -74,11 +74,11 @@ public partial class Build
MSBuildSolution = RootDirectory / "dirs.proj"; MSBuildSolution = RootDirectory / "dirs.proj";
// PARAMETERS // PARAMETERS
IsLocalBuild = Host == HostType.Console; IsLocalBuild = NukeBuild.IsLocalBuild;
IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix || IsRunningOnUnix = Environment.OSVersion.Platform == PlatformID.Unix ||
Environment.OSVersion.Platform == PlatformID.MacOSX; Environment.OSVersion.Platform == PlatformID.MacOSX;
IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows); IsRunningOnWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
IsRunningOnAzure = Host == HostType.AzurePipelines || IsRunningOnAzure = Host is AzurePipelines ||
Environment.GetEnvironmentVariable("LOGNAME") == "vsts"; Environment.GetEnvironmentVariable("LOGNAME") == "vsts";
if (IsRunningOnAzure) if (IsRunningOnAzure)

12
nukebuild/BuildTasksPatcher.cs

@ -17,8 +17,12 @@ public class BuildTasksPatcher
{ {
if (entry.Name == "Avalonia.Build.Tasks.dll") if (entry.Name == "Avalonia.Build.Tasks.dll")
{ {
var temp = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".dll"); var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tempDir);
var temp = Path.Combine(tempDir, Guid.NewGuid() + ".dll");
var output = temp + ".output"; var output = temp + ".output";
File.Copy(typeof(Microsoft.Build.Framework.ITask).Assembly.GetModules()[0].FullyQualifiedName,
Path.Combine(tempDir, "Microsoft.Build.Framework.dll"));
var patched = new MemoryStream(); var patched = new MemoryStream();
try try
{ {
@ -57,10 +61,8 @@ public class BuildTasksPatcher
{ {
try try
{ {
if (File.Exists(temp)) if(Directory.Exists(tempDir))
File.Delete(temp); Directory.Delete(tempDir, true);
if (File.Exists(output))
File.Delete(output);
} }
catch catch
{ {

4
nukebuild/DotNetConfigHelper.cs

@ -46,7 +46,7 @@ public class DotNetConfigHelper
public DotNetConfigHelper SetVerbosity(DotNetVerbosity verbosity) public DotNetConfigHelper SetVerbosity(DotNetVerbosity verbosity)
{ {
Build = Build?.SetVerbosity(verbosity); Build = Build?.SetVerbosity(verbosity);
Pack = Pack?.SetVerbostiy(verbosity); Pack = Pack?.SetVerbosity(verbosity);
Test = Test?.SetVerbosity(verbosity); Test = Test?.SetVerbosity(verbosity);
return this; return this;
} }
@ -54,4 +54,4 @@ public class DotNetConfigHelper
public static implicit operator DotNetConfigHelper(DotNetBuildSettings s) => new DotNetConfigHelper(s); 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(DotNetPackSettings s) => new DotNetConfigHelper(s);
public static implicit operator DotNetConfigHelper(DotNetTestSettings s) => new DotNetConfigHelper(s); public static implicit operator DotNetConfigHelper(DotNetTestSettings s) => new DotNetConfigHelper(s);
} }

14
nukebuild/MicroComGen.cs

@ -1,14 +0,0 @@
using System.IO;
using MicroCom.CodeGenerator;
using Nuke.Common;
partial class Build : NukeBuild
{
Target GenerateCppHeaders => _ => _.Executes(() =>
{
var file = MicroComCodeGenerator.Parse(
File.ReadAllText(RootDirectory / "src" / "Avalonia.Native" / "avn.idl"));
File.WriteAllText(RootDirectory / "native" / "Avalonia.Native" / "inc" / "avalonia-native.h",
file.GenerateCppHeader());
});
}

15
nukebuild/Shims.cs

@ -49,7 +49,11 @@ public partial class Build
{ {
if (fsEntry is FileInfo) if (fsEntry is FileInfo)
{ {
#if NET6
var relPath = Path.GetRelativePath(rootPath, fsEntry.FullName); var relPath = Path.GetRelativePath(rootPath, fsEntry.FullName);
#else
var relPath = GetRelativePath(rootPath, fsEntry.FullName);
#endif
AddFile(fsEntry.FullName, relPath); AddFile(fsEntry.FullName, relPath);
} }
} }
@ -78,6 +82,17 @@ public partial class Build
} }
} }
private static string GetRelativePath(string relativeTo, string path)
{
var uri = new Uri(relativeTo);
var rel = Uri.UnescapeDataString(uri.MakeRelativeUri(new Uri(path)).ToString()).Replace(Path.AltDirectorySeparatorChar, Path.DirectorySeparatorChar);
if (rel.Contains(Path.DirectorySeparatorChar.ToString()) == false)
{
rel = $".{Path.DirectorySeparatorChar}{rel}";
}
return rel;
}
class NumergeNukeLogger : INumergeLogger class NumergeNukeLogger : INumergeLogger
{ {
public void Log(NumergeLogLevel level, string message) public void Log(NumergeLogLevel level, string message)

41
nukebuild/_build.csproj

@ -1,41 +1,48 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath> <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<RootNamespace></RootNamespace> <RootNamespace></RootNamespace>
<IsPackable>False</IsPackable> <IsPackable>False</IsPackable>
<NoWarn>CS0649;CS0169</NoWarn> <NoWarn>CS0649;CS0169;SYSLIB0011</NoWarn>
<NukeTelemetryVersion>1</NukeTelemetryVersion>
<TargetFramework>net7.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<Import Project="..\build\JetBrains.dotMemoryUnit.props" /> <Import Project="..\build\JetBrains.dotMemoryUnit.props" />
<ItemGroup> <ItemGroup>
<PackageReference Include="Nuke.Common" Version="5.0.0" /> <PackageReference Include="Nuke.Common" Version="6.2.1" />
<PackageReference Include="xunit.runner.console" Version="2.3.1" />
<PackageReference Include="vswhere" Version="2.6.7" Condition=" '$(OS)' == 'Windows_NT' " /> <PackageReference Include="vswhere" Version="2.6.7" Condition=" '$(OS)' == 'Windows_NT' " />
<PackageReference Include="ILRepack.NETStandard" Version="2.0.4" />
<PackageReference Include="MicroCom.CodeGenerator" Version="0.10.4" /> <PackageReference Include="MicroCom.CodeGenerator" Version="0.10.4" />
<!-- Keep in sync with Avalonia.Build.Tasks --> <!-- Keep in sync with Avalonia.Build.Tasks -->
<PackageReference Include="Mono.Cecil" Version="0.11.2" /> <PackageReference Include="Mono.Cecil" Version="0.11.4" />
<PackageReference Include="SourceLink" Version="1.1.0" GeneratePathProperty="true" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.3.1" PrivateAssets="All" />
<PackageReference Include="xunit.runner.console" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<NukeMetadata Include="**\*.json" Exclude="bin\**;obj\**" /> <NukeMetadata Include="**\*.json" Exclude="bin\**;obj\**" />
<NukeExternalFiles Include="**\*.*.ext" Exclude="bin\**;obj\**" /> <NukeExternalFiles Include="**\*.*.ext" Exclude="bin\**;obj\**" />
<None Remove="*.csproj.DotSettings;*.ref.*.txt" />
<!-- Common build related files --> <!-- Common build related files -->
<None Include="..\build.ps1" />
<None Include="..\build.sh" />
<None Include="..\.nuke" />
<None Include="..\global.json" Condition="Exists('..\global.json')" />
<None Include="..\nuget.config" Condition="Exists('..\nuget.config')" />
<None Include="..\Jenkinsfile" Condition="Exists('..\Jenkinsfile')" />
<None Include="..\appveyor.yml" Condition="Exists('..\appveyor.yml')" />
<None Include="..\.travis.yml" Condition="Exists('..\.travis.yml')" />
<None Include="..\GitVersion.yml" Condition="Exists('..\GitVersion.yml')" />
<Compile Remove="Numerge/**/*.*" /> <Compile Remove="Numerge/**/*.*" />
<Compile Include="Numerge/Numerge/**/*.cs" /> <Compile Include="Numerge/Numerge/**/*.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(NuGetPackageRoot)sourcelink/1.1.0/tools/pdbstr.exe"></EmbeddedResource>
</ItemGroup>
<ItemGroup>
<Compile Remove="il-repack\ILRepack\Application.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="Numerge\Numerge.Console\" />
</ItemGroup>
</Project> </Project>

1
nukebuild/il-repack

@ -0,0 +1 @@
Subproject commit 892f079ea8cb0c178f0a68f53a7a7eac13acdda9

12
samples/ControlCatalog.Android/MainActivity.cs

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

13
samples/ControlCatalog.Android/SplashActivity.cs

@ -1,12 +1,23 @@
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.Content.PM;
using Android.OS; using Android.OS;
using Avalonia.Android;
namespace ControlCatalog.Android namespace ControlCatalog.Android
{ {
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)] [Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity 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) protected override void OnCreate(Bundle? savedInstanceState)
{ {
base.OnCreate(savedInstanceState); base.OnCreate(savedInstanceState);

0
samples/ControlCatalog.Web/App.razor → samples/ControlCatalog.Blazor.Web/App.razor

17
samples/ControlCatalog.Blazor.Web/App.razor.cs

@ -0,0 +1,17 @@
using Avalonia;
using Avalonia.Web.Blazor;
namespace ControlCatalog.Blazor.Web;
public partial class App
{
protected override void OnParametersSet()
{
AppBuilder.Configure<ControlCatalog.App>()
.UseBlazor()
// .With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
.SetupWithSingleViewLifetime();
base.OnParametersSet();
}
}

29
samples/ControlCatalog.Blazor.Web/ControlCatalog.Blazor.Web.csproj

@ -0,0 +1,29 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<Nullable>enable</Nullable>
<EmccTotalMemory>16777216</EmccTotalMemory>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="7.0.0-rc.1.22427.2" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="7.0.0-rc.1.22427.2" PrivateAssets="all" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup>
<Import Project="..\..\build\ReferenceCoreLibraries.props" />
<Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.props" />
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.targets" />
</Project>

0
samples/ControlCatalog.Web/Pages/Index.razor → samples/ControlCatalog.Blazor.Web/Pages/Index.razor

29
samples/ControlCatalog.Blazor.Web/Program.cs

@ -0,0 +1,29 @@
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using ControlCatalog.Blazor.Web;
public class Program
{
public static async Task Main(string[] args)
{
await CreateHostBuilder(args).Build().RunAsync();
}
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
return builder;
}
}

0
samples/ControlCatalog.Web/Properties/launchSettings.json → samples/ControlCatalog.Blazor.Web/Properties/launchSettings.json

0
samples/ControlCatalog.Web/Shared/MainLayout.razor → samples/ControlCatalog.Blazor.Web/Shared/MainLayout.razor

3
samples/ControlCatalog.Web/_Imports.razor → samples/ControlCatalog.Blazor.Web/_Imports.razor

@ -6,6 +6,5 @@
@using Microsoft.AspNetCore.Components.Web.Virtualization @using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.AspNetCore.Components.WebAssembly.Http @using Microsoft.AspNetCore.Components.WebAssembly.Http
@using Microsoft.JSInterop @using Microsoft.JSInterop
@using ControlCatalog.Web @using ControlCatalog.Blazor.Web.Shared
@using ControlCatalog.Web.Shared
@using SkiaSharp @using SkiaSharp

0
samples/ControlCatalog.Web/wwwroot/css/app.css → samples/ControlCatalog.Blazor.Web/wwwroot/css/app.css

0
samples/ControlCatalog.Web/wwwroot/favicon.ico → samples/ControlCatalog.Blazor.Web/wwwroot/favicon.ico

Before

Width:  |  Height:  |  Size: 172 KiB

After

Width:  |  Height:  |  Size: 172 KiB

0
samples/ControlCatalog.Web/wwwroot/index.html → samples/ControlCatalog.Blazor.Web/wwwroot/index.html

20
samples/ControlCatalog.Web/App.razor.cs

@ -1,20 +0,0 @@
using Avalonia;
using Avalonia.Web.Blazor;
namespace ControlCatalog.Web;
public partial class App
{
protected override void OnParametersSet()
{
WebAppBuilder.Configure<ControlCatalog.App>()
.AfterSetup(_ =>
{
ControlCatalog.Pages.EmbedSample.Implementation = new EmbedSampleWeb();
})
.With(new SkiaOptions { CustomGpuFactory = null }) // uncomment to disable GPU/GL rendering
.SetupWithSingleViewLifetime();
base.OnParametersSet();
}
}

68
samples/ControlCatalog.Web/ControlCatalog.Web.csproj

@ -1,57 +1,45 @@
<Project Sdk="Microsoft.NET.Sdk.BlazorWebAssembly"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net6.0</TargetFramework> <TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable> <RuntimeIdentifier>browser-wasm</RuntimeIdentifier>
<!--Temporal hack that fixes compilation in VS--> <WasmMainJSPath>main.js</WasmMainJSPath>
<TypeScriptCompileBlocked>true</TypeScriptCompileBlocked> <OutputType>Exe</OutputType>
<EmccTotalMemory>16777216</EmccTotalMemory> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport> <MSBuildEnableWorkloadResolver>true</MSBuildEnableWorkloadResolver>
<BlazorWebAssemblyPreserveCollationData>false</BlazorWebAssemblyPreserveCollationData> <WasmBuildNative>true</WasmBuildNative>
<EmccFlags>-sVERBOSE -sERROR_ON_UNDEFINED_SYMBOLS=0</EmccFlags>
</PropertyGroup> </PropertyGroup>
<!-- In debug, make builds faster by reducing optimizations --> <PropertyGroup Condition="'$(Configuration)'=='Release'">
<PropertyGroup Condition="'$(Configuration)' == 'Debug'"> <RunAOTCompilation>true</RunAOTCompilation>
<WasmNativeStrip>false</WasmNativeStrip> <PublishTrimmed>true</PublishTrimmed>
<EmccCompileOptimizationFlag>-O1</EmccCompileOptimizationFlag> <TrimMode>full</TrimMode>
<RunAOTCompilation>false</RunAOTCompilation> <WasmBuildNative>true</WasmBuildNative>
</PropertyGroup> <InvariantGlobalization>true</InvariantGlobalization>
<WasmEnableSIMD>true</WasmEnableSIMD>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<Optimize>true</Optimize>
<WasmNativeStrip>true</WasmNativeStrip>
<EmccCompileOptimizationFlag>-O3</EmccCompileOptimizationFlag> <EmccCompileOptimizationFlag>-O3</EmccCompileOptimizationFlag>
<EmccLinkOptimizationFlag>-O3</EmccLinkOptimizationFlag> <EmccLinkOptimizationFlag>-O3</EmccLinkOptimizationFlag>
<RunAOTCompilation>false</RunAOTCompilation>
<DebuggerSupport>false</DebuggerSupport>
<EnableUnsafeBinaryFormatterSerialization>false</EnableUnsafeBinaryFormatterSerialization>
<EnableUnsafeUTF7Encoding>false</EnableUnsafeUTF7Encoding>
<EventSourceSupport>false</EventSourceSupport>
<HttpActivityPropagationSupport>false</HttpActivityPropagationSupport>
<InvariantGlobalization>true</InvariantGlobalization>
<MetadataUpdaterSupport>false</MetadataUpdaterSupport>
<UseNativeHttpHandler>true</UseNativeHttpHandler>
<UseSystemResourceKeys>true</UseSystemResourceKeys>
<PublishTrimmed>true</PublishTrimmed>
<TrimMode>link</TrimMode>
<TrimmerRemoveSymbols>true</TrimmerRemoveSymbols>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly" Version="6.0.0" /> <TrimmerRootDescriptor Include="Roots.xml" />
<PackageReference Include="Microsoft.AspNetCore.Components.WebAssembly.DevServer" Version="6.0.0" PrivateAssets="all" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" /> <ProjectReference Include="..\..\src\Skia\Avalonia.Skia\Avalonia.Skia.csproj" />
<ProjectReference Include="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.csproj" /> <ProjectReference Include="..\..\src\Web\Avalonia.Web\Avalonia.Web.csproj" />
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" /> <ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\ReferenceCoreLibraries.props" /> <ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <WasmExtraFilesToDeploy Include="index.html" />
<WasmExtraFilesToDeploy Include="main.js" />
<Import Project="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.targets" /> <WasmExtraFilesToDeploy Include="embed.js" />
<Import Project="..\..\src\Web\Avalonia.Web.Blazor\Avalonia.Web.Blazor.CompilationTuning.props" /> <WasmExtraFilesToDeploy Include="favicon.ico" />
<WasmExtraFilesToDeploy Include="Logo.svg" />
<WasmExtraFilesToDeploy Include="app.css" />
</ItemGroup>
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.props" />
<Import Project="..\..\src\Web\Avalonia.Web\Avalonia.Web.targets" />
</Project> </Project>

32
samples/ControlCatalog.Web/EmbedSample.Browser.cs

@ -1,34 +1,42 @@
using System; using System;
using System.Runtime.InteropServices.JavaScript;
using Avalonia;
using Avalonia.Platform; using Avalonia.Platform;
using Avalonia.Web.Blazor; using Avalonia.Web;
using ControlCatalog.Pages; using ControlCatalog.Pages;
using Microsoft.JSInterop;
namespace ControlCatalog.Web; namespace ControlCatalog.Web;
public class EmbedSampleWeb : INativeDemoControl public class EmbedSampleWeb : INativeDemoControl
{ {
public IPlatformHandle CreateControl(bool isSecond, IPlatformHandle parent, Func<IPlatformHandle> createDefault) public IPlatformHandle CreateControl(bool isSecond, IPlatformHandle parent, Func<IPlatformHandle> createDefault)
{ {
var runtime = AvaloniaLocator.Current.GetRequiredService<IJSInProcessRuntime>();
if (isSecond) if (isSecond)
{ {
var iframe = runtime.Invoke<IJSInProcessObjectReference>("document.createElement", "iframe"); var iframe = EmbedInterop.CreateElement("iframe");
iframe.InvokeVoid("setAttribute", "src", "https://www.youtube.com/embed/kZCIporjJ70"); iframe.SetProperty("src", "https://www.youtube.com/embed/kZCIporjJ70");
return new JSObjectControlHandle(iframe); return new JSObjectControlHandle(iframe);
} }
else else
{ {
// window.createAppButton source is defined in "app.js" file. var defaultHandle = (JSObjectControlHandle)createDefault();
var button = runtime.Invoke<IJSInProcessObjectReference>("window.createAppButton");
_ = JSHost.ImportAsync("embed.js", "./embed.js").ContinueWith(_ =>
{
EmbedInterop.AddAppButton(defaultHandle.Object);
});
return new JSObjectControlHandle(button); return defaultHandle;
} }
} }
} }
internal static partial class EmbedInterop
{
[JSImport("globalThis.document.createElement")]
public static partial JSObject CreateElement(string tagName);
[JSImport("addAppButton", "embed.js")]
public static partial void AddAppButton(JSObject parentObject);
}

5
samples/ControlCatalog.Web/Logo.svg

@ -0,0 +1,5 @@
<svg width="35" height="35" viewBox="0 0 35 35" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M30.4661 34.928C30.5364 34.928 30.6052 34.928 30.6754 34.928C32.8596 34.928 34.654 33.2918 34.9053 31.1752L34.9356 16.9955C34.6872 7.56697 26.9662 0 17.4777 0C7.83263 0 0.0137329 7.8189 0.0137329 17.464C0.0137329 27.0059 7.66618 34.7631 17.1687 34.928H30.4661Z" fill="white"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5239 5.948C12.0268 5.948 7.42967 9.80117 6.286 14.954C7.38092 15.2609 8.18385 16.2664 8.18385 17.4593C8.18385 18.6523 7.38092 19.6577 6.286 19.9647C7.42966 25.1175 12.0268 28.9706 17.5239 28.9706C19.525 28.9706 21.4068 28.4601 23.0462 27.562V28.8927H29.0352V17.9365C29.0407 17.7908 29.0352 17.6063 29.0352 17.4593C29.0352 11.1018 23.8814 5.948 17.5239 5.948ZM12.0098 17.4593C12.0098 14.414 14.4786 11.9452 17.5239 11.9452C20.5693 11.9452 23.038 14.414 23.038 17.4593C23.038 20.5047 20.5693 22.9734 17.5239 22.9734C14.4786 22.9734 12.0098 20.5047 12.0098 17.4593Z" fill="#8B44AC"/>
<path d="M7.36841 17.4517C7.36841 18.4691 6.54368 19.2938 5.52631 19.2938C4.50894 19.2938 3.6842 18.4691 3.6842 17.4517C3.6842 16.4343 4.50894 15.6096 5.52631 15.6096C6.54368 15.6096 7.36841 16.4343 7.36841 17.4517Z" fill="#8B44AC"/>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

37
samples/ControlCatalog.Web/Program.cs

@ -1,29 +1,22 @@
using System; using System.Runtime.Versioning;
using System.Net.Http; using Avalonia;
using System.Threading.Tasks; using Avalonia.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting; using ControlCatalog;
using Microsoft.Extensions.DependencyInjection;
using ControlCatalog.Web; using ControlCatalog.Web;
public class Program [assembly:SupportedOSPlatform("browser")]
internal partial class Program
{ {
public static async Task Main(string[] args) private static void Main(string[] args)
{ {
await CreateHostBuilder(args).Build().RunAsync(); BuildAvaloniaApp()
.AfterSetup(_ =>
{
ControlCatalog.Pages.EmbedSample.Implementation = new EmbedSampleWeb();
}).SetupBrowserApp("out");
} }
public static WebAssemblyHostBuilder CreateHostBuilder(string[] args) public static AppBuilder BuildAvaloniaApp()
{ => AppBuilder.Configure<App>();
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
return builder;
}
} }

6
samples/ControlCatalog.Web/Roots.xml

@ -0,0 +1,6 @@
<linker>
<assembly fullname="ControlCatalog" preserve="All" />
<assembly fullname="ControlCatalog.Web" preserve="All" />
<assembly fullname="Avalonia.Themes.Fluent" preserve="All" />
<assembly fullname="Avalonia.Themes.Simple" preserve="All" />
</linker>

49
samples/ControlCatalog.Web/app.css

@ -0,0 +1,49 @@
#out {
height: 100vh;
width: 100vw
}
#avalonia-splash {
position: relative;
height: 100%;
width: 100%;
color: whitesmoke;
background: #171C2C;
font-family: 'Nunito', sans-serif;
background-position: center;
background-size: cover;
background-repeat: no-repeat;
}
#avalonia-splash a{
color: whitesmoke;
text-decoration: none;
}
.center {
display: flex;
justify-content: center;
height: 250px;
}
.splash-close {
animation: slide 0.5s linear 1s forwards;
}
@keyframes slide {
0% {
top: 0%;
}
50% {
opacity: 80%;
}
100% {
top: 100%;
overflow: hidden;
opacity: 0;
display: none;
visibility: collapse;
}
}

11
samples/ControlCatalog.Web/embed.js

@ -0,0 +1,11 @@
export function addAppButton(parent) {
var button = globalThis.document.createElement('button');
button.innerText = 'Hello world';
var clickCount = 0;
button.onclick = () => {
clickCount++;
button.innerText = 'Click count ' + clickCount;
};
parent.appendChild(button);
return button;
}

BIN
samples/ControlCatalog.Web/favicon.ico

Binary file not shown.

After

Width:  |  Height:  |  Size: 172 KiB

31
samples/ControlCatalog.Web/index.html

@ -0,0 +1,31 @@
<!DOCTYPE html>
<!-- Licensed to the .NET Foundation under one or more agreements. -->
<!-- The .NET Foundation licenses this file to you under the MIT license. -->
<html>
<head>
<title>AvaloniaUI - ControlCatalog</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="modulepreload" href="./main.js" />
<link rel="modulepreload" href="./dotnet.js" />
<link rel="modulepreload" href="./avalonia.js" />
<link rel="stylesheet" href="./app.css" />
</head>
<body style="margin: 0px">
<div id="out">
<div id="avalonia-splash">
<div class="center">
<h2>Powered by</h2>
<a class="navbar-brand" href="https://www.avaloniaui.net/" target="_blank">
<img src="Logo.svg" alt="Avalonia Logo" width="30" height="24" />
Avalonia
</a>
</div>
</div>
</div>
<script type='module' src="./main.js"></script>
</body>
</html>

19
samples/ControlCatalog.Web/main.js

@ -0,0 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
import { dotnet } from './dotnet.js'
import { registerAvaloniaModule } from './avalonia.js';
const is_browser = typeof window != "undefined";
if (!is_browser) throw new Error(`Expected to be running in a browser`);
const dotnetRuntime = await dotnet
.withDiagnosticTracing(false)
.withApplicationArgumentsFromQuery()
.create();
await registerAvaloniaModule(dotnetRuntime);
const config = dotnetRuntime.getConfig();
await dotnetRuntime.runMainAndExit(config.mainAssemblyName, ["dotnet", "is", "great!"]);

11
samples/ControlCatalog.Web/runtimeconfig.template.json

@ -0,0 +1,11 @@
{
"wasmHostProperties": {
"perHostConfig": [
{
"name": "browser",
"html-path": "index.html",
"Host": "browser"
}
]
}
}

4
samples/MobileSandbox.Android/MainActivity.cs

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

4
samples/MobileSandbox.Android/SplashActivity.cs

@ -1,11 +1,11 @@
using Android.App; using Android.App;
using Android.Content; using Android.Content;
using Android.OS; using Avalonia.Android;
namespace MobileSandbox.Android namespace MobileSandbox.Android
{ {
[Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)] [Activity(Theme = "@style/MyTheme.Splash", MainLauncher = true, NoHistory = true)]
public class SplashActivity : Activity public class SplashActivity : AvaloniaSplashActivity<App>
{ {
protected override void OnResume() protected override void OnResume()
{ {

105
src/Android/Avalonia.Android/AvaloniaActivity.cs

@ -1,105 +0,0 @@
using Android.OS;
using AndroidX.AppCompat.App;
using Android.Content.Res;
using AndroidX.Lifecycle;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Controls;
using Android.Runtime;
using Android.App;
using Android.Content;
using System;
namespace Avalonia.Android
{
public abstract class AvaloniaActivity : AppCompatActivity
{
internal class SingleViewLifetime : ISingleViewApplicationLifetime
{
public AvaloniaView View { get; internal set; }
public Control MainView
{
get => (Control)View.Content;
set => View.Content = value;
}
}
internal Action<int, Result, Intent> ActivityResult;
internal AvaloniaView View;
internal AvaloniaViewModel _viewModel;
protected abstract AppBuilder CreateAppBuilder();
protected override void OnCreate(Bundle savedInstanceState)
{
var builder = CreateAppBuilder();
var lifetime = new SingleViewLifetime();
builder.AfterSetup(x =>
{
_viewModel = new ViewModelProvider(this).Get(Java.Lang.Class.FromType(typeof(AvaloniaViewModel))) as AvaloniaViewModel;
View = new AvaloniaView(this);
if (_viewModel.Content != null)
{
View.Content = _viewModel.Content;
}
SetContentView(View);
lifetime.View = View;
View.Prepare();
});
builder.SetupWithLifetime(lifetime);
base.OnCreate(savedInstanceState);
}
public object Content
{
get
{
return _viewModel.Content;
}
set
{
_viewModel.Content = value;
if (View != null)
View.Content = value;
}
}
public override void OnConfigurationChanged(Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
}
protected override void OnDestroy()
{
View.Content = null;
base.OnDestroy();
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
ActivityResult?.Invoke(requestCode, resultCode, data);
}
}
public abstract class AvaloniaActivity<TApp> : AvaloniaActivity where TApp : Application, new()
{
protected virtual AppBuilder CustomizeAppBuilder(AppBuilder builder) => builder.UseAndroid();
protected override AppBuilder CreateAppBuilder()
{
var builder = AppBuilder.Configure<TApp>();
return CustomizeAppBuilder(builder);
}
}
}

72
src/Android/Avalonia.Android/AvaloniaMainActivity.cs

@ -0,0 +1,72 @@
using System;
using Android.App;
using Android.Content;
using Android.Content.Res;
using Android.OS;
using Android.Runtime;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
namespace Avalonia.Android
{
public abstract class AvaloniaMainActivity : AppCompatActivity
{
internal static object ViewContent;
internal Action<int, Result, Intent> ActivityResult;
internal AvaloniaView View;
protected override void OnCreate(Bundle savedInstanceState)
{
View = new AvaloniaView(this);
if (ViewContent != null)
{
View.Content = ViewContent;
}
View.Prepare();
if (Avalonia.Application.Current.ApplicationLifetime is SingleViewLifetime lifetime)
{
lifetime.View = View;
}
base.OnCreate(savedInstanceState);
SetContentView(View);
}
public object Content
{
get
{
return ViewContent;
}
set
{
ViewContent = value;
if (View != null)
View.Content = value;
}
}
public override void OnConfigurationChanged(Configuration newConfig)
{
base.OnConfigurationChanged(newConfig);
}
protected override void OnDestroy()
{
View.Content = null;
base.OnDestroy();
}
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
ActivityResult?.Invoke(requestCode, resultCode, data);
}
}
}

34
src/Android/Avalonia.Android/AvaloniaSplashActivity.cs

@ -0,0 +1,34 @@
using Android.OS;
using AndroidX.AppCompat.App;
using AndroidX.Lifecycle;
namespace Avalonia.Android
{
public abstract class AvaloniaSplashActivity : AppCompatActivity
{
protected abstract AppBuilder CreateAppBuilder();
protected override void OnCreate(Bundle? savedInstanceState)
{
base.OnCreate(savedInstanceState);
var builder = CreateAppBuilder();
var lifetime = new SingleViewLifetime();
builder.SetupWithLifetime(lifetime);
}
}
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);
}
}
}

11
src/Android/Avalonia.Android/AvaloniaViewModel.cs

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Avalonia.Android
{
internal class AvaloniaViewModel : AndroidX.Lifecycle.ViewModel
{
public object Content { get; set; }
}
}

6
src/Android/Avalonia.Android/OpenGL/GlPlatformSurface.cs

@ -1,4 +1,5 @@
using Avalonia.OpenGL.Egl; using Avalonia.OpenGL;
using Avalonia.OpenGL.Egl;
using Avalonia.OpenGL.Surfaces; using Avalonia.OpenGL.Surfaces;
namespace Avalonia.Android.OpenGL namespace Avalonia.Android.OpenGL
@ -19,7 +20,8 @@ namespace Avalonia.Android.OpenGL
public static GlPlatformSurface TryCreate(IEglWindowGlPlatformSurfaceInfo info) public static GlPlatformSurface TryCreate(IEglWindowGlPlatformSurfaceInfo info)
{ {
if (EglPlatformOpenGlInterface.TryCreate() is EglPlatformOpenGlInterface egl) var feature = AvaloniaLocator.Current.GetService<IPlatformOpenGlInterface>();
if (feature is EglPlatformOpenGlInterface egl)
{ {
return new GlPlatformSurface(egl, info); return new GlPlatformSurface(egl, info);
} }

11
src/Android/Avalonia.Android/Platform/SkiaPlatform/TopLevelImpl.cs

@ -3,20 +3,14 @@ using System.Collections.Generic;
using Android.Content; using Android.Content;
using Android.Graphics; using Android.Graphics;
using Android.Media.TV;
using Android.OS;
using Android.Runtime; using Android.Runtime;
using Android.Text;
using Android.Views; using Android.Views;
using Android.Views.InputMethods; using Android.Views.InputMethods;
using Android.Widget;
using Avalonia.Android.OpenGL; using Avalonia.Android.OpenGL;
using Avalonia.Android.Platform.Input;
using Avalonia.Android.Platform.Specific; using Avalonia.Android.Platform.Specific;
using Avalonia.Android.Platform.Specific.Helpers; using Avalonia.Android.Platform.Specific.Helpers;
using Avalonia.Android.Platform.Storage; using Avalonia.Android.Platform.Storage;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Controls.Platform.Surfaces; using Avalonia.Controls.Platform.Surfaces;
using Avalonia.Input; using Avalonia.Input;
@ -29,7 +23,6 @@ using Avalonia.Platform.Storage;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Rendering.Composition; using Avalonia.Rendering.Composition;
using Java.Lang; using Java.Lang;
using static System.Net.Mime.MediaTypeNames;
namespace Avalonia.Android.Platform.SkiaPlatform namespace Avalonia.Android.Platform.SkiaPlatform
{ {
@ -59,7 +52,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
_view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling); _view.Resources.DisplayMetrics.HeightPixels).ToSize(RenderScaling);
NativeControlHost = new AndroidNativeControlHostImpl(avaloniaView); NativeControlHost = new AndroidNativeControlHostImpl(avaloniaView);
StorageProvider = new AndroidStorageProvider((AvaloniaActivity)avaloniaView.Context); StorageProvider = new AndroidStorageProvider((AvaloniaMainActivity)avaloniaView.Context);
} }
public virtual Point GetAvaloniaPointFromEvent(MotionEvent e, int pointerIndex) => public virtual Point GetAvaloniaPointFromEvent(MotionEvent e, int pointerIndex) =>
@ -301,7 +294,7 @@ namespace Avalonia.Android.Platform.SkiaPlatform
IsComposing = true; IsComposing = true;
_inputMethod.Client.SetPreeditText(ComposingText); _inputMethod.Client?.SetPreeditText(ComposingText);
return base.SetComposingText(text, newCursorPosition); return base.SetComposingText(text, newCursorPosition);
} }

4
src/Android/Avalonia.Android/Platform/Storage/AndroidStorageProvider.cs

@ -14,10 +14,10 @@ namespace Avalonia.Android.Platform.Storage;
internal class AndroidStorageProvider : IStorageProvider internal class AndroidStorageProvider : IStorageProvider
{ {
private readonly AvaloniaActivity _activity; private readonly AvaloniaMainActivity _activity;
private int _lastRequestCode = 20000; private int _lastRequestCode = 20000;
public AndroidStorageProvider(AvaloniaActivity activity) public AndroidStorageProvider(AvaloniaMainActivity activity)
{ {
_activity = activity; _activity = activity;
} }

26
src/Android/Avalonia.Android/SingleViewLifetime.cs

@ -0,0 +1,26 @@
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
namespace Avalonia.Android
{
internal class SingleViewLifetime : ISingleViewApplicationLifetime
{
private AvaloniaView _view;
public AvaloniaView View
{
get => _view; internal set
{
if (_view != null)
{
_view.Content = null;
_view.Dispose();
}
_view = value;
_view.Content = MainView;
}
}
public Control MainView { get; set; }
}
}

2
src/Avalonia.Base/Input/Cursor.cs

@ -33,7 +33,7 @@ namespace Avalonia.Input
DragLink, DragLink,
None, None,
// Not available in GTK directly, see http://www.pixelbeat.org/programming/x_cursors/ // Not available in GTK directly, see https://www.pixelbeat.org/programming/x_cursors/
// We might enable them later, preferably, by loading pixmax directly from theme with fallback image // We might enable them later, preferably, by loading pixmax directly from theme with fallback image
// SizeNorthWestSouthEast, // SizeNorthWestSouthEast,
// SizeNorthEastSouthWest, // SizeNorthEastSouthWest,

35
src/Avalonia.Base/Logging/LogArea.cs

@ -8,51 +8,66 @@ namespace Avalonia.Logging
/// <summary> /// <summary>
/// The log event comes from the property system. /// The log event comes from the property system.
/// </summary> /// </summary>
public const string Property = "Property"; public const string Property = nameof(Property);
/// <summary> /// <summary>
/// The log event comes from the binding system. /// The log event comes from the binding system.
/// </summary> /// </summary>
public const string Binding = "Binding"; public const string Binding = nameof(Binding);
/// <summary> /// <summary>
/// The log event comes from the animations system. /// The log event comes from the animations system.
/// </summary> /// </summary>
public const string Animations = "Animations"; public const string Animations = nameof(Animations);
/// <summary> /// <summary>
/// The log event comes from the visual system. /// The log event comes from the visual system.
/// </summary> /// </summary>
public const string Visual = "Visual"; public const string Visual = nameof(Visual);
/// <summary> /// <summary>
/// The log event comes from the layout system. /// The log event comes from the layout system.
/// </summary> /// </summary>
public const string Layout = "Layout"; public const string Layout = nameof(Layout);
/// <summary> /// <summary>
/// The log event comes from the control system. /// The log event comes from the control system.
/// </summary> /// </summary>
public const string Control = "Control"; public const string Control = nameof(Control);
/// <summary> /// <summary>
/// The log event comes from Win32Platform. /// The log event comes from Win32 Platform.
/// </summary> /// </summary>
public const string Win32Platform = nameof(Win32Platform); public const string Win32Platform = nameof(Win32Platform);
/// <summary> /// <summary>
/// The log event comes from X11Platform. /// The log event comes from X11 Platform.
/// </summary> /// </summary>
public const string X11Platform = nameof(X11Platform); public const string X11Platform = nameof(X11Platform);
/// <summary> /// <summary>
/// The log event comes from AndroidPlatform. /// The log event comes from Android Platform.
/// </summary> /// </summary>
public const string AndroidPlatform = nameof(AndroidPlatform); public const string AndroidPlatform = nameof(AndroidPlatform);
/// <summary> /// <summary>
/// The log event comes from IOSPlatform. /// The log event comes from iOS Platform.
/// </summary> /// </summary>
public const string IOSPlatform = nameof(IOSPlatform); public const string IOSPlatform = nameof(IOSPlatform);
/// <summary>
/// The log event comes from LinuxFramebuffer Platform
/// </summary>
public const string LinuxFramebufferPlatform = nameof(LinuxFramebufferPlatform);
/// <summary>
/// The log event comes from FreeDesktop Platform
/// </summary>
public const string FreeDesktopPlatform = nameof(FreeDesktopPlatform);
/// <summary>
/// The log event comes from macOS Platform
/// </summary>
public const string macOSPlatform = nameof(macOSPlatform);
} }
} }

2
src/Avalonia.Base/Media/PreciseEllipticArcHelper.cs

@ -1081,7 +1081,7 @@ namespace Avalonia.Media
Point c = rest * (cs) + translation; Point c = rest * (cs) + translation;
// See "http://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter" to understand // See "https://www.w3.org/TR/SVG/implnote.html#ArcConversionEndpointToCenter" to understand
// how the ellipse center is calculated // how the ellipse center is calculated

2
src/Avalonia.Base/Media/TextFormatting/Unicode/BinaryReaderExtensions.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain // not use this product except in compliance with the License. You may obtain
// a copy of the License at // a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/Codepoint.cs

@ -104,7 +104,7 @@ namespace Avalonia.Media.TextFormatting.Unicode
/// <summary> /// <summary>
/// Gets the canonical representation of a given codepoint. /// Gets the canonical representation of a given codepoint.
/// <see href="http://www.unicode.org/L2/L2013/13123-norm-and-bpa.pdf"/> /// <see href="https://www.unicode.org/L2/L2013/13123-norm-and-bpa.pdf"/>
/// </summary> /// </summary>
/// <param name="codePoint">The code point to be mapped.</param> /// <param name="codePoint">The code point to be mapped.</param>
/// <returns>The mapped canonical code point, or the passed <paramref name="codePoint"/>.</returns> /// <returns>The mapped canonical code point, or the passed <paramref name="codePoint"/>.</returns>

2
src/Avalonia.Base/Media/TextFormatting/Unicode/LineBreak.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain // not use this product except in compliance with the License. You may obtain
// a copy of the License at // a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrie.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain // not use this product except in compliance with the License. You may obtain
// a copy of the License at // a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.Constants.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain // not use this product except in compliance with the License. You may obtain
// a copy of the License at // a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Media/TextFormatting/Unicode/UnicodeTrieBuilder.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain // not use this product except in compliance with the License. You may obtain
// a copy of the License at // a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

2
src/Avalonia.Base/Platform/Storage/IStorageFile.cs

@ -18,6 +18,7 @@ public interface IStorageFile : IStorageItem
/// <summary> /// <summary>
/// Opens a stream for read access. /// Opens a stream for read access.
/// </summary> /// </summary>
/// <exception cref="System.UnauthorizedAccessException" />
Task<Stream> OpenReadAsync(); Task<Stream> OpenReadAsync();
/// <summary> /// <summary>
@ -28,5 +29,6 @@ public interface IStorageFile : IStorageItem
/// <summary> /// <summary>
/// Opens stream for writing to the file. /// Opens stream for writing to the file.
/// </summary> /// </summary>
/// <exception cref="System.UnauthorizedAccessException" />
Task<Stream> OpenWriteAsync(); Task<Stream> OpenWriteAsync();
} }

1
src/Avalonia.Base/Properties/AssemblyInfo.cs

@ -30,4 +30,5 @@ using Avalonia.Metadata;
[assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.Skia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: InternalsVisibleTo("Avalonia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.UnitTests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: InternalsVisibleTo("Avalonia.Web.Blazor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")] [assembly: InternalsVisibleTo("Avalonia.Web.Blazor, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: InternalsVisibleTo("Avalonia.Web, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c1bba1142285fe0419326fb25866ba62c47e6c2b5c1ab0c95b46413fad375471232cb81706932e1cef38781b9ebd39d5100401bacb651c6c5bbf59e571e81b3bc08d2a622004e08b1a6ece82a7e0b9857525c86d2b95fab4bc3dce148558d7f3ae61aa3a234086902aeface87d9dfdd32b9d2fe3c6dd4055b5ab4b104998bd87")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

2
src/Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs

@ -1,9 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Xml.Linq; using System.Xml.Linq;
using System.Linq; using System.Linq;

2
src/Avalonia.Base/Utilities/BinarySearchExtension.cs

@ -5,7 +5,7 @@
// not use this product except in compliance with the License. You may obtain // not use this product except in compliance with the License. You may obtain
// a copy of the License at // a copy of the License at
// //
// http://www.apache.org/licenses/LICENSE-2.0 // https://www.apache.org/licenses/LICENSE-2.0
// //
// Unless required by applicable law or agreed to in writing, software // Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT

7
src/Avalonia.Build.Tasks/Avalonia.Build.Tasks.csproj

@ -9,6 +9,11 @@
<NoWarn>NU1605;CS8632</NoWarn> <NoWarn>NU1605;CS8632</NoWarn>
</PropertyGroup> </PropertyGroup>
<!--Disable Net Perf. analyzer for submodule to avoid commit issue -->
<PropertyGroup>
<EnableNETAnalyzers>false</EnableNETAnalyzers>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="../Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs"> <Compile Include="../Avalonia.Base/Utilities/AvaloniaResourcesIndex.cs">
<Link>Shared/AvaloniaResourcesIndex.cs</Link> <Link>Shared/AvaloniaResourcesIndex.cs</Link>
@ -105,7 +110,7 @@
<Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" /> <Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\**\obj\**\*.cs" /> <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\**\obj\**\*.cs" />
<Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" /> <Compile Remove="../Markup/Avalonia.Markup.Xaml.Loader\xamlil.github\src\XamlX\IL\SreTypeSystem.cs" />
<PackageReference Include="Mono.Cecil" Version="0.11.2" /> <PackageReference Include="Mono.Cecil" Version="0.11.4" />
<PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" PrivateAssets="All" /> <PackageReference Include="Microsoft.Build.Framework" Version="15.1.548" PrivateAssets="All" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" /> <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
</ItemGroup> </ItemGroup>

1
src/Avalonia.Build.Tasks/GenerateAvaloniaResourcesTask.cs

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.Text; using System.Text;
using Avalonia.Markup.Xaml.PortableXaml; using Avalonia.Markup.Xaml.PortableXaml;
using Avalonia.Utilities; using Avalonia.Utilities;

359
src/Avalonia.Controls.ColorPicker/ColorPalettes/MaterialColorPalette.cs

@ -0,0 +1,359 @@
using Avalonia.Media;
using Avalonia.Utilities;
namespace Avalonia.Controls
{
/// <summary>
/// Implements a reduced version of the 2014 Material Design color palette.
/// </summary>
/// <remarks>
/// This palette is based on the one outlined here:
///
/// https://material.io/design/color/the-color-system.html#tools-for-picking-colors
///
/// In order to make the palette uniform and rectangular the following
/// alterations were made:
///
/// 1. The A100-A700 shades of each color are excluded.
/// These shades do not exist for all colors (brown/gray).
/// 2. Black/White are stand-alone and are also excluded.
///
/// </remarks>
public class MaterialColorPalette : IColorPalette
{
// See: https://material.io/design/color/the-color-system.html#tools-for-picking-colors
// This is a reduced palette for uniformity
private static Color[,]? _colorChart = null;
private static int _colorChartColorCount = 0;
private static int _colorChartShadeCount = 0;
private static object _colorChartMutex = new object();
/// <summary>
/// Initializes all color chart colors.
/// </summary>
/// <remarks>
/// This is pulled out separately to lazy load for performance.
/// If no material color palette is ever used, no colors will be created.
/// </remarks>
private void InitColorChart()
{
lock (_colorChartMutex)
{
_colorChart = new Color[,]
{
// Red
{
Color.FromArgb(0xFF, 0xFF, 0xEB, 0xEE),
Color.FromArgb(0xFF, 0xFF, 0xCD, 0xD2),
Color.FromArgb(0xFF, 0xEF, 0x9A, 0x9A),
Color.FromArgb(0xFF, 0xE5, 0x73, 0x73),
Color.FromArgb(0xFF, 0xEF, 0x53, 0x50),
Color.FromArgb(0xFF, 0xF4, 0x43, 0x36),
Color.FromArgb(0xFF, 0xE5, 0x39, 0x35),
Color.FromArgb(0xFF, 0xD3, 0x2F, 0x2F),
Color.FromArgb(0xFF, 0xC6, 0x28, 0x28),
Color.FromArgb(0xFF, 0xB7, 0x1C, 0x1C),
},
// Pink
{
Color.FromArgb(0xFF, 0xFC, 0xE4, 0xEC),
Color.FromArgb(0xFF, 0xF8, 0xBB, 0xD0),
Color.FromArgb(0xFF, 0xF4, 0x8F, 0xB1),
Color.FromArgb(0xFF, 0xF0, 0x62, 0x92),
Color.FromArgb(0xFF, 0xEC, 0x40, 0x7A),
Color.FromArgb(0xFF, 0xE9, 0x1E, 0x63),
Color.FromArgb(0xFF, 0xD8, 0x1B, 0x60),
Color.FromArgb(0xFF, 0xC2, 0x18, 0x5B),
Color.FromArgb(0xFF, 0xAD, 0x14, 0x57),
Color.FromArgb(0xFF, 0x88, 0x0E, 0x4F),
},
// Purple
{
Color.FromArgb(0xFF, 0xF3, 0xE5, 0xF5),
Color.FromArgb(0xFF, 0xE1, 0xBE, 0xE7),
Color.FromArgb(0xFF, 0xCE, 0x93, 0xD8),
Color.FromArgb(0xFF, 0xBA, 0x68, 0xC8),
Color.FromArgb(0xFF, 0xAB, 0x47, 0xBC),
Color.FromArgb(0xFF, 0x9C, 0x27, 0xB0),
Color.FromArgb(0xFF, 0x8E, 0x24, 0xAA),
Color.FromArgb(0xFF, 0x7B, 0x1F, 0xA2),
Color.FromArgb(0xFF, 0x6A, 0x1B, 0x9A),
Color.FromArgb(0xFF, 0x4A, 0x14, 0x8C),
},
// Deep Purple
{
Color.FromArgb(0xFF, 0xED, 0xE7, 0xF6),
Color.FromArgb(0xFF, 0xD1, 0xC4, 0xE9),
Color.FromArgb(0xFF, 0xB3, 0x9D, 0xDB),
Color.FromArgb(0xFF, 0x95, 0x75, 0xCD),
Color.FromArgb(0xFF, 0x7E, 0x57, 0xC2),
Color.FromArgb(0xFF, 0x67, 0x3A, 0xB7),
Color.FromArgb(0xFF, 0x5E, 0x35, 0xB1),
Color.FromArgb(0xFF, 0x51, 0x2D, 0xA8),
Color.FromArgb(0xFF, 0x45, 0x27, 0xA0),
Color.FromArgb(0xFF, 0x31, 0x1B, 0x92),
},
// Indigo
{
Color.FromArgb(0xFF, 0xE8, 0xEA, 0xF6),
Color.FromArgb(0xFF, 0xC5, 0xCA, 0xE9),
Color.FromArgb(0xFF, 0x9F, 0xA8, 0xDA),
Color.FromArgb(0xFF, 0x79, 0x86, 0xCB),
Color.FromArgb(0xFF, 0x5C, 0x6B, 0xC0),
Color.FromArgb(0xFF, 0x3F, 0x51, 0xB5),
Color.FromArgb(0xFF, 0x39, 0x49, 0xAB),
Color.FromArgb(0xFF, 0x30, 0x3F, 0x9F),
Color.FromArgb(0xFF, 0x28, 0x35, 0x93),
Color.FromArgb(0xFF, 0x1A, 0x23, 0x7E),
},
// Blue
{
Color.FromArgb(0xFF, 0xE3, 0xF2, 0xFD),
Color.FromArgb(0xFF, 0xBB, 0xDE, 0xFB),
Color.FromArgb(0xFF, 0x90, 0xCA, 0xF9),
Color.FromArgb(0xFF, 0x64, 0xB5, 0xF6),
Color.FromArgb(0xFF, 0x42, 0xA5, 0xF5),
Color.FromArgb(0xFF, 0x21, 0x96, 0xF3),
Color.FromArgb(0xFF, 0x1E, 0x88, 0xE5),
Color.FromArgb(0xFF, 0x19, 0x76, 0xD2),
Color.FromArgb(0xFF, 0x15, 0x65, 0xC0),
Color.FromArgb(0xFF, 0x0D, 0x47, 0xA1),
},
// Light Blue
{
Color.FromArgb(0xFF, 0xE1, 0xF5, 0xFE),
Color.FromArgb(0xFF, 0xB3, 0xE5, 0xFC),
Color.FromArgb(0xFF, 0x81, 0xD4, 0xFA),
Color.FromArgb(0xFF, 0x4F, 0xC3, 0xF7),
Color.FromArgb(0xFF, 0x29, 0xB6, 0xF6),
Color.FromArgb(0xFF, 0x03, 0xA9, 0xF4),
Color.FromArgb(0xFF, 0x03, 0x9B, 0xE5),
Color.FromArgb(0xFF, 0x02, 0x88, 0xD1),
Color.FromArgb(0xFF, 0x02, 0x77, 0xBD),
Color.FromArgb(0xFF, 0x01, 0x57, 0x9B),
},
// Cyan
{
Color.FromArgb(0xFF, 0xE0, 0xF7, 0xFA),
Color.FromArgb(0xFF, 0xB2, 0xEB, 0xF2),
Color.FromArgb(0xFF, 0x80, 0xDE, 0xEA),
Color.FromArgb(0xFF, 0x4D, 0xD0, 0xE1),
Color.FromArgb(0xFF, 0x26, 0xC6, 0xDA),
Color.FromArgb(0xFF, 0x00, 0xBC, 0xD4),
Color.FromArgb(0xFF, 0x00, 0xAC, 0xC1),
Color.FromArgb(0xFF, 0x00, 0x97, 0xA7),
Color.FromArgb(0xFF, 0x00, 0x83, 0x8F),
Color.FromArgb(0xFF, 0x00, 0x60, 0x64),
},
// Teal
{
Color.FromArgb(0xFF, 0xE0, 0xF2, 0xF1),
Color.FromArgb(0xFF, 0xB2, 0xDF, 0xDB),
Color.FromArgb(0xFF, 0x80, 0xCB, 0xC4),
Color.FromArgb(0xFF, 0x4D, 0xB6, 0xAC),
Color.FromArgb(0xFF, 0x26, 0xA6, 0x9A),
Color.FromArgb(0xFF, 0x00, 0x96, 0x88),
Color.FromArgb(0xFF, 0x00, 0x89, 0x7B),
Color.FromArgb(0xFF, 0x00, 0x79, 0x6B),
Color.FromArgb(0xFF, 0x00, 0x69, 0x5C),
Color.FromArgb(0xFF, 0x00, 0x4D, 0x40),
},
// Green
{
Color.FromArgb(0xFF, 0xE8, 0xF5, 0xE9),
Color.FromArgb(0xFF, 0xC8, 0xE6, 0xC9),
Color.FromArgb(0xFF, 0xA5, 0xD6, 0xA7),
Color.FromArgb(0xFF, 0x81, 0xC7, 0x84),
Color.FromArgb(0xFF, 0x66, 0xBB, 0x6A),
Color.FromArgb(0xFF, 0x4C, 0xAF, 0x50),
Color.FromArgb(0xFF, 0x43, 0xA0, 0x47),
Color.FromArgb(0xFF, 0x38, 0x8E, 0x3C),
Color.FromArgb(0xFF, 0x2E, 0x7D, 0x32),
Color.FromArgb(0xFF, 0x1B, 0x5E, 0x20),
},
// Light Green
{
Color.FromArgb(0xFF, 0xF1, 0xF8, 0xE9),
Color.FromArgb(0xFF, 0xDC, 0xED, 0xC8),
Color.FromArgb(0xFF, 0xC5, 0xE1, 0xA5),
Color.FromArgb(0xFF, 0xAE, 0xD5, 0x81),
Color.FromArgb(0xFF, 0x9C, 0xCC, 0x65),
Color.FromArgb(0xFF, 0x8B, 0xC3, 0x4A),
Color.FromArgb(0xFF, 0x7C, 0xB3, 0x42),
Color.FromArgb(0xFF, 0x68, 0x9F, 0x38),
Color.FromArgb(0xFF, 0x55, 0x8B, 0x2F),
Color.FromArgb(0xFF, 0x33, 0x69, 0x1E),
},
// Lime
{
Color.FromArgb(0xFF, 0xF9, 0xFB, 0xE7),
Color.FromArgb(0xFF, 0xF0, 0xF4, 0xC3),
Color.FromArgb(0xFF, 0xE6, 0xEE, 0x9C),
Color.FromArgb(0xFF, 0xDC, 0xE7, 0x75),
Color.FromArgb(0xFF, 0xD4, 0xE1, 0x57),
Color.FromArgb(0xFF, 0xCD, 0xDC, 0x39),
Color.FromArgb(0xFF, 0xC0, 0xCA, 0x33),
Color.FromArgb(0xFF, 0xAF, 0xB4, 0x2B),
Color.FromArgb(0xFF, 0x9E, 0x9D, 0x24),
Color.FromArgb(0xFF, 0x82, 0x77, 0x17),
},
// Yellow
{
Color.FromArgb(0xFF, 0xFF, 0xFD, 0xE7),
Color.FromArgb(0xFF, 0xFF, 0xF9, 0xC4),
Color.FromArgb(0xFF, 0xFF, 0xF5, 0x9D),
Color.FromArgb(0xFF, 0xFF, 0xF1, 0x76),
Color.FromArgb(0xFF, 0xFF, 0xEE, 0x58),
Color.FromArgb(0xFF, 0xFF, 0xEB, 0x3B),
Color.FromArgb(0xFF, 0xFD, 0xD8, 0x35),
Color.FromArgb(0xFF, 0xFB, 0xC0, 0x2D),
Color.FromArgb(0xFF, 0xF9, 0xA8, 0x25),
Color.FromArgb(0xFF, 0xF5, 0x7F, 0x17),
},
// Amber
{
Color.FromArgb(0xFF, 0xFF, 0xF8, 0xE1),
Color.FromArgb(0xFF, 0xFF, 0xEC, 0xB3),
Color.FromArgb(0xFF, 0xFF, 0xE0, 0x82),
Color.FromArgb(0xFF, 0xFF, 0xD5, 0x4F),
Color.FromArgb(0xFF, 0xFF, 0xCA, 0x28),
Color.FromArgb(0xFF, 0xFF, 0xC1, 0x07),
Color.FromArgb(0xFF, 0xFF, 0xB3, 0x00),
Color.FromArgb(0xFF, 0xFF, 0xA0, 0x00),
Color.FromArgb(0xFF, 0xFF, 0x8F, 0x00),
Color.FromArgb(0xFF, 0xFF, 0x6F, 0x00),
},
// Orange
{
Color.FromArgb(0xFF, 0xFF, 0xF3, 0xE0),
Color.FromArgb(0xFF, 0xFF, 0xE0, 0xB2),
Color.FromArgb(0xFF, 0xFF, 0xCC, 0x80),
Color.FromArgb(0xFF, 0xFF, 0xB7, 0x4D),
Color.FromArgb(0xFF, 0xFF, 0xA7, 0x26),
Color.FromArgb(0xFF, 0xFF, 0x98, 0x00),
Color.FromArgb(0xFF, 0xFB, 0x8C, 0x00),
Color.FromArgb(0xFF, 0xF5, 0x7C, 0x00),
Color.FromArgb(0xFF, 0xEF, 0x6C, 0x00),
Color.FromArgb(0xFF, 0xE6, 0x51, 0x00),
},
// Deep Orange
{
Color.FromArgb(0xFF, 0xFB, 0xE9, 0xE7),
Color.FromArgb(0xFF, 0xFF, 0xCC, 0xBC),
Color.FromArgb(0xFF, 0xFF, 0xAB, 0x91),
Color.FromArgb(0xFF, 0xFF, 0x8A, 0x65),
Color.FromArgb(0xFF, 0xFF, 0x70, 0x43),
Color.FromArgb(0xFF, 0xFF, 0x57, 0x22),
Color.FromArgb(0xFF, 0xF4, 0x51, 0x1E),
Color.FromArgb(0xFF, 0xE6, 0x4A, 0x19),
Color.FromArgb(0xFF, 0xD8, 0x43, 0x15),
Color.FromArgb(0xFF, 0xBF, 0x36, 0x0C),
},
// Brown
{
Color.FromArgb(0xFF, 0xEF, 0xEB, 0xE9),
Color.FromArgb(0xFF, 0xD7, 0xCC, 0xC8),
Color.FromArgb(0xFF, 0xBC, 0xAA, 0xA4),
Color.FromArgb(0xFF, 0xA1, 0x88, 0x7F),
Color.FromArgb(0xFF, 0x8D, 0x6E, 0x63),
Color.FromArgb(0xFF, 0x79, 0x55, 0x48),
Color.FromArgb(0xFF, 0x6D, 0x4C, 0x41),
Color.FromArgb(0xFF, 0x5D, 0x40, 0x37),
Color.FromArgb(0xFF, 0x4E, 0x34, 0x2E),
Color.FromArgb(0xFF, 0x3E, 0x27, 0x23),
},
// Gray
{
Color.FromArgb(0xFF, 0xFA, 0xFA, 0xFA),
Color.FromArgb(0xFF, 0xF5, 0xF5, 0xF5),
Color.FromArgb(0xFF, 0xEE, 0xEE, 0xEE),
Color.FromArgb(0xFF, 0xE0, 0xE0, 0xE0),
Color.FromArgb(0xFF, 0xBD, 0xBD, 0xBD),
Color.FromArgb(0xFF, 0x9E, 0x9E, 0x9E),
Color.FromArgb(0xFF, 0x75, 0x75, 0x75),
Color.FromArgb(0xFF, 0x61, 0x61, 0x61),
Color.FromArgb(0xFF, 0x42, 0x42, 0x42),
Color.FromArgb(0xFF, 0x21, 0x21, 0x21),
},
// Blue Gray
{
Color.FromArgb(0xFF, 0xEC, 0xEF, 0xF1),
Color.FromArgb(0xFF, 0xCF, 0xD8, 0xDC),
Color.FromArgb(0xFF, 0xB0, 0xBE, 0xC5),
Color.FromArgb(0xFF, 0x90, 0xA4, 0xAE),
Color.FromArgb(0xFF, 0x78, 0x90, 0x9C),
Color.FromArgb(0xFF, 0x60, 0x7D, 0x8B),
Color.FromArgb(0xFF, 0x54, 0x6E, 0x7A),
Color.FromArgb(0xFF, 0x45, 0x5A, 0x64),
Color.FromArgb(0xFF, 0x37, 0x47, 0x4F),
Color.FromArgb(0xFF, 0x26, 0x32, 0x38),
},
};
_colorChartColorCount = _colorChart.GetLength(0);
_colorChartShadeCount = _colorChart.GetLength(1);
}
return;
}
/// <inheritdoc/>
public int ColorCount
{
get
{
if (_colorChart == null)
{
InitColorChart();
}
return _colorChartColorCount;
}
}
/// <inheritdoc/>
public int ShadeCount
{
get
{
if (_colorChart == null)
{
InitColorChart();
}
return _colorChartShadeCount;
}
}
/// <inheritdoc/>
public Color GetColor(int colorIndex, int shadeIndex)
{
if (_colorChart == null)
{
InitColorChart();
}
return _colorChart![
MathUtilities.Clamp(colorIndex, 0, _colorChartColorCount - 1),
MathUtilities.Clamp(shadeIndex, 0, _colorChartShadeCount - 1)];
}
}
}

2
src/Avalonia.Controls/AutoCompleteBox.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/Calendar.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/CalendarBlackoutDatesCollection.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/CalendarButton.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using Avalonia.Controls.Metadata; using Avalonia.Controls.Metadata;

2
src/Avalonia.Controls/Calendar/CalendarDateRange.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/CalendarDayButton.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/CalendarExtensions.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using Avalonia.Input; using Avalonia.Input;

2
src/Avalonia.Controls/Calendar/CalendarItem.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/DateTimeHelper.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Calendar/SelectedDatesCollection.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using Avalonia.Threading; using Avalonia.Threading;

2
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePicker.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerDateValidationErrorEventArgs.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/CalendarDatePicker/CalendarDatePickerFormat.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
namespace Avalonia.Controls namespace Avalonia.Controls

28
src/Avalonia.Controls/ComboBox.cs

@ -21,8 +21,11 @@ namespace Avalonia.Controls
/// A drop-down list control. /// A drop-down list control.
/// </summary> /// </summary>
[TemplatePart("PART_Popup", typeof(Popup))] [TemplatePart("PART_Popup", typeof(Popup))]
[PseudoClasses(pcDropdownOpen, pcPressed)]
public class ComboBox : SelectingItemsControl public class ComboBox : SelectingItemsControl
{ {
public const string pcDropdownOpen = ":dropdownopen";
public const string pcPressed = ":pressed";
/// <summary> /// <summary>
/// The default value for the <see cref="ItemsControl.ItemsPanel"/> property. /// The default value for the <see cref="ItemsControl.ItemsPanel"/> property.
/// </summary> /// </summary>
@ -95,6 +98,7 @@ namespace Avalonia.Controls
SelectedItemProperty.Changed.AddClassHandler<ComboBox>((x, e) => x.SelectedItemChanged(e)); SelectedItemProperty.Changed.AddClassHandler<ComboBox>((x, e) => x.SelectedItemChanged(e));
KeyDownEvent.AddClassHandler<ComboBox>((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel); KeyDownEvent.AddClassHandler<ComboBox>((x, e) => x.OnKeyDown(e), Interactivity.RoutingStrategies.Tunnel);
IsTextSearchEnabledProperty.OverrideDefaultValue<ComboBox>(true); IsTextSearchEnabledProperty.OverrideDefaultValue<ComboBox>(true);
IsDropDownOpenProperty.Changed.AddClassHandler<ComboBox>((x, e) => x.DropdownChanged(e));
} }
/// <summary> /// <summary>
@ -267,6 +271,20 @@ namespace Avalonia.Controls
} }
} }
/// <inheritdoc/>
protected override void OnPointerPressed(PointerPressedEventArgs e)
{
base.OnPointerPressed(e);
if(!e.Handled && e.Source is IVisual source)
{
if (_popup?.IsInsidePopup(source) == true)
{
return;
}
}
PseudoClasses.Set(pcPressed, true);
}
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnPointerReleased(PointerReleasedEventArgs e) protected override void OnPointerReleased(PointerReleasedEventArgs e)
{ {
@ -286,10 +304,12 @@ namespace Avalonia.Controls
e.Handled = true; e.Handled = true;
} }
} }
PseudoClasses.Set(pcPressed, false);
base.OnPointerReleased(e); base.OnPointerReleased(e);
} }
/// <inheritdoc/> /// <inheritdoc/>
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
@ -470,5 +490,11 @@ namespace Avalonia.Controls
MoveSelection(NavigationDirection.Previous, WrapSelection); MoveSelection(NavigationDirection.Previous, WrapSelection);
} }
} }
private void DropdownChanged(AvaloniaPropertyChangedEventArgs e)
{
bool newValue = e.GetNewValue<bool>();
PseudoClasses.Set(pcDropdownOpen, newValue);
}
} }
} }

2
src/Avalonia.Controls/Primitives/PopupPositioning/IPopupPositioner.cs

@ -35,7 +35,7 @@ DEALINGS IN THE SOFTWARE.
The above is the version of the MIT "Expat" License used by X.org: The above is the version of the MIT "Expat" License used by X.org:
http://cgit.freedesktop.org/xorg/xserver/tree/COPYING https://cgit.freedesktop.org/xorg/xserver/tree/COPYING
Adjustments for Avalonia needs: Adjustments for Avalonia needs:

91
src/Avalonia.Controls/TextBox.cs

@ -18,6 +18,7 @@ using Avalonia.Media.TextFormatting;
using Avalonia.Media.TextFormatting.Unicode; using Avalonia.Media.TextFormatting.Unicode;
using Avalonia.Automation.Peers; using Avalonia.Automation.Peers;
using System.Diagnostics; using System.Diagnostics;
using Avalonia.Threading;
namespace Avalonia.Controls namespace Avalonia.Controls
{ {
@ -159,18 +160,41 @@ namespace Avalonia.Controls
(o, v) => o.UndoLimit = v, (o, v) => o.UndoLimit = v,
unsetValue: -1); unsetValue: -1);
/// <summary>
/// Defines the <see cref="CopyingToClipboard"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> CopyingToClipboardEvent = public static readonly RoutedEvent<RoutedEventArgs> CopyingToClipboardEvent =
RoutedEvent.Register<TextBox, RoutedEventArgs>( RoutedEvent.Register<TextBox, RoutedEventArgs>(
nameof(CopyingToClipboard), RoutingStrategies.Bubble); nameof(CopyingToClipboard), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="CuttingToClipboard"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> CuttingToClipboardEvent = public static readonly RoutedEvent<RoutedEventArgs> CuttingToClipboardEvent =
RoutedEvent.Register<TextBox, RoutedEventArgs>( RoutedEvent.Register<TextBox, RoutedEventArgs>(
nameof(CuttingToClipboard), RoutingStrategies.Bubble); nameof(CuttingToClipboard), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="PastingFromClipboard"/> event.
/// </summary>
public static readonly RoutedEvent<RoutedEventArgs> PastingFromClipboardEvent = public static readonly RoutedEvent<RoutedEventArgs> PastingFromClipboardEvent =
RoutedEvent.Register<TextBox, RoutedEventArgs>( RoutedEvent.Register<TextBox, RoutedEventArgs>(
nameof(PastingFromClipboard), RoutingStrategies.Bubble); nameof(PastingFromClipboard), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="TextChanged"/> event.
/// </summary>
public static readonly RoutedEvent<TextChangedEventArgs> TextChangedEvent =
RoutedEvent.Register<TextBox, TextChangedEventArgs>(
nameof(TextChanged), RoutingStrategies.Bubble);
/// <summary>
/// Defines the <see cref="TextChanging"/> event.
/// </summary>
public static readonly RoutedEvent<TextChangingEventArgs> TextChangingEvent =
RoutedEvent.Register<TextBox, TextChangingEventArgs>(
nameof(TextChanging), RoutingStrategies.Bubble);
readonly struct UndoRedoState : IEquatable<UndoRedoState> readonly struct UndoRedoState : IEquatable<UndoRedoState>
{ {
public string? Text { get; } public string? Text { get; }
@ -359,8 +383,8 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public double LineHeight public double LineHeight
{ {
get { return GetValue(LineHeightProperty); } get => GetValue(LineHeightProperty);
set { SetValue(LineHeightProperty, value); } set => SetValue(LineHeightProperty, value);
} }
[Content] [Content]
@ -376,11 +400,19 @@ namespace Avalonia.Controls
CaretIndex = CoerceCaretIndex(caretIndex, value); CaretIndex = CoerceCaretIndex(caretIndex, value);
SelectionStart = CoerceCaretIndex(selectionStart, value); SelectionStart = CoerceCaretIndex(selectionStart, value);
SelectionEnd = CoerceCaretIndex(selectionEnd, value); SelectionEnd = CoerceCaretIndex(selectionEnd, value);
if (SetAndRaise(TextProperty, ref _text, value) && IsUndoEnabled && !_isUndoingRedoing)
var textChanged = SetAndRaise(TextProperty, ref _text, value);
if (textChanged && IsUndoEnabled && !_isUndoingRedoing)
{ {
_undoRedoHelper.Clear(); _undoRedoHelper.Clear();
SnapshotUndoRedo(); // so we always have an initial state SnapshotUndoRedo(); // so we always have an initial state
} }
if (textChanged)
{
RaiseTextChangeEvents();
}
} }
} }
@ -564,6 +596,27 @@ namespace Avalonia.Controls
remove => RemoveHandler(PastingFromClipboardEvent, value); remove => RemoveHandler(PastingFromClipboardEvent, value);
} }
/// <summary>
/// Occurs asynchronously after text changes and the new text is rendered.
/// </summary>
public event EventHandler<TextChangedEventArgs>? TextChanged
{
add => AddHandler(TextChangedEvent, value);
remove => RemoveHandler(TextChangedEvent, value);
}
/// <summary>
/// Occurs synchronously when text starts to change but before it is rendered.
/// </summary>
/// <remarks>
/// This event occurs just after the <see cref="Text"/> property value has been updated.
/// </remarks>
public event EventHandler<TextChangingEventArgs>? TextChanging
{
add => AddHandler(TextChangingEvent, value);
remove => RemoveHandler(TextChangingEvent, value);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
_presenter = e.NameScope.Get<TextPresenter>("PART_TextPresenter"); _presenter = e.NameScope.Get<TextPresenter>("PART_TextPresenter");
@ -1252,7 +1305,7 @@ namespace Avalonia.Controls
if (text != null && _wordSelectionStart >= 0) if (text != null && _wordSelectionStart >= 0)
{ {
var distance = caretIndex - _wordSelectionStart; var distance = caretIndex - _wordSelectionStart;
if (distance <= 0) if (distance <= 0)
{ {
@ -1539,11 +1592,39 @@ namespace Avalonia.Controls
return text.Substring(start, end - start); return text.Substring(start, end - start);
} }
/// <summary>
/// Raises both the <see cref="TextChanging"/> and <see cref="TextChanged"/> events.
/// </summary>
/// <remarks>
/// This must be called after the <see cref="Text"/> property is set.
/// </remarks>
private void RaiseTextChangeEvents()
{
// Note the following sequence of these events (following WinUI)
// 1. TextChanging occurs synchronously when text starts to change but before it is rendered.
// This occurs after the Text property is set.
// 2. TextChanged occurs asynchronously after text changes and the new text is rendered.
var textChangingEventArgs = new TextChangingEventArgs(TextChangingEvent);
RaiseEvent(textChangingEventArgs);
Dispatcher.UIThread.Post(() =>
{
var textChangedEventArgs = new TextChangedEventArgs(TextChangedEvent);
RaiseEvent(textChangedEventArgs);
}, DispatcherPriority.Normal);
}
private void SetTextInternal(string value, bool raiseTextChanged = true) private void SetTextInternal(string value, bool raiseTextChanged = true)
{ {
if (raiseTextChanged) if (raiseTextChanged)
{ {
SetAndRaise(TextProperty, ref _text, value); bool textChanged = SetAndRaise(TextProperty, ref _text, value);
if (textChanged)
{
RaiseTextChangeEvents();
}
} }
else else
{ {

2
src/Avalonia.Controls/TextBoxTextInputMethodClient.cs

@ -64,7 +64,7 @@ namespace Avalonia.Controls
return new TextInputMethodSurroundingText return new TextInputMethodSurroundingText
{ {
Text = lineText ?? "", Text = lineText ?? "",
AnchorOffset = anchorOffset, AnchorOffset = anchorOffset,
CursorOffset = cursorOffset CursorOffset = cursorOffset
}; };

20
src/Avalonia.Controls/TextChangedEventArgs.cs

@ -0,0 +1,20 @@
using Avalonia.Interactivity;
namespace Avalonia.Controls
{
/// <summary>
/// Provides data specific to a TextChanged event.
/// </summary>
public class TextChangedEventArgs : RoutedEventArgs
{
public TextChangedEventArgs(RoutedEvent? routedEvent)
: base (routedEvent)
{
}
public TextChangedEventArgs(RoutedEvent? routedEvent, IInteractive? source)
: base(routedEvent, source)
{
}
}
}

20
src/Avalonia.Controls/TextChangingEventArgs.cs

@ -0,0 +1,20 @@
using Avalonia.Interactivity;
namespace Avalonia.Controls
{
/// <summary>
/// Provides data specific to a TextChanging event.
/// </summary>
public class TextChangingEventArgs : RoutedEventArgs
{
public TextChangingEventArgs(RoutedEvent? routedEvent)
: base (routedEvent)
{
}
public TextChangingEventArgs(RoutedEvent? routedEvent, IInteractive? source)
: base(routedEvent, source)
{
}
}
}

2
src/Avalonia.Controls/Utils/ISelectionAdapter.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Controls/Utils/SelectingItemsControlSelectionAdapter.cs

@ -1,6 +1,6 @@
// (c) Copyright Microsoft Corporation. // (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL). // This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details. // Please see https://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved. // All other rights reserved.
using System; using System;

2
src/Avalonia.Native/IconLoader.cs

@ -6,7 +6,7 @@ namespace Avalonia.Native
// OSX doesn't have a concept of *window* icon. // OSX doesn't have a concept of *window* icon.
// Icons in the title bar are only shown if there is // Icons in the title bar are only shown if there is
// an opened file (on disk) associated with the current window // an opened file (on disk) associated with the current window
// see http://stackoverflow.com/a/7038671/2231814 // see https://stackoverflow.com/a/7038671/2231814
class IconLoader : IPlatformIconLoader class IconLoader : IPlatformIconLoader
{ {
class IconStub : IWindowIconImpl class IconStub : IWindowIconImpl

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Bold.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-ExtraLight.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Light.ttf

Binary file not shown.

BIN
src/Avalonia.Themes.Fluent/Assets/Inter-Medium.ttf

Binary file not shown.

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save