Browse Source

Merge branch 'master' into d2d-netstandard

pull/1040/head
Nikita Tsukanov 9 years ago
committed by GitHub
parent
commit
1337df1231
  1. 9
      .gitmodules
  2. 43
      Avalonia.sln
  3. 3
      appveyor.yml
  4. 52
      build.cake
  5. 5
      build/Base.props
  6. 4
      build/Markup.props
  7. 1
      build/SharpDX.props
  8. 2
      build/SkiaSharp.props
  9. 1
      build/UnitTests.NetCore.targets
  10. 12
      build/XUnit.props
  11. 88
      packages.cake
  12. 1
      samples/BindingTest/BindingTest.csproj
  13. 2
      samples/BindingTest/MainWindow.xaml
  14. 4
      samples/BindingTest/ViewModels/MainWindowViewModel.cs
  15. 1
      samples/ControlCatalog.Android/ControlCatalog.Android.csproj
  16. 1
      samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj
  17. 1
      samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
  18. 2
      samples/ControlCatalog/ControlCatalog.csproj
  19. 23
      samples/ControlCatalog/Pages/MenuPage.xaml
  20. 1
      samples/RenderTest/RenderTest.csproj
  21. 1
      samples/VirtualizationTest/VirtualizationTest.csproj
  22. 1
      samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj
  23. 3
      samples/interop/GtkInteropDemo/GtkInteropDemo.csproj
  24. 14
      samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml
  25. 15
      samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs
  26. 2
      samples/interop/WindowsInteropTest/Program.cs
  27. 9
      samples/interop/WindowsInteropTest/WindowsInteropTest.csproj
  28. 5
      scripts/ReplaceNugetCache.ps1
  29. 7
      scripts/ReplaceNugetCache.sh
  30. 4
      src/Android/Avalonia.Android/Avalonia.Android.csproj
  31. 1
      src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
  32. 2
      src/Avalonia.Animation/Avalonia.Animation.csproj
  33. 3
      src/Avalonia.Base/Avalonia.Base.csproj
  34. 15
      src/Avalonia.Base/Metadata/AmbientAttribute.cs
  35. 15
      src/Avalonia.Base/Metadata/TemplateContent.cs
  36. 2
      src/Avalonia.Controls/Avalonia.Controls.csproj
  37. 36
      src/Avalonia.Controls/Button.cs
  38. 2
      src/Avalonia.Controls/ContextMenu.cs
  39. 45
      src/Avalonia.Controls/Control.cs
  40. 10
      src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs
  41. 2
      src/Avalonia.Controls/Menu.cs
  42. 11
      src/Avalonia.Controls/MenuItem.cs
  43. 9
      src/Avalonia.Controls/Panel.cs
  44. 38
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  45. 9
      src/Avalonia.Controls/TextBox.cs
  46. 30
      src/Avalonia.Controls/ToolTip.cs
  47. 22
      src/Avalonia.Controls/TreeView.cs
  48. 9
      src/Avalonia.Controls/WindowBase.cs
  49. 2
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  50. 2
      src/Avalonia.DesignerSupport/DesignerAssist.cs
  51. 2
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  52. 24
      src/Avalonia.Diagnostics/DevTools.xaml.cs
  53. 3
      src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj
  54. 2
      src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj
  55. 2
      src/Avalonia.Input/Avalonia.Input.csproj
  56. 5
      src/Avalonia.Input/FocusManager.cs
  57. 15
      src/Avalonia.Input/ICustomKeyboardNavigation.cs
  58. 27
      src/Avalonia.Input/KeyboardNavigationHandler.cs
  59. 16
      src/Avalonia.Input/Navigation/DirectionalNavigation.cs
  60. 87
      src/Avalonia.Input/Navigation/TabNavigation.cs
  61. 2
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  62. 2
      src/Avalonia.Layout/Avalonia.Layout.csproj
  63. 10
      src/Avalonia.Layout/IEmbeddedLayoutRoot.cs
  64. 12
      src/Avalonia.Layout/LayoutManager.cs
  65. 9
      src/Avalonia.Layout/Layoutable.cs
  66. 2
      src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj
  67. 2
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  68. 2
      src/Avalonia.Styling/Avalonia.Styling.csproj
  69. 25
      src/Avalonia.Styling/Styling/Style.cs
  70. 90
      src/Avalonia.Styling/Styling/StyleResources.cs
  71. 2
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  72. 2
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  73. 3
      src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj
  74. 3
      src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj
  75. 2
      src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj
  76. 18
      src/Gtk/Avalonia.Gtk3/Interop/Native.cs
  77. 13
      src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs
  78. 326
      src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj
  79. 228
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs
  80. 215
      src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs
  81. 33
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaAttachableXamlMember.cs
  82. 58
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaContentPropertyProvider.cs
  83. 31
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaLifeCycleListener.cs
  84. 25
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaMemberValuePlugin.cs
  85. 181
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaNamespaceRegistry.cs
  86. 79
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaObjectAssembler.cs
  87. 41
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaParserFactory.cs
  88. 91
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaRuntimeTypeSource.cs
  89. 180
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeFeatureProvider.cs
  90. 28
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeRepository.cs
  91. 126
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaWiringContext.cs
  92. 31
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaXamlMember.cs
  93. 61
      src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaXamlType.cs
  94. 30
      src/Markup/Avalonia.Markup.Xaml/Context/NameScopeWrapper.cs
  95. 174
      src/Markup/Avalonia.Markup.Xaml/Context/PropertyAccessor.cs
  96. 21
      src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaListTypeConverter.cs
  97. 44
      src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs
  98. 31
      src/Markup/Avalonia.Markup.Xaml/Converters/BitmapTypeConverter.cs
  99. 21
      src/Markup/Avalonia.Markup.Xaml/Converters/BrushTypeConverter.cs
  100. 20
      src/Markup/Avalonia.Markup.Xaml/Converters/ClassesTypeConverter.cs

9
.gitmodules

@ -5,9 +5,6 @@
path = src/Avalonia.HtmlRenderer/external
url = https://github.com/AvaloniaUI/HTML-Renderer.git
branch = perspex-pcl
[submodule "src/Markup/Avalonia.Markup.Xaml/OmniXAML"]
path = src/Markup/Avalonia.Markup.Xaml/OmniXAML
url = https://github.com/AvaloniaUI/OmniXAML.git
[submodule "src/Markup/Avalonia.Markup.Xaml/glass"]
path = src/Markup/Avalonia.Markup.Xaml/glass
url = https://github.com/SuperJMN/glass
[submodule "src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github"]
path = src/Markup/Avalonia.Markup.Xaml/PortableXaml/portable.xaml.github
url = https://github.com/cwensley/Portable.Xaml.git

43
Avalonia.sln

@ -191,6 +191,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.LinuxFramebuffer",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Direct3DInteropSample", "samples\interop\Direct3DInteropSample\Direct3DInteropSample.csproj", "{638580B0-7910-40EF-B674-DCB34DA308CD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Win32.Interop", "src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj", "{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Skia\Avalonia.Skia\Avalonia.Skia.projitems*{2f59f3d0-748d-4652-b01e-e0d954756308}*SharedItemsImports = 13
@ -2589,6 +2591,46 @@ Global
{638580B0-7910-40EF-B674-DCB34DA308CD}.Release|Mono.Build.0 = Release|Any CPU
{638580B0-7910-40EF-B674-DCB34DA308CD}.Release|x86.ActiveCfg = Release|Any CPU
{638580B0-7910-40EF-B674-DCB34DA308CD}.Release|x86.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|Any CPU.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|iPhone.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|iPhone.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|iPhoneSimulator.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|Mono.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|Mono.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|x86.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Ad-Hoc|x86.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|Any CPU.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|Any CPU.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|iPhone.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|iPhone.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|iPhoneSimulator.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|iPhoneSimulator.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|Mono.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|Mono.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|x86.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.AppStore|x86.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|iPhone.Build.0 = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|Mono.ActiveCfg = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|Mono.Build.0 = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|x86.ActiveCfg = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Debug|x86.Build.0 = Debug|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|Any CPU.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|iPhone.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|iPhone.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|Mono.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|Mono.Build.0 = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|x86.ActiveCfg = Release|Any CPU
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2649,5 +2691,6 @@ Global
{4D6FAF79-58B4-482F-9122-0668C346364C} = {74487168-7D91-487E-BF93-055F2251461E}
{854568D5-13D1-4B4F-B50D-534DC7EFD3C9} = {86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}
{638580B0-7910-40EF-B674-DCB34DA308CD} = {A0CC0258-D18C-4AB3-854F-7101680FC3F9}
{CBC4FF2F-92D4-420B-BE21-9FE0B930B04E} = {B39A8919-9F95-48FE-AD7B-76E08B509888}
EndGlobalSection
EndGlobal

3
appveyor.yml

@ -14,7 +14,7 @@ environment:
secure: OtVfyN3ErqQrDTnWH2HDfJDlCiu/i4/X4wFmK3ZXXP7HmCiXYPSbTjMPwwdOxRaK
MYGET_API_URL: https://www.myget.org/F/avalonia-ci/api/v2/package
init:
- ps: (New-Object Net.WebClient).DownloadFile('https://raw.githubusercontent.com/appveyor/ci/master/scripts/xamarin-vs2017-151-fixed.targets', "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Microsoft.Common.Targets\ImportAfter\Xamarin.Common.targets")
- ps: if (Test-Path env:nuget_address) {[System.IO.File]::AppendAllText("C:\Windows\System32\drivers\etc\hosts", "`n$($env:nuget_address)`tapi.nuget.org")}
install:
- if not exist gtk-sharp-2.12.26.msi appveyor DownloadFile http://download.xamarin.com/GTKforWindows/Windows/gtk-sharp-2.12.26.msi
- if not exist dotnet-1.0.1.exe appveyor DownloadFile https://go.microsoft.com/fwlink/?linkid=843448 -FileName "dotnet-1.0.1.exe"
@ -26,7 +26,6 @@ before_build:
build_script:
- ps: .\build.ps1 -Target "AppVeyor" -Platform "$env:platform" -Configuration "$env:configuration"
after_build:
- tools\JetBrains.dotMemoryUnit\tools\dotMemoryUnit.exe -targetExecutable="%xunit20%\xunit.console.x86.exe" -returnTargetExitCode --"tests\Avalonia.LeakTests\bin\Release\Avalonia.LeakTests.dll"
- "SET PATH=C:\\Python34;C:\\Python34\\Scripts;%PATH%"
- pip install codecov
- codecov -f "./artifacts/coverage.xml"

52
build.cake

@ -4,8 +4,8 @@
#addin "nuget:?package=Polly&version=4.2.0"
#addin "nuget:?package=NuGet.Core&version=2.12.0"
#tool "nuget:?package=xunit.runner.console&version=2.2.0"
#tool "nuget:https://dotnet.myget.org/F/nuget-build/?package=NuGet.CommandLine&version=4.3.0-preview1-3980&prerelease"
#tool "nuget:?package=JetBrains.dotMemoryUnit&version=2.3.20160517.113140"
#tool "JetBrains.ReSharper.CommandLineTools"
///////////////////////////////////////////////////////////////////////////////
// TOOLS
@ -119,7 +119,6 @@ Task("Restore-NuGet-Packages")
}})
.Execute(()=> {
NuGetRestore(parameters.MSBuildSolution, new NuGetRestoreSettings {
ToolPath = "./tools/NuGet.CommandLine/tools/NuGet.exe",
ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
});
});
@ -194,6 +193,7 @@ Task("Run-Net-Core-Unit-Tests")
Task("Run-Unit-Tests")
.IsDependentOn("Run-Net-Core-Unit-Tests")
.IsDependentOn("Build")
.IsDependentOn("Run-Leak-Tests")
.WithCriteria(() => !parameters.SkipTests)
.Does(() =>
{
@ -206,13 +206,6 @@ Task("Run-Unit-Tests")
.Select(name => MakeAbsolute(File("./tests/" + name + "/bin/" + parameters.DirSuffix + "/" + name + ".dll")))
.ToList();
if (parameters.IsRunningOnWindows)
{
var leakTests = GetFiles("./tests/Avalonia.LeakTests/bin/" + parameters.DirSuffix + "/*.LeakTests.dll");
unitTests.AddRange(leakTests);
}
var toolPath = (parameters.IsPlatformAnyCPU || parameters.IsPlatformX86) ?
"./tools/xunit.runner.console/tools/xunit.console.x86.exe" :
"./tools/xunit.runner.console/tools/xunit.console.exe";
@ -365,6 +358,44 @@ Task("Publish-NuGet")
Information("Publish-NuGet Task failed, but continuing with next Task...");
});
Task("Run-Leak-Tests")
.WithCriteria(parameters.IsRunningOnWindows)
.IsDependentOn("Build")
.Does(() =>
{
DotNetCoreRestore("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj");
DotNetBuild("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj", settings => settings.SetConfiguration("Release"));
var report = "tests\\Avalonia.LeakTests\\bin\\Release\\report.xml";
if(System.IO.File.Exists(report))
System.IO.File.Delete(report);
var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName="tests\\Avalonia.LeakTests\\toolproject\\bin\\dotMemoryUnit.exe",
Arguments="-targetExecutable=\"tools\\xunit.runner.console\\tools\\xunit.console.x86.exe\" -returnTargetExitCode -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ",
UseShellExecute = false,
});
var st = System.Diagnostics.Stopwatch.StartNew();
while(!proc.HasExited && !System.IO.File.Exists(report))
{
if(st.Elapsed.TotalSeconds>60)
{
Error("Timed out, probably a bug in dotMemoryUnit");
proc.Kill();
throw new Exception("dotMemory issue");
}
proc.WaitForExit(100);
}
try{
proc.Kill();
}catch{}
var doc = System.Xml.Linq.XDocument.Load(report);
if(doc.Root.Descendants("assembly").Any(x=>x.Attribute("failed").Value.ToString() != "0"))
{
throw new Exception("Tests failed");
}
});
Task("Inspect")
.WithCriteria(parameters.IsRunningOnWindows)
.IsDependentOn("Restore-NuGet-Packages")
@ -372,7 +403,8 @@ Task("Inspect")
{
var badIssues = new []{"PossibleNullReferenceException"};
var whitelist = new []{"tests", "src\\android", "src\\ios",
"src\\windows\\avalonia.designer", "src\\avalonia.htmlrenderer\\external"};
"src\\windows\\avalonia.designer", "src\\avalonia.htmlrenderer\\external",
"src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"};
Information("Running code inspections");

5
build/Base.props

@ -0,0 +1,5 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="System.ValueTuple" Version="4.3.1" />
</ItemGroup>
</Project>

4
build/Markup.props

@ -5,5 +5,9 @@
<PackageReference Include="System.Linq" Version="4.3.0" />
<PackageReference Include="System.Runtime" Version="4.3.0" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.0" />
<PackageReference Include="System.ComponentModel.TypeConverter" Version="4.3.0" />
<PackageReference Include="System.ComponentModel.Primitives" Version="4.3.0" />
<PackageReference Include="System.Runtime.Serialization.Primitives" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
</ItemGroup>
</Project>

1
build/SharpDX.props

@ -4,5 +4,6 @@
<PackageReference Include="SharpDX.Direct2D1" Version="4.0.0" />
<PackageReference Include="SharpDX.Direct3D11" Version="4.0.0" />
<PackageReference Include="SharpDX.DXGI" Version="4.0.0" />
<PackageReference Include="SharpDX.Direct3D9" Version="4.0.0" Condition="'$(UseDirect3D9)' == 'true'" />
</ItemGroup>
</Project>

2
build/SkiaSharp.props

@ -1,6 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="SkiaSharp" Version="1.57.1" />
<PackageReference Condition="$(TargetFramework.Trim('.').ToLower().StartsWith('netframework'))" Include="Avalonia.Skia.Linux.Natives" Version="1.57.1.3" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.57.1.3" />
</ItemGroup>
</Project>

1
build/UnitTests.NetCore.targets

@ -25,5 +25,4 @@
<ItemGroup>
<PackageReference Include="System.Threading.Thread" Version="4.3.0" />
</ItemGroup>
<Import Condition="'$(TargetFramework)' == 'net461'" Project="$(MSBuildThisFileDirectory)..\src\Shared\nuget.workaround.targets" />
</Project>

12
build/XUnit.props

@ -12,4 +12,16 @@
<ItemGroup Condition="'$(TargetFramework)' == 'netcoreapp1.1'">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0" />
</ItemGroup>
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<Target Name="ForceGenerationOfBindingRedirects"
AfterTargets="ResolveAssemblyReferences"
BeforeTargets="GenerateBindingRedirects"
Condition="'$(AutoGenerateBindingRedirects)' == 'true'">
<PropertyGroup>
<!-- Needs to be set in a target because it has to be set after the initial evaluation in the common targets -->
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
</PropertyGroup>
</Target>
</Project>

88
packages.cake

@ -8,6 +8,42 @@ public class Packages
public string NugetPackagesDir {get; private set;}
public string SkiaSharpVersion {get; private set; }
public string SkiaSharpLinuxVersion {get; private set; }
public Dictionary<string, IList<Tuple<string,string>>> PackageVersions{get; private set;}
class DependencyBuilder : List<NuSpecDependency>
{
Packages _parent;
public DependencyBuilder(Packages parent)
{
_parent = parent;
}
string GetVersion(string name)
{
return _parent.PackageVersions[name].First().Item1;
}
public DependencyBuilder Dep(string name, params string[] fws)
{
if(fws.Length == 0)
Add(new NuSpecDependency() { Id = name, Version = GetVersion(name) });
foreach(var fw in fws)
Add(new NuSpecDependency() { Id = name, TargetFramework = fw, Version = GetVersion(name) });
return this;
}
public DependencyBuilder Deps(string[] fws, params string[] deps)
{
foreach(var fw in fws)
foreach(var name in deps)
Add(new NuSpecDependency() { Id = name, TargetFramework = fw, Version = GetVersion(name) });
return this;
}
}
//new NuSpecDependency() { Id = "System.Threading.ThreadPool", TargetFramework = "netcoreapp1.0", Version = "4.3.0" },
public Packages(ICakeContext context, Parameters parameters)
{
// NUGET NUSPECS
@ -26,7 +62,7 @@ public class Packages
// Key: Package Id
// Value is Tuple where Item1: Package Version, Item2: The *.csproj/*.props file path.
var packageVersions = new Dictionary<string, IList<Tuple<string,string>>>();
PackageVersions = packageVersions;
System.IO.Directory.EnumerateFiles(((DirectoryPath)context.Directory("./build")).FullPath,
"*.props", SearchOption.AllDirectories).ToList().ForEach(fileName =>
{
@ -75,22 +111,26 @@ public class Packages
var SplatVersion = packageVersions["Splat"].FirstOrDefault().Item1;
var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1;
var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1;
var SystemValueTupleVersion = packageVersions["System.ValueTuple"].FirstOrDefault().Item1;
SkiaSharpVersion = packageVersions["SkiaSharp"].FirstOrDefault().Item1;
SkiaSharpLinuxVersion = packageVersions["Avalonia.Skia.Linux.Natives"].FirstOrDefault().Item1;
var SharpDXVersion = packageVersions["SharpDX"].FirstOrDefault().Item1;
var SharpDXDirect2D1Version = packageVersions["SharpDX.Direct2D1"].FirstOrDefault().Item1;
var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1;
var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1;
var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
context.Information("Package: Serilog, version: {0}", SerilogVersion);
context.Information("Package: Splat, version: {0}", SplatVersion);
context.Information("Package: Sprache, version: {0}", SpracheVersion);
context.Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
context.Information("Package: System.ValueTuple, version: {0}", SystemValueTupleVersion);
context.Information("Package: SkiaSharp, version: {0}", SkiaSharpVersion);
context.Information("Package: Avalonia.Skia.Linux.Natives, version: {0}", SkiaSharpLinuxVersion);
context.Information("Package: SharpDX, version: {0}", SharpDXVersion);
context.Information("Package: SharpDX.Direct2D1, version: {0}", SharpDXDirect2D1Version);
context.Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version);
context.Information("Package: SharpDX.Direct3D9, version: {0}", SharpDXDirect3D9Version);
context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME")
@ -146,12 +186,12 @@ public class Packages
};
var coreLibrariesFiles = coreLibraries.Select((lib) => {
return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard1.1/" + lib[1] + lib[2]);
return (FilePath)context.File(lib[0] + lib[1] + "/bin/" + parameters.DirSuffix + "/netstandard1.3/" + lib[1] + lib[2]);
}).ToList();
var coreLibrariesNuSpecContent = coreLibrariesFiles.Select((file) => {
return new NuSpecContent {
Source = file.FullPath, Target = "lib/netstandard1.1"
Source = file.FullPath, Target = "lib/netstandard1.3"
};
});
@ -191,7 +231,7 @@ public class Packages
new NuGetPackSettings()
{
Id = "Avalonia",
Dependencies = new []
Dependencies = new DependencyBuilder(this)
{
new NuSpecDependency() { Id = "Serilog", Version = SerilogVersion },
new NuSpecDependency() { Id = "Splat", Version = SplatVersion },
@ -204,8 +244,12 @@ public class Packages
new NuSpecDependency() { Id = "Splat", TargetFramework = "netcoreapp1.0", Version = SplatVersion },
new NuSpecDependency() { Id = "Serilog", TargetFramework = "netcoreapp1.0", Version = SerilogVersion },
new NuSpecDependency() { Id = "Sprache", TargetFramework = "netcoreapp1.0", Version = SpracheVersion },
new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion }
},
new NuSpecDependency() { Id = "System.Reactive", TargetFramework = "netcoreapp1.0", Version = SystemReactiveVersion },
}
.Deps(new string[]{null, "netcoreapp1.0"},
"System.ValueTuple", "System.ComponentModel.TypeConverter", "System.ComponentModel.Primitives",
"System.Runtime.Serialization.Primitives", "System.Xml.XmlDocument")
.ToArray(),
Files = coreLibrariesNuSpecContent
.Concat(win32CoreLibrariesNuSpecContent).Concat(net45RuntimePlatform)
.Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
@ -225,9 +269,9 @@ public class Packages
},
Files = new []
{
new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard1.1" }
new NuSpecContent { Source = "Avalonia.HtmlRenderer.dll", Target = "lib/netstandard1.3" }
},
BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard1.1"),
BasePath = context.Directory("./src/Avalonia.HtmlRenderer/bin/" + parameters.DirSuffix + "/netstandard1.3"),
OutputDirectory = parameters.NugetRoot
}
};
@ -341,7 +385,7 @@ public class Packages
Files = new []
{
new NuSpecContent { Source = "Avalonia.Win32/bin/" + parameters.DirSuffix + "/Avalonia.Win32.dll", Target = "lib/net45" },
new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard1.1/Avalonia.Win32.dll", Target = "lib/netstandard1.1" }
new NuSpecContent { Source = "Avalonia.Win32.NetStandard/bin/" + parameters.DirSuffix + "/netstandard1.3/Avalonia.Win32.dll", Target = "lib/netstandard1.3" }
},
BasePath = context.Directory("./src/Windows"),
OutputDirectory = parameters.NugetRoot
@ -396,9 +440,9 @@ public class Packages
},
Files = new []
{
new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.1" }
new NuSpecContent { Source = "Avalonia.Gtk3.dll", Target = "lib/netstandard1.3" }
},
BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard1.1"),
BasePath = context.Directory("./src/Gtk/Avalonia.Gtk3/bin/" + parameters.DirSuffix + "/netstandard1.3"),
OutputDirectory = parameters.NugetRoot
},
///////////////////////////////////////////////////////////////////////////////
@ -454,9 +498,9 @@ public class Packages
new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", TargetFramework="net45", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="net45", Version = parameters.Version },
//.NET Core
new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp1.1", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", TargetFramework="netcoreapp1.1", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp1.1", Version = parameters.Version }
new NuSpecDependency() { Id = "Avalonia.Win32", TargetFramework="netcoreapp1.0", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Skia.Desktop", TargetFramework="netcoreapp1.0", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Gtk3", TargetFramework="netcoreapp1.0", Version = parameters.Version }
},
Files = new NuSpecContent[]
{
@ -465,6 +509,22 @@ public class Packages
BasePath = context.Directory("./"),
OutputDirectory = parameters.NugetRoot
},
new NuGetPackSettings()
{
Id = "Avalonia.Win32.Interoperability",
Dependencies = new []
{
new NuSpecDependency() { Id = "Avalonia.Win32", Version = parameters.Version },
new NuSpecDependency() { Id = "Avalonia.Direct2D1", Version = parameters.Version },
new NuSpecDependency() { Id = "SharpDX.Direct3D9", Version = SharpDXDirect3D9Version },
},
Files = new []
{
new NuSpecContent { Source = "Avalonia.Win32.Interop/bin/" + parameters.DirSuffix + "/Avalonia.Win32.Interop.dll", Target = "lib/net45" }
},
BasePath = context.Directory("./src/Windows"),
OutputDirectory = parameters.NugetRoot
},
///////////////////////////////////////////////////////////////////////////////
// Avalonia.LinuxFramebuffer
///////////////////////////////////////////////////////////////////////////////

1
samples/BindingTest/BindingTest.csproj

@ -162,5 +162,4 @@
<Import Project="..\..\build\Serilog.Sinks.Trace.props" />
<Import Project="..\..\build\Splat.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\src\Shared\nuget.workaround.targets" />
</Project>

2
samples/BindingTest/MainWindow.xaml

@ -44,6 +44,8 @@
<StackPanel Margin="18" Gap="4" Width="200" HorizontalAlignment="Left">
<TextBlock FontSize="16" Text="Scheduler"/>
<TextBox Watermark="Background Thread" Text="{Binding CurrentTime, Mode=OneWay}"/>
<TextBlock FontSize="16" Text="Stream Operator"/>
<TextBox Watermark="StreamOperator" Text="{Binding CurrentTimeObservable^, Mode=OneWay}"/>
</StackPanel>
</StackPanel>
</StackPanel>

4
samples/BindingTest/ViewModels/MainWindowViewModel.cs

@ -49,6 +49,9 @@ namespace BindingTest.ViewModels
Thread.Sleep(1000);
}
});
CurrentTimeObservable = Observable.Timer(TimeSpan.Zero, TimeSpan.FromSeconds(1))
.Select(x => DateTimeOffset.Now.ToString());
}
public ObservableCollection<TestItem> Items { get; }
@ -85,6 +88,7 @@ namespace BindingTest.ViewModels
private set { this.RaiseAndSetIfChanged(ref _currentTime, value); }
}
public IObservable<string> CurrentTimeObservable { get; }
public ReactiveCommand<object> StringValueCommand { get; }
public DataAnnotationsErrorViewModel DataAnnotationsValidation { get; } = new DataAnnotationsErrorViewModel();

1
samples/ControlCatalog.Android/ControlCatalog.Android.csproj

@ -158,5 +158,4 @@
</ItemGroup>
<Import Project="..\..\build\Rx.props" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="$(MSBuildThisFileDirectory)..\..\src\Shared\nuget.workaround.targets" />
</Project>

1
samples/ControlCatalog.Desktop/ControlCatalog.Desktop.csproj

@ -144,5 +144,4 @@
<Import Project="..\..\build\Serilog.props" />
<Import Project="..\..\build\SkiaSharp.props" />
<Import Project="..\..\build\Serilog.Sinks.Trace.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\src\Shared\nuget.workaround.targets" />
</Project>

1
samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj

@ -181,5 +181,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<Import Project="$(MSBuildThisFileDirectory)..\..\src\Shared\nuget.workaround.targets" />
</Project>

2
samples/ControlCatalog/ControlCatalog.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

23
samples/ControlCatalog/Pages/MenuPage.xaml

@ -31,5 +31,28 @@
</MenuItem>
</Menu>
</StackPanel>
<TextBlock Classes="h2" Text="A context menu (right click)">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Standard _Menu Item"/>
<Separator/>
<MenuItem Header="Menu with _Submenu">
<MenuItem Header="Submenu _1"/>
<MenuItem Header="Submenu _2"/>
</MenuItem>
<MenuItem Header="Menu Item with _Icon">
<MenuItem.Icon>
<Image Source="resm:ControlCatalog.Assets.github_icon.png"/>
</MenuItem.Icon>
</MenuItem>
<MenuItem Header="Menu Item with _Checkbox">
<MenuItem.Icon>
<CheckBox BorderThickness="0" IsHitTestVisible="False" IsChecked="True"/>
</MenuItem.Icon>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</StackPanel>
</UserControl>

1
samples/RenderTest/RenderTest.csproj

@ -183,5 +183,4 @@
<Import Project="..\..\build\Serilog.Sinks.Trace.props" />
<Import Project="..\..\build\Splat.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\src\Shared\nuget.workaround.targets" />
</Project>

1
samples/VirtualizationTest/VirtualizationTest.csproj

@ -158,5 +158,4 @@
<Import Project="..\..\build\Serilog.Sinks.Trace.props" />
<Import Project="..\..\build\Splat.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\src\Shared\nuget.workaround.targets" />
</Project>

1
samples/interop/Direct3DInteropSample/Direct3DInteropSample.csproj

@ -31,5 +31,4 @@
<Import Project="..\..\..\build\Serilog.Sinks.Trace.props" />
<Import Project="..\..\..\build\Splat.props" />
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\..\src\Shared\nuget.workaround.targets" />
</Project>

3
samples/interop/GtkInteropDemo/GtkInteropDemo.csproj

@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>GtkInteropDemo</RootNamespace>
<AssemblyName>GtkInteropDemo</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
@ -151,5 +151,4 @@
</ItemGroup>
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(MSBuildThisFileDirectory)..\..\..\src\Shared\nuget.workaround.targets" />
</Project>

14
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml

@ -1,10 +1,12 @@
<Window x:Class="WindowsInteropTest.EmbedToWpfDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:av="clr-namespace:Avalonia.Controls;assembly=Avalonia.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WindowsInteropTest"
xmlns:embedding="clr-namespace:Avalonia.Win32.Embedding;assembly=Avalonia.Win32"
xmlns:wpf="clr-namespace:Avalonia.Win32.Interop.Wpf;assembly=Avalonia.Win32.Interop"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="400" MinWidth="500" MinHeight="400">
<DockPanel>
@ -14,8 +16,18 @@
<Calendar/>
</StackPanel>
</GroupBox>
<GroupBox Header="Avalonia button" DockPanel.Dock="Bottom">
<wpf:WpfAvaloniaHost >
<av:Button Content="Avalonia button"/>
</wpf:WpfAvaloniaHost>
</GroupBox>
<GroupBox Header="AvBtn" DockPanel.Dock="Right">
<wpf:WpfAvaloniaHost x:Name="RightBtn">
<av:Button Content="Avalonia button 2"/>
</wpf:WpfAvaloniaHost>
</GroupBox>
<GroupBox Header="Avalonia">
<embedding:WpfAvaloniaControlHost x:Name="Host"/>
<wpf:WpfAvaloniaHost x:Name="Host"/>
</GroupBox>
</DockPanel>
</Window>

15
samples/interop/WindowsInteropTest/EmbedToWpfDemo.xaml.cs

@ -11,7 +11,9 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Avalonia;
using Avalonia.Controls;
using Avalonia.VisualTree;
using ControlCatalog;
using Window = System.Windows.Window;
@ -25,7 +27,18 @@ namespace WindowsInteropTest
public EmbedToWpfDemo()
{
InitializeComponent();
Host.Content = new MainView();
var view = new MainView();
view.AttachedToVisualTree += delegate
{
((TopLevel) view.GetVisualRoot()).AttachDevTools();
};
Host.Content = view;
var btn = (Avalonia.Controls.Button) RightBtn.Content;
btn.Click += delegate
{
btn.Content += "!";
};
}
}
}

2
samples/interop/WindowsInteropTest/Program.cs

@ -15,7 +15,7 @@ namespace WindowsInteropTest
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
AppBuilder.Configure<App>().UseWin32().UseSkia().SetupWithoutStarting();
AppBuilder.Configure<App>().UseWin32().UseDirect2D1().SetupWithoutStarting();
System.Windows.Forms.Application.Run(new SelectorForm());
}
}

9
samples/interop/WindowsInteropTest/WindowsInteropTest.csproj

@ -9,12 +9,12 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WindowsInteropTest</RootNamespace>
<AssemblyName>WindowsInteropTest</AssemblyName>
<TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
@ -164,6 +164,10 @@
<Project>{3e908f67-5543-4879-a1dc-08eace79b3cd}</Project>
<Name>Avalonia.Direct2D1</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32.Interop\Avalonia.Win32.Interop.csproj">
<Project>{cbc4ff2f-92d4-420b-be21-9fe0b930b04e}</Project>
<Name>Avalonia.Win32.Interop</Name>
</ProjectReference>
<ProjectReference Include="..\..\..\src\Windows\Avalonia.Win32\Avalonia.Win32.csproj">
<Project>{811a76cf-1cf6-440f-963b-bbe31bd72a82}</Project>
<Name>Avalonia.Win32</Name>
@ -182,5 +186,4 @@
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\build\SkiaSharp.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\..\src\Shared\nuget.workaround.targets" />
</Project>

5
scripts/ReplaceNugetCache.ps1

@ -0,0 +1,5 @@
copy ..\samples\ControlCatalog.NetCore\bin\Debug\netcoreapp1.1\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netcoreapp1.0\
copy ..\samples\ControlCatalog.NetCore.\bin\Debug\netcoreapp1.1\Avalonia**.dll ~\.nuget\packages\avalonia\$args\lib\netstandard1.1\
copy ..\samples\ControlCatalog.NetCore.\bin\Debug\netcoreapp1.1\Avalonia**.dll ~\.nuget\packages\avalonia.gtk3\$args\lib\netstandard1.1\
copy ..\samples\ControlCatalog.NetCore.\bin\Debug\netcoreapp1.1\Avalonia**.dll ~\.nuget\packages\avalonia.skia.desktop\$args\lib\netstandard1.3\
copy ..\samples\ControlCatalog.NetCore.\bin\Debug\netcoreapp1.1\Avalonia**.dll ~\.nuget\packages\avalonia.win32\$args\lib\netstandard1.1\

7
scripts/ReplaceNugetCache.sh

@ -0,0 +1,7 @@
#!/usr/bin/env bash
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp1.1/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netcoreapp1.0/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp1.1/Avalonia**.dll ~/.nuget/packages/avalonia/$1/lib/netstandard1.1/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp1.1/Avalonia**.dll ~/.nuget/packages/avalonia.gtk3/$1/lib/netstandard1.1/
cp ../samples/ControlCatalog.NetCore/bin/Debug/netcoreapp1.1/Avalonia**.dll ~/.nuget/packages/avalonia.skia.desktop/$1/lib/netstandard1.3/

4
src/Android/Avalonia.Android/Avalonia.Android.csproj

@ -133,8 +133,4 @@
<Import Project="..\..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\Shared\nuget.workaround.targets" />
<PropertyGroup Condition="'$(UseRoslynPathHack)' == ''">
<CscToolPath>$(MSBuildToolsPath)\Roslyn</CscToolPath>
</PropertyGroup>
</Project>

1
src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj

@ -157,5 +157,4 @@
<Import Project="..\..\..\build\Splat.props" />
<Import Project="..\..\..\build\Sprache.props" />
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\Shared\nuget.workaround.targets" />
</Project>

2
src/Avalonia.Animation/Avalonia.Animation.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

3
src/Avalonia.Base/Avalonia.Base.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
@ -30,6 +30,7 @@
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
</ItemGroup>
<Import Project="..\..\build\Base.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
</Project>

15
src/Avalonia.Base/Metadata/AmbientAttribute.cs

@ -0,0 +1,15 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Metadata
{
/// <summary>
/// Defines the ambient class/property
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property, Inherited = true)]
public class AmbientAttribute : Attribute
{
}
}

15
src/Avalonia.Base/Metadata/TemplateContent.cs

@ -0,0 +1,15 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Metadata
{
/// <summary>
/// Defines the property that contains the object's content in markup.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class TemplateContentAttribute : Attribute
{
}
}

2
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

36
src/Avalonia.Controls/Button.cs

@ -207,7 +207,11 @@ namespace Avalonia.Controls
/// <param name="e">The event args.</param>
protected virtual void OnClick(RoutedEventArgs e)
{
Command?.Execute(CommandParameter);
if (Command != null)
{
Command.Execute(CommandParameter);
e.Handled = true;
}
}
/// <inheritdoc/>
@ -215,13 +219,16 @@ namespace Avalonia.Controls
{
base.OnPointerPressed(e);
PseudoClasses.Add(":pressed");
e.Device.Capture(this);
e.Handled = true;
if (ClickMode == ClickMode.Press)
if (e.MouseButton == MouseButton.Left)
{
RaiseClickEvent();
PseudoClasses.Add(":pressed");
e.Device.Capture(this);
e.Handled = true;
if (ClickMode == ClickMode.Press)
{
RaiseClickEvent();
}
}
}
@ -230,13 +237,16 @@ namespace Avalonia.Controls
{
base.OnPointerReleased(e);
e.Device.Capture(null);
PseudoClasses.Remove(":pressed");
e.Handled = true;
if (ClickMode == ClickMode.Release && new Rect(Bounds.Size).Contains(e.GetPosition(this)))
if (e.MouseButton == MouseButton.Left)
{
RaiseClickEvent();
e.Device.Capture(null);
PseudoClasses.Remove(":pressed");
e.Handled = true;
if (ClickMode == ClickMode.Release && new Rect(Bounds.Size).Contains(e.GetPosition(this)))
{
RaiseClickEvent();
}
}
}

2
src/Avalonia.Controls/ContextMenu.cs

@ -19,7 +19,7 @@ namespace Avalonia.Controls
{
ContextMenuProperty.Changed.Subscribe(ContextMenuChanged);
MenuItem.ClickEvent.AddClassHandler<ContextMenu>(x => x.OnContextMenuClick);
MenuItem.ClickEvent.AddClassHandler<ContextMenu>(x => x.OnContextMenuClick, handledEventsToo: true);
}
/// <summary>

45
src/Avalonia.Controls/Control.cs

@ -355,18 +355,28 @@ namespace Avalonia.Controls
if (--_initCount == 0 && _isAttachedToLogicalTree)
{
if (!_styled)
{
RegisterWithNameScope();
ApplyStyling();
_styled = true;
}
InitializeStylesIfNeeded();
if (!IsInitialized)
{
IsInitialized = true;
Initialized?.Invoke(this, EventArgs.Empty);
}
InitializeIfNeeded();
}
}
private void InitializeStylesIfNeeded(bool force = false)
{
if (_initCount == 0 && (!_styled || force))
{
RegisterWithNameScope();
ApplyStyling();
_styled = true;
}
}
private void InitializeIfNeeded()
{
if (_initCount == 0 && !IsInitialized)
{
IsInitialized = true;
Initialized?.Invoke(this, EventArgs.Empty);
}
}
@ -580,11 +590,7 @@ namespace Avalonia.Controls
{
base.OnAttachedToVisualTreeCore(e);
if (!IsInitialized)
{
IsInitialized = true;
Initialized?.Invoke(this, EventArgs.Empty);
}
InitializeIfNeeded();
}
/// <inheritdoc/>
@ -752,12 +758,7 @@ namespace Avalonia.Controls
{
_isAttachedToLogicalTree = true;
if (_initCount == 0)
{
RegisterWithNameScope();
ApplyStyling();
_styled = true;
}
InitializeStylesIfNeeded(true);
OnAttachedToLogicalTree(e);
}

10
src/Avalonia.Controls/Embedding/EmbeddableControlRoot.cs

@ -22,6 +22,8 @@ namespace Avalonia.Controls.Embedding
[CanBeNull]
public new IEmbeddableWindowImpl PlatformImpl => (IEmbeddableWindowImpl) base.PlatformImpl;
protected bool EnforceClientSize { get; set; } = true;
public void Prepare()
{
EnsureInitialized();
@ -38,12 +40,12 @@ namespace Avalonia.Controls.Embedding
init.EndInit();
}
}
protected override Size MeasureOverride(Size availableSize)
{
var cs = PlatformImpl?.ClientSize ?? default(Size);
base.MeasureOverride(cs);
return cs;
if (EnforceClientSize)
availableSize = PlatformImpl?.ClientSize ?? default(Size);
return base.MeasureOverride(availableSize);
}
private readonly NameScope _nameScope = new NameScope();

2
src/Avalonia.Controls/Menu.cs

@ -47,7 +47,7 @@ namespace Avalonia.Controls
static Menu()
{
ItemsPanelProperty.OverrideDefaultValue(typeof(Menu), DefaultPanel);
MenuItem.ClickEvent.AddClassHandler<Menu>(x => x.OnMenuClick);
MenuItem.ClickEvent.AddClassHandler<Menu>(x => x.OnMenuClick, handledEventsToo: true);
MenuItem.SubmenuOpenedEvent.AddClassHandler<Menu>(x => x.OnSubmenuOpened);
}

11
src/Avalonia.Controls/MenuItem.cs

@ -102,6 +102,11 @@ namespace Avalonia.Controls
AccessKeyHandler.AccessKeyPressedEvent.AddClassHandler<MenuItem>(x => x.AccessKeyPressed);
}
public MenuItem()
{
}
/// <summary>
/// Occurs when a <see cref="MenuItem"/> without a submenu is clicked.
/// </summary>
@ -192,7 +197,11 @@ namespace Avalonia.Controls
/// <param name="e">The click event args.</param>
protected virtual void OnClick(RoutedEventArgs e)
{
Command?.Execute(CommandParameter);
if (Command != null)
{
Command.Execute(CommandParameter);
e.Handled = true;
}
}
/// <summary>

9
src/Avalonia.Controls/Panel.cs

@ -64,9 +64,12 @@ namespace Avalonia.Controls
{
Contract.Requires<ArgumentNullException>(value != null);
VisualChildren.Clear();
_children.Clear();
_children.AddRange(value);
if (_children != value)
{
VisualChildren.Clear();
_children.Clear();
_children.AddRange(value);
}
}
}

38
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -8,6 +8,7 @@ using Avalonia.Controls.Templates;
using Avalonia.Layout;
using Avalonia.LogicalTree;
using Avalonia.Media;
using Avalonia.VisualTree;
namespace Avalonia.Controls.Presenters
{
@ -88,6 +89,7 @@ namespace Avalonia.Controls.Presenters
static ContentPresenter()
{
ContentProperty.Changed.AddClassHandler<ContentPresenter>(x => x.ContentChanged);
ContentTemplateProperty.Changed.AddClassHandler<ContentPresenter>(x => x.ContentChanged);
TemplatedParentProperty.Changed.AddClassHandler<ContentPresenter>(x => x.TemplatedParentChanged);
}
@ -313,27 +315,22 @@ namespace Avalonia.Controls.Presenters
if (content != null && newChild == null)
{
// We have content and it isn't a control, so first try to recycle the existing
// child control to display the new data by querying if the template that created
// the child can recycle items and that it also matches the new data.
if (oldChild != null &&
_dataTemplate != null &&
_dataTemplate.SupportsRecycling &&
_dataTemplate.Match(content))
var dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default;
// We have content and it isn't a control, so if the new data template is the same
// as the old data template, try to recycle the existing child control to display
// the new data.
if (dataTemplate == _dataTemplate && dataTemplate.SupportsRecycling)
{
newChild = oldChild;
}
else
{
// We couldn't recycle an existing control so find a data template for the data
// and use it to create a control.
_dataTemplate = this.FindDataTemplate(content, ContentTemplate) ?? FuncDataTemplate.Default;
_dataTemplate = dataTemplate;
newChild = _dataTemplate.Build(content);
// Try to give the new control its own name scope.
var controlResult = newChild as Control;
if (controlResult != null)
// Give the new control its own name scope.
if (newChild is Control controlResult)
{
NameScope.SetNameScope(controlResult, new NameScope());
}
@ -424,6 +421,19 @@ namespace Avalonia.Controls.Presenters
private void ContentChanged(AvaloniaPropertyChangedEventArgs e)
{
_createdChild = false;
if (((ILogical)this).IsAttachedToLogicalTree)
{
UpdateChild();
}
else if (Child != null)
{
VisualChildren.Remove(Child);
LogicalChildren.Remove(Child);
Child = null;
_dataTemplate = null;
}
InvalidateMeasure();
}

9
src/Avalonia.Controls/TextBox.cs

@ -236,6 +236,11 @@ namespace Avalonia.Controls
{
_presenter = e.NameScope.Get<TextPresenter>("PART_TextPresenter");
_presenter.Cursor = new Cursor(StandardCursorType.Ibeam);
if(IsFocused)
{
_presenter.ShowCaret();
}
}
protected override void OnGotFocus(GotFocusEventArgs e)
@ -254,7 +259,7 @@ namespace Avalonia.Controls
}
else
{
_presenter.ShowCaret();
_presenter?.ShowCaret();
}
}
@ -263,7 +268,7 @@ namespace Avalonia.Controls
base.OnLostFocus(e);
SelectionStart = 0;
SelectionEnd = 0;
_presenter.HideCaret();
_presenter?.HideCaret();
}
protected override void OnTextInput(TextInputEventArgs e)

30
src/Avalonia.Controls/ToolTip.cs

@ -106,24 +106,28 @@ namespace Avalonia.Controls
if (control != null && control.IsVisible && control.GetVisualRoot() != null)
{
var cp = (control.GetVisualRoot() as IInputRoot)?.MouseDevice?.GetPosition(control);
var position = control.PointToScreen(cp ?? new Point(0, 0)) + new Vector(0, 22);
if (s_popup == null)
if (cp.HasValue && control.IsVisible && new Rect(control.Bounds.Size).Contains(cp.Value))
{
s_popup = new PopupRoot();
s_popup.Content = new ToolTip();
}
else
{
((ISetLogicalParent)s_popup).SetParent(null);
}
var position = control.PointToScreen(cp.Value) + new Vector(0, 22);
if (s_popup == null)
{
s_popup = new PopupRoot();
s_popup.Content = new ToolTip();
}
else
{
((ISetLogicalParent)s_popup).SetParent(null);
}
((ISetLogicalParent)s_popup).SetParent(control);
((ToolTip)s_popup.Content).Content = GetTip(control);
s_popup.Position = position;
s_popup.Show();
((ToolTip)s_popup.Content).Content = GetTip(control);
s_popup.Position = position;
s_popup.Show();
s_current = control;
s_current = control;
}
}
}

22
src/Avalonia.Controls/TreeView.cs

@ -16,7 +16,7 @@ namespace Avalonia.Controls
/// <summary>
/// Displays a hierachical tree of data.
/// </summary>
public class TreeView : ItemsControl
public class TreeView : ItemsControl, ICustomKeyboardNavigation
{
/// <summary>
/// Defines the <see cref="AutoScrollToSelectedItem"/> property.
@ -90,6 +90,26 @@ namespace Avalonia.Controls
}
}
(bool handled, IInputElement next) ICustomKeyboardNavigation.GetNext(IInputElement element, NavigationDirection direction)
{
if (direction == NavigationDirection.Next || direction == NavigationDirection.Previous)
{
if (!this.IsVisualAncestorOf(element))
{
IControl result = _selectedItem != null ?
ItemContainerGenerator.Index.ContainerFromItem(_selectedItem) :
ItemContainerGenerator.ContainerFromIndex(0);
return (true, result);
}
else
{
return (true, null);
}
}
return (false, null);
}
/// <inheritdoc/>
protected override IItemContainerGenerator CreateItemContainerGenerator()
{

9
src/Avalonia.Controls/WindowBase.cs

@ -29,6 +29,7 @@ namespace Avalonia.Controls
public static readonly DirectProperty<WindowBase, bool> IsActiveProperty =
AvaloniaProperty.RegisterDirect<WindowBase, bool>(nameof(IsActive), o => o.IsActive);
private bool _hasExecutedInitialLayoutPass;
private bool _isActive;
private bool _ignoreVisibilityChange;
@ -136,7 +137,13 @@ namespace Avalonia.Controls
{
EnsureInitialized();
IsVisible = true;
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
if (!_hasExecutedInitialLayoutPass)
{
LayoutManager.Instance.ExecuteInitialLayoutPass(this);
_hasExecutedInitialLayoutPass = true;
}
PlatformImpl?.Show();
}
finally

2
src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.DesignerSupport/DesignerAssist.cs

@ -5,8 +5,6 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using OmniXaml;
using OmniXaml.ObjectAssembler;
using Avalonia.Controls;
using Avalonia.Controls.Platform;
using Avalonia.Markup.Xaml;

2
src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

24
src/Avalonia.Diagnostics/DevTools.xaml.cs

@ -14,11 +14,11 @@ using Avalonia.VisualTree;
namespace Avalonia
{
public static class WindowExtensions
public static class DevToolsExtensions
{
public static void AttachDevTools(this Window window)
public static void AttachDevTools(this TopLevel control)
{
Avalonia.Diagnostics.DevTools.Attach(window);
Avalonia.Diagnostics.DevTools.Attach(control);
}
}
}
@ -27,7 +27,7 @@ namespace Avalonia.Diagnostics
{
public class DevTools : UserControl
{
private static Dictionary<Window, Window> s_open = new Dictionary<Window, Window>();
private static Dictionary<TopLevel, Window> s_open = new Dictionary<TopLevel, Window>();
private IDisposable _keySubscription;
public DevTools(IControl root)
@ -43,9 +43,9 @@ namespace Avalonia.Diagnostics
public IControl Root { get; }
public static IDisposable Attach(Window window)
public static IDisposable Attach(TopLevel control)
{
return window.AddHandler(
return control.AddHandler(
KeyDownEvent,
WindowPreviewKeyDown,
RoutingStrategies.Tunnel);
@ -55,16 +55,16 @@ namespace Avalonia.Diagnostics
{
if (e.Key == Key.F12)
{
var window = (Window)sender;
var control = (TopLevel)sender;
var devToolsWindow = default(Window);
if (s_open.TryGetValue(window, out devToolsWindow))
if (s_open.TryGetValue(control, out devToolsWindow))
{
devToolsWindow.Activate();
}
else
{
var devTools = new DevTools(window);
var devTools = new DevTools(control);
devToolsWindow = new Window
{
@ -78,7 +78,7 @@ namespace Avalonia.Diagnostics
};
devToolsWindow.Closed += devTools.DevToolsClosed;
s_open.Add((Window)sender, devToolsWindow);
s_open.Add(control, devToolsWindow);
devToolsWindow.Show();
}
}
@ -88,9 +88,7 @@ namespace Avalonia.Diagnostics
{
var devToolsWindow = (Window)sender;
var devTools = (DevTools)devToolsWindow.Content;
var window = (Window)devTools.Root;
s_open.Remove(window);
s_open.Remove((TopLevel)devTools.Root);
_keySubscription.Dispose();
devToolsWindow.Closed -= DevToolsClosed;
}

3
src/Avalonia.DotNetFrameworkRuntime/Avalonia.DotNetFrameworkRuntime.csproj

@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Avalonia.DotNetFrameworkRuntime</RootNamespace>
<AssemblyName>Avalonia.DotNetFrameworkRuntime</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
@ -69,5 +69,4 @@
<Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\Shared\nuget.workaround.targets" />
</Project>

2
src/Avalonia.HtmlRenderer/Avalonia.HtmlRenderer.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<EnableDefaultItems>False</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>

2
src/Avalonia.Input/Avalonia.Input.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

5
src/Avalonia.Input/FocusManager.cs

@ -176,9 +176,10 @@ namespace Avalonia.Input
/// <param name="e">The event args.</param>
private void OnPreviewPointerPressed(object sender, RoutedEventArgs e)
{
if (sender == e.Source)
var ev = (PointerPressedEventArgs)e;
if (sender == e.Source && ev.MouseButton == MouseButton.Left)
{
var ev = (PointerPressedEventArgs)e;
var element = (ev.Device?.Captured as IInputElement) ?? (e.Source as IInputElement);
if (element == null || !CanFocus(element))

15
src/Avalonia.Input/ICustomKeyboardNavigation.cs

@ -0,0 +1,15 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
namespace Avalonia.Input
{
/// <summary>
/// Designates a control as handling its own keyboard navigation.
/// </summary>
public interface ICustomKeyboardNavigation
{
(bool handled, IInputElement next) GetNext(IInputElement element, NavigationDirection direction);
}
}

27
src/Avalonia.Input/KeyboardNavigationHandler.cs

@ -2,7 +2,9 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using Avalonia.Input.Navigation;
using Avalonia.VisualTree;
namespace Avalonia.Input
{
@ -52,6 +54,31 @@ namespace Avalonia.Input
{
Contract.Requires<ArgumentNullException>(element != null);
var customHandler = element.GetSelfAndVisualAncestors()
.OfType<ICustomKeyboardNavigation>()
.FirstOrDefault();
if (customHandler != null)
{
var (handled, next) = customHandler.GetNext(element, direction);
if (handled)
{
if (next != null)
{
return next;
}
else if (direction == NavigationDirection.Next || direction == NavigationDirection.Previous)
{
return TabNavigation.GetNextInTabOrder((IInputElement)customHandler, direction, true);
}
else
{
return null;
}
}
}
if (direction == NavigationDirection.Next || direction == NavigationDirection.Previous)
{
return TabNavigation.GetNextInTabOrder(element, direction);

16
src/Avalonia.Input/Navigation/DirectionalNavigation.cs

@ -41,7 +41,7 @@ namespace Avalonia.Input.Navigation
{
case KeyboardNavigationMode.Continue:
return GetNextInContainer(element, container, direction) ??
GetFirstInNextContainer(element, direction);
GetFirstInNextContainer(element, element, direction);
case KeyboardNavigationMode.Cycle:
return GetNextInContainer(element, container, direction) ??
GetFocusableDescendant(container, direction);
@ -173,10 +173,12 @@ namespace Avalonia.Input.Navigation
/// <summary>
/// Gets the first item that should be focused in the next container.
/// </summary>
/// <param name="element">The element being navigated away from.</param>
/// <param name="container">The container.</param>
/// <param name="direction">The direction of the search.</param>
/// <returns>The first element, or null if there are no more elements.</returns>
private static IInputElement GetFirstInNextContainer(
IInputElement element,
IInputElement container,
NavigationDirection direction)
{
@ -200,6 +202,16 @@ namespace Avalonia.Input.Navigation
if (sibling != null)
{
if (sibling is ICustomKeyboardNavigation custom)
{
var (handled, customNext) = custom.GetNext(element, direction);
if (handled)
{
return customNext;
}
}
if (sibling.CanFocus())
{
next = sibling;
@ -214,7 +226,7 @@ namespace Avalonia.Input.Navigation
if (next == null)
{
next = GetFirstInNextContainer(parent, direction);
next = GetFirstInNextContainer(element, parent, direction);
}
}
else

87
src/Avalonia.Input/Navigation/TabNavigation.cs

@ -18,13 +18,17 @@ namespace Avalonia.Input.Navigation
/// </summary>
/// <param name="element">The element.</param>
/// <param name="direction">The tab direction. Must be Next or Previous.</param>
/// <param name="outsideElement">
/// If true will not descend into <paramref name="element"/> to find next control.
/// </param>
/// <returns>
/// The next element in the specified direction, or null if <paramref name="element"/>
/// was the last in the requested direction.
/// </returns>
public static IInputElement GetNextInTabOrder(
IInputElement element,
NavigationDirection direction)
NavigationDirection direction,
bool outsideElement = false)
{
Contract.Requires<ArgumentNullException>(element != null);
Contract.Requires<ArgumentException>(
@ -40,20 +44,20 @@ namespace Avalonia.Input.Navigation
switch (mode)
{
case KeyboardNavigationMode.Continue:
return GetNextInContainer(element, container, direction) ??
GetFirstInNextContainer(element, direction);
return GetNextInContainer(element, container, direction, outsideElement) ??
GetFirstInNextContainer(element, element, direction);
case KeyboardNavigationMode.Cycle:
return GetNextInContainer(element, container, direction) ??
return GetNextInContainer(element, container, direction, outsideElement) ??
GetFocusableDescendant(container, direction);
case KeyboardNavigationMode.Contained:
return GetNextInContainer(element, container, direction);
return GetNextInContainer(element, container, direction, outsideElement);
default:
return GetFirstInNextContainer(container, direction);
return GetFirstInNextContainer(element, container, direction);
}
}
else
{
return GetFocusableDescendants(element).FirstOrDefault();
return GetFocusableDescendants(element, direction).FirstOrDefault();
}
}
@ -66,16 +70,17 @@ namespace Avalonia.Input.Navigation
private static IInputElement GetFocusableDescendant(IInputElement container, NavigationDirection direction)
{
return direction == NavigationDirection.Next ?
GetFocusableDescendants(container).FirstOrDefault() :
GetFocusableDescendants(container).LastOrDefault();
GetFocusableDescendants(container, direction).FirstOrDefault() :
GetFocusableDescendants(container, direction).LastOrDefault();
}
/// <summary>
/// Gets the focusable descendants of the specified element.
/// </summary>
/// <param name="element">The element.</param>
/// <param name="direction">The tab direction. Must be Next or Previous.</param>
/// <returns>The element's focusable descendants.</returns>
private static IEnumerable<IInputElement> GetFocusableDescendants(IInputElement element)
private static IEnumerable<IInputElement> GetFocusableDescendants(IInputElement element, NavigationDirection direction)
{
var mode = KeyboardNavigation.GetTabNavigation((InputElement)element);
@ -103,16 +108,25 @@ namespace Avalonia.Input.Navigation
foreach (var child in children)
{
if (child.CanFocus())
var customNext = GetCustomNext(child, direction);
if (customNext.handled)
{
yield return child;
yield return customNext.next;
}
if (child.CanFocusDescendants())
else
{
foreach (var descendant in GetFocusableDescendants(child))
if (child.CanFocus())
{
yield return descendant;
yield return child;
}
if (child.CanFocusDescendants())
{
foreach (var descendant in GetFocusableDescendants(child, direction))
{
yield return descendant;
}
}
}
}
@ -124,15 +138,19 @@ namespace Avalonia.Input.Navigation
/// <param name="element">The starting element/</param>
/// <param name="container">The container.</param>
/// <param name="direction">The direction.</param>
/// <param name="outsideElement">
/// If true will not descend into <paramref name="element"/> to find next control.
/// </param>
/// <returns>The next element, or null if the element is the last.</returns>
private static IInputElement GetNextInContainer(
IInputElement element,
IInputElement container,
NavigationDirection direction)
NavigationDirection direction,
bool outsideElement)
{
if (direction == NavigationDirection.Next)
if (direction == NavigationDirection.Next && !outsideElement)
{
var descendant = GetFocusableDescendants(element).FirstOrDefault();
var descendant = GetFocusableDescendants(element, direction).FirstOrDefault();
if (descendant != null)
{
@ -167,7 +185,7 @@ namespace Avalonia.Input.Navigation
if (element != null && direction == NavigationDirection.Previous)
{
var descendant = GetFocusableDescendants(element).LastOrDefault();
var descendant = GetFocusableDescendants(element, direction).LastOrDefault();
if (descendant != null)
{
@ -184,10 +202,12 @@ namespace Avalonia.Input.Navigation
/// <summary>
/// Gets the first item that should be focused in the next container.
/// </summary>
/// <param name="element">The element being navigated away from.</param>
/// <param name="container">The container.</param>
/// <param name="direction">The direction of the search.</param>
/// <returns>The first element, or null if there are no more elements.</returns>
private static IInputElement GetFirstInNextContainer(
IInputElement element,
IInputElement container,
NavigationDirection direction)
{
@ -210,6 +230,13 @@ namespace Avalonia.Input.Navigation
if (sibling != null)
{
var customNext = GetCustomNext(sibling, direction);
if (customNext.handled)
{
return customNext.next;
}
if (sibling.CanFocus())
{
next = sibling;
@ -217,24 +244,34 @@ namespace Avalonia.Input.Navigation
else
{
next = direction == NavigationDirection.Next ?
GetFocusableDescendants(sibling).FirstOrDefault() :
GetFocusableDescendants(sibling).LastOrDefault();
GetFocusableDescendants(sibling, direction).FirstOrDefault() :
GetFocusableDescendants(sibling, direction).LastOrDefault();
}
}
if (next == null)
{
next = GetFirstInNextContainer(parent, direction);
next = GetFirstInNextContainer(element, parent, direction);
}
}
else
{
next = direction == NavigationDirection.Next ?
GetFocusableDescendants(container).FirstOrDefault() :
GetFocusableDescendants(container).LastOrDefault();
GetFocusableDescendants(container, direction).FirstOrDefault() :
GetFocusableDescendants(container, direction).LastOrDefault();
}
return next;
}
private static (bool handled, IInputElement next) GetCustomNext(IInputElement element, NavigationDirection direction)
{
if (element is ICustomKeyboardNavigation custom)
{
return custom.GetNext(element, direction);
}
return (false, null);
}
}
}

2
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.Layout/Avalonia.Layout.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

10
src/Avalonia.Layout/IEmbeddedLayoutRoot.cs

@ -0,0 +1,10 @@
namespace Avalonia.Layout
{
/// <summary>
/// A special layout root with enforced size for Arrange pass
/// </summary>
public interface IEmbeddedLayoutRoot : ILayoutRoot
{
Size AllocatedSize { get; }
}
}

12
src/Avalonia.Layout/LayoutManager.cs

@ -186,12 +186,14 @@ namespace Avalonia.Layout
if (!control.IsArrangeValid && control.IsAttachedToVisualTree)
{
if (control is ILayoutRoot root)
{
root.Arrange(new Rect(control.DesiredSize));
}
else
if (control is IEmbeddedLayoutRoot embeddedRoot)
control.Arrange(new Rect(embeddedRoot.AllocatedSize));
else if (control is ILayoutRoot root)
control.Arrange(new Rect(root.DesiredSize));
else if (control.PreviousArrange != null)
{
// Has been observed that PreviousArrange sometimes is null, probably a bug somewhere else.
// Condition observed: control.VisualParent is Scrollbar, control is Border.
control.Arrange(control.PreviousArrange.Value);
}
}

9
src/Avalonia.Layout/Layoutable.cs

@ -367,6 +367,14 @@ namespace Avalonia.Layout
}
}
/// <summary>
/// Called by InvalidateMeasure
/// </summary>
protected virtual void OnMeasureInvalidated()
{
}
/// <summary>
/// Invalidates the measurement of the control and queues a new layout pass.
/// </summary>
@ -384,6 +392,7 @@ namespace Avalonia.Layout
LayoutManager.Instance?.InvalidateMeasure(this);
InvalidateVisual();
}
OnMeasureInvalidated();
}
}

2
src/Avalonia.Logging.Serilog/Avalonia.Logging.Serilog.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

2
src/Avalonia.Styling/Avalonia.Styling.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

25
src/Avalonia.Styling/Styling/Style.cs

@ -13,10 +13,10 @@ namespace Avalonia.Styling
/// </summary>
public class Style : IStyle
{
private static Dictionary<IStyleable, List<IDisposable>> _applied =
private static Dictionary<IStyleable, List<IDisposable>> _applied =
new Dictionary<IStyleable, List<IDisposable>>();
private Dictionary<string, object> _resources;
private StyleResources _resources;
/// <summary>
/// Initializes a new instance of the <see cref="Style"/> class.
@ -37,13 +37,13 @@ namespace Avalonia.Styling
/// <summary>
/// Gets or sets a dictionary of style resources.
/// </summary>
public IDictionary<string, object> Resources
public StyleResources Resources
{
get
{
if (_resources == null)
{
_resources = new Dictionary<string, object>();
_resources = new StyleResources();
}
return _resources;
@ -51,25 +51,30 @@ namespace Avalonia.Styling
set
{
var resources = Resources;
foreach (var i in value)
if (!Equals(resources, value))
{
resources.Add(i);
foreach (var i in value)
{
resources[i.Key] = i.Value;
//resources.Add(i.Key, i.Value);
//(resources as IDictionary<string,object>).Add(i);
}
}
}
}
/// <summary>
/// Gets or sets style's selector.
/// Gets or sets the style's selector.
/// </summary>
public Selector Selector { get; set; }
/// <summary>
/// Gets or sets style's setters.
/// Gets or sets the style's setters.
/// </summary>
[Content]
public IEnumerable<ISetter> Setters { get; set; } = new List<ISetter>();
public IList<ISetter> Setters { get; set; } = new List<ISetter>();
/// <summary>
/// Attaches the style to a control if the style's selector matches.

90
src/Avalonia.Styling/Styling/StyleResources.cs

@ -0,0 +1,90 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace Avalonia.Styling
{
/// <summary>
/// Holds resources for a <see cref="Style"/>.
/// </summary>
public class StyleResources : IDictionary<string, object>, IDictionary
{
private Dictionary<string, object> _inner = new Dictionary<string, object>();
public object this[string key]
{
get { return _inner[key]; }
set { _inner[key] = value; }
}
public int Count => _inner.Count;
ICollection<string> IDictionary<string, object>.Keys => _inner.Keys;
ICollection<object> IDictionary<string, object>.Values => _inner.Values;
bool ICollection<KeyValuePair<string, object>>.IsReadOnly => false;
object IDictionary.this[object key]
{
get { return ((IDictionary)_inner)[key]; }
set { ((IDictionary)_inner)[key] = value; }
}
ICollection IDictionary.Keys => _inner.Keys;
ICollection IDictionary.Values => _inner.Values;
bool ICollection.IsSynchronized => false;
object ICollection.SyncRoot => ((IDictionary)_inner).SyncRoot;
bool IDictionary.IsFixedSize => false;
bool IDictionary.IsReadOnly => false;
public void Add(string key, object value) => _inner.Add(key, value);
public void Clear() => _inner.Clear();
public bool ContainsKey(string key) => _inner.ContainsKey(key);
public bool Remove(string key) => _inner.Remove(key);
public IEnumerator<KeyValuePair<string, object>> GetEnumerator() => _inner.GetEnumerator();
public bool TryGetValue(string key, out object value) => _inner.TryGetValue(key, out value);
bool ICollection<KeyValuePair<string, object>>.Contains(KeyValuePair<string, object> item)
{
return ((IDictionary<string, object>)_inner).Contains(item);
}
void ICollection<KeyValuePair<string, object>>.Add(KeyValuePair<string, object> item)
{
((IDictionary<string, object>)_inner).Add(item);
}
void ICollection<KeyValuePair<string, object>>.CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
{
((IDictionary<string, object>)_inner).CopyTo(array, arrayIndex);
}
bool ICollection<KeyValuePair<string, object>>.Remove(KeyValuePair<string, object> item)
{
return ((IDictionary<string, object>)_inner).Remove(item);
}
void ICollection.CopyTo(Array array, int index) => ((IDictionary)_inner).CopyTo(array, index);
IEnumerator IEnumerable.GetEnumerator() => _inner.GetEnumerator();
IDictionaryEnumerator IDictionary.GetEnumerator() => ((IDictionary)_inner).GetEnumerator();
void IDictionary.Add(object key, object value) => ((IDictionary)_inner).Add(key, value);
bool IDictionary.Contains(object key) => ((IDictionary)_inner).Contains(key);
void IDictionary.Remove(object key) => ((IDictionary)_inner).Remove(key);
}
}

2
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">

2
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<RootNamespace>Avalonia</RootNamespace>
</PropertyGroup>

3
src/Gtk/Avalonia.Cairo/Avalonia.Cairo.csproj

@ -9,7 +9,7 @@
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Avalonia.Cairo</RootNamespace>
<AssemblyName>Avalonia.Cairo</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
@ -103,5 +103,4 @@
<Import Project="..\..\Shared\RenderHelpers\RenderHelpers.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\Shared\nuget.workaround.targets" />
</Project>

3
src/Gtk/Avalonia.Gtk/Avalonia.Gtk.csproj

@ -7,7 +7,7 @@
<OutputType>Library</OutputType>
<RootNamespace>Avalonia.Gtk</RootNamespace>
<AssemblyName>Avalonia.Gtk</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
@ -98,5 +98,4 @@
</ProjectReference>
</ItemGroup>
<Import Project="..\..\..\build\Rx.props" />
<Import Project="$(MSBuildThisFileDirectory)..\..\Shared\nuget.workaround.targets" />
</Project>

2
src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>

18
src/Gtk/Avalonia.Gtk3/Interop/Native.cs

@ -500,6 +500,24 @@ namespace Avalonia.Gtk3.Interop
public gdouble delta_y;
}
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventCrossing
{
public GdkEventType type;
public IntPtr window;
public gint8 send_event;
public IntPtr subwindow;
public guint32 time;
public gdouble x;
public gdouble y;
public gdouble x_root;
public gdouble y_root;
public int mode;
public int detail;
public bool focus;
public GdkModifierType state;
};
[StructLayout(LayoutKind.Sequential)]
unsafe struct GdkEventWindowState
{

13
src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs

@ -45,6 +45,7 @@ namespace Avalonia.Gtk3
ConnectEvent("window-state-event", OnStateChanged);
ConnectEvent("key-press-event", OnKeyEvent);
ConnectEvent("key-release-event", OnKeyEvent);
ConnectEvent("leave-notify-event", OnLeaveNotifyEvent);
Connect<Native.D.signal_generic>("destroy", OnDestroy);
Native.GtkWidgetRealize(gtkWidget);
_lastSize = ClientSize;
@ -194,6 +195,18 @@ namespace Avalonia.Gtk3
return true;
}
private unsafe bool OnLeaveNotifyEvent(IntPtr w, IntPtr pev, IntPtr userData)
{
var evnt = (GdkEventCrossing*) pev;
var position = new Point(evnt->x, evnt->y);
Input(new RawMouseEventArgs(Gtk3Platform.Mouse,
evnt->time,
_inputRoot,
RawMouseEventType.Move,
position, GetModifierKeys(evnt->state)));
return true;
}
private unsafe bool OnCommit(IntPtr gtkwidget, IntPtr utf8string, IntPtr userdata)
{
Input(new RawTextInputEventArgs(Gtk3Platform.Keyboard, _lastKbdEvent, Utf8Buffer.StringFromPtr(utf8string)));

326
src/Markup/Avalonia.Markup.Xaml/Avalonia.Markup.Xaml.csproj

@ -1,273 +1,98 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.1</TargetFramework>
<TargetFramework>netstandard1.3</TargetFramework>
<EnableDefaultCompileItems>False</EnableDefaultCompileItems>
<EnableDefaultItems>false</EnableDefaultItems>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DefineConstants>TRACE;DEBUG;NETSTANDARD1_3;PCL;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<NoWarn>CS1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<DefineConstants>NETSTANDARD1_3;PCL;NETSTANDARD</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Avalonia.Markup.Xaml.XML</DocumentationFile>
<NoWarn>CS1591</NoWarn>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Context\NameScopeWrapper.cs" />
<Compile Include="Context\AvaloniaAttachableXamlMember.cs" />
<Compile Include="Context\AvaloniaLifeCycleListener.cs" />
<Compile Include="Context\AvaloniaMemberValuePlugin.cs" />
<Compile Include="Context\AvaloniaNamespaceRegistry.cs" />
<Compile Include="Context\AvaloniaObjectAssembler.cs" />
<Compile Include="Context\AvaloniaTypeFeatureProvider.cs" />
<Compile Include="Context\AvaloniaParserFactory.cs" />
<Compile Include="Context\AvaloniaRuntimeTypeSource.cs" />
<Compile Include="Context\AvaloniaTypeRepository.cs" />
<Compile Include="Context\AvaloniaXamlMember.cs" />
<Compile Include="Context\AvaloniaXamlType.cs" />
<Compile Include="Context\PropertyAccessor.cs" />
<Compile Include="Converters\BitmapTypeConverter.cs" />
<Compile Include="Converters\BrushTypeConverter.cs" />
<Compile Include="Converters\ClassesTypeConverter.cs" />
<Compile Include="Converters\ColorTypeConverter.cs" />
<Compile Include="Converters\ColumnDefinitionsTypeConverter.cs" />
<Compile Include="Converters\CursorTypeConverter.cs" />
<Compile Include="Converters\DateTimeTypeConverter.cs" />
<Compile Include="Converters\FontWeightConverter.cs" />
<Compile Include="Converters\GeometryTypeConverter.cs" />
<Compile Include="Converters\GridLengthTypeConverter.cs" />
<Compile Include="Converters\IconTypeConverter.cs" />
<Compile Include="Converters\KeyGestureConverter.cs" />
<Compile Include="Converters\MemberSelectorTypeConverter.cs" />
<Compile Include="Converters\AvaloniaListTypeConverter.cs" />
<Compile Include="Converters\AvaloniaPropertyTypeConverter.cs" />
<Compile Include="Converters\PointsListTypeConverter.cs" />
<Compile Include="Converters\SizeTypeConverter.cs" />
<Compile Include="Converters\PointTypeConverter.cs" />
<Compile Include="Converters\RelativePointTypeConverter.cs" />
<Compile Include="Converters\RelativeRectTypeConverter.cs" />
<Compile Include="Converters\RowDefinitionsTypeConverter.cs" />
<Compile Include="Converters\SelectorTypeConverter.cs" />
<Compile Include="Converters\ThicknessTypeConverter.cs" />
<Compile Include="Converters\TimeSpanTypeConverter.cs" />
<Compile Include="Converters\UriTypeConverter.cs" />
<Compile Include="Data\Binding.cs" />
<Compile Include="Data\DelayedBinding.cs" />
<Compile Include="Data\MultiBinding.cs" />
<Compile Include="Data\RelativeSource.cs" />
<Compile Include="Data\SourceBindingEndpoint.cs" />
<Compile Include="Data\StyleResourceBinding.cs" />
<Compile Include="Data\TargetBindingEndpoint.cs" />
<Compile Include="glass\Glass.Core\AutoKeyDictionary.cs" />
<Compile Include="glass\Glass.Core\DependencySorter.cs" />
<Compile Include="glass\Glass.Core\EnumExtensions.cs" />
<Compile Include="glass\Glass.Core\Extensions.cs" />
<Compile Include="glass\Glass.Core\Guard.cs" />
<Compile Include="glass\Glass.Core\IAdd.cs" />
<Compile Include="glass\Glass.Core\IDependency.cs" />
<Compile Include="glass\Glass.Core\ReflectionExtensions.cs" />
<Compile Include="glass\Glass.Core\StackingLinkedList.cs" />
<Compile Include="glass\Glass.Core\StackingLinkedListMixin.cs" />
<Compile Include="MarkupExtensions\Standard\StaticExtension.cs" />
<Compile Include="MarkupExtensions\Standard\TypeExtension.cs" />
<Compile Include="MarkupExtensions\StyleResourceExtension.cs" />
<Compile Include="MarkupExtensions\BindingExtension.cs" />
<Compile Include="MarkupExtensions\RelativeSourceExtension.cs" />
<Compile Include="MarkupExtensions\StaticExtension.cs" />
<Compile Include="MarkupExtensions\TemplateBindingExtension.cs" />
<Compile Include="MarkupExtensions\TypeExtension.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Attributes\ContentPropertyAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Attributes\DependsOnAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Attributes\XmlnsDefinitionAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\AddressPack.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\AssemblyNameConfig.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\ConfiguredAssembly.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\ConfiguredAssemblyWithNamespaces.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\ContentProperties.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\ContentPropertyDefinition.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\Converters.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\Route.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\TypeConverterRegistration.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\XamlInstructionBuilder.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Builder\XamlNamespace.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\DefaultLoader.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\DefaultObjectAssemblerFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\DefaultParserFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\DeferredLoaderMapping.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\DependencySortingVisitor.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IContentPropertyProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IDeferredLoader.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IInstanceLifeCycleListener.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ILoader.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IMarkupExtension.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\INameScope.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\InstanceLifeCycleHandler.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Instruction.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\InstructionNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\InstructionTreeBuilder.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\InstructionType.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IObjectAssembler.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IObjectAssemblerFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IParserFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IRuntimeTypeSource.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ITypeFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ITypeFeatureProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ITypeProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\IValueConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\LoadException.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\LoadMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\LookaheadBuffer.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\MarkupExtension.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\MarkupExtensionContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\MemberDependencyNodeSorter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\MemberReverserVisitor.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\NamespaceDeclaration.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\NamespacePrefix.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssemblerMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Command.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\EndMemberCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\EndObjectCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\GetObjectCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\ITopDownValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\NamespaceDeclarationCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\StartMemberCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\StartObjectCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Commands\ValueCommand.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\ConstructionArgument.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\CurrentLevelWrapper.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\InstanceProperties.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Level.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\NullLevel.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\NullLifecycleListener.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\ObjectAssembler.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\PreviousLevelWrapper.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\Settings.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\StateCommuter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\StoredInstance.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\TopDownValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\TypeOperations.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\ValueProcessingMode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ObjectAssembler\XamlSetValueEventArgs.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ParseException.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\Inject.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\IParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\AssignmentNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\IdentifierNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\MarkupExtensionNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\MarkupExtensionNodeToXamlNodesConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\MarkupExtensionParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\Option.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\OptionsCollection.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\PositionalOption.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\PropertyOption.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\StringNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\MarkupExtensions\TreeNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\Parser\IInstructionParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\Parser\InstructionParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\Parser\OrderAwareInstructionParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\AttributeAssignment.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\AttributeFeed.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\AttributeParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\DirectiveAssignment.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\IProtoParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\IXmlReader.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\NodeType.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\NsPrefix.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\ProtoInstructionParser.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\UnprocessedAttributeBase.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Parsers\ProtoParser\XmlCompatibilityReader.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\PhaseParserKit.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\PrefixRegistrationMode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ProtoInstruction.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ProtoInstructionBuilder.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\RuntimeTypeSource.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Sequence.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TemplateHostingObjectAssembler.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\BooleanConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\DoubleTypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\IntTypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\StringTypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\BuiltInConverters\TypeTypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ITypeConverter.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ITypeConverterProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\IValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\TypeConverterAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\TypeConverterProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeConversion\ValueContext.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeFactory.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeFactoryMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeFeatureProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\TypeNotFoundException.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\AttachableMember.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\ClrNamespace.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\CommonValueConversion.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\CoreTypes.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\DependencyRegistration.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\DependencyRegistrations.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\Directive.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\GenericMetadata.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\IMemberValuePlugin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\INamespaceRegistry.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\ITypeRepository.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\Member.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\MemberBase.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\MemberValuePlugin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\Metadata.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\MetadataProvider.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\MutableMember.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\NameAttribute.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\Namespace.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\NamespaceRegistry.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\NamespaceRegistryMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\PrefixRegistration.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\PropertyLocator.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\TypeConverterProviderMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\TypeRepository.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\TypeRepositoryMixin.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\XamlName.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\XamlQualifiedName.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\XamlType.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Typing\XamlTypeName.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\ValueConversionException.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Visualization\IVisitor.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Visualization\NodeType.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Visualization\NodeVisualizer.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Visualization\VisualizationNode.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\Visualization\VisualizationTag.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\XmlLoader.cs" />
<Compile Include="OmniXAML\Source\OmniXaml\XmlParser.cs" />
<Compile Include="Parsers\SelectorGrammar.cs" />
<Compile Include="Parsers\SelectorParser.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Styling\StyleInclude.cs" />
<Compile Include="Templates\ControlTemplate.cs" />
<Compile Include="Templates\DataTemplate.cs" />
<Compile Include="Templates\FocusAdornerTemplate.cs" />
<Compile Include="Templates\ItemsPanelTemplate.cs" />
<Compile Include="Templates\MemberSelector.cs" />
<Compile Include="Templates\Template.cs" />
<Compile Include="Templates\TemplateContent.cs" />
<Compile Include="Templates\TemplateLoader.cs" />
<Compile Include="Templates\TreeDataTemplate.cs" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="AvaloniaXamlLoaderPortableXaml.cs" />
<Compile Include="AvaloniaXamlLoader.cs" />
<Compile Include="Converters\SetterValueTypeConverter.cs" />
<Compile Include="MarkupExtensions\StyleIncludeExtension.cs" />
<Compile Include="PortableXaml\AvaloniaXamlContext.cs" />
<Compile Include="PortableXaml\XamlBinding.cs" />
<Compile Include="PortableXaml\AttributeExtensions.cs" />
<Compile Include="PortableXaml\AvaloniaMemberAttributeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaNameScope.cs" />
<Compile Include="PortableXaml\AvaloniaDefaultTypeConverters.cs" />
<Compile Include="PortableXaml\AvaloniaXamlObjectWriter.cs" />
<Compile Include="PortableXaml\AvaloniaRuntimeTypeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaXamlSchemaContext.cs" />
<Compile Include="Converters\BitmapTypeConverter.cs" />
<Compile Include="Converters\BrushTypeConverter.cs" />
<Compile Include="Converters\ClassesTypeConverter.cs" />
<Compile Include="Converters\ColorTypeConverter.cs" />
<Compile Include="Converters\ColumnDefinitionsTypeConverter.cs" />
<Compile Include="Converters\CursorTypeConverter.cs" />
<Compile Include="Converters\GeometryTypeConverter.cs" />
<Compile Include="Converters\GridLengthTypeConverter.cs" />
<Compile Include="Converters\IconTypeConverter.cs" />
<Compile Include="Converters\KeyGestureConverter.cs" />
<Compile Include="Converters\MemberSelectorTypeConverter.cs" />
<Compile Include="Converters\AvaloniaListTypeConverter.cs" />
<Compile Include="Converters\AvaloniaPropertyTypeConverter.cs" />
<Compile Include="Converters\PointsListTypeConverter.cs" />
<Compile Include="Converters\SizeTypeConverter.cs" />
<Compile Include="Converters\PointTypeConverter.cs" />
<Compile Include="Converters\RelativePointTypeConverter.cs" />
<Compile Include="Converters\RelativeRectTypeConverter.cs" />
<Compile Include="Converters\RowDefinitionsTypeConverter.cs" />
<Compile Include="Converters\SelectorTypeConverter.cs" />
<Compile Include="Converters\ThicknessTypeConverter.cs" />
<Compile Include="Converters\TimeSpanTypeConverter.cs" />
<Compile Include="Data\Binding.cs" />
<Compile Include="Data\DelayedBinding.cs" />
<Compile Include="Data\MultiBinding.cs" />
<Compile Include="Data\RelativeSource.cs" />
<Compile Include="Data\StyleResourceBinding.cs" />
<Compile Include="MarkupExtensions\StyleResourceExtension.cs" />
<Compile Include="MarkupExtensions\BindingExtension.cs" />
<Compile Include="MarkupExtensions\RelativeSourceExtension.cs" />
<Compile Include="MarkupExtensions\StaticExtension.cs" />
<Compile Include="MarkupExtensions\TemplateBindingExtension.cs" />
<Compile Include="MarkupExtensions\TypeExtension.cs" />
<Compile Include="Parsers\SelectorGrammar.cs" />
<Compile Include="Parsers\SelectorParser.cs" />
<Compile Include="PortableXaml\AvaloniaTypeAttributeProvider.cs" />
<Compile Include="PortableXaml\AvaloniaXamlType.cs" />
<Compile Include="PortableXaml\TypeDescriptorExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Styling\StyleInclude.cs" />
<Compile Include="Templates\ControlTemplate.cs" />
<Compile Include="Templates\DataTemplate.cs" />
<Compile Include="Templates\FocusAdornerTemplate.cs" />
<Compile Include="Templates\ItemsPanelTemplate.cs" />
<Compile Include="Templates\MemberSelector.cs" />
<Compile Include="Templates\Template.cs" />
<Compile Include="Templates\TemplateContent.cs" />
<Compile Include="Templates\TemplateLoader.cs" />
<Compile Include="Templates\TreeDataTemplate.cs" />
<Compile Include="PortableXaml\portable.xaml.github\src\Portable.Xaml\**\*.cs" Exclude="PortableXaml\portable.xaml.github\src\Portable.Xaml\Assembly\**\*.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Avalonia.Animation\Avalonia.Animation.csproj" />
<ProjectReference Include="..\..\Avalonia.Base\Avalonia.Base.csproj" />
@ -279,11 +104,6 @@
<ProjectReference Include="..\..\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\Avalonia.Markup\Avalonia.Markup.csproj" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<Content Include="glass\Glass.Core\Glass.Core.csproj" />
</ItemGroup>
<Import Project="..\..\..\build\Markup.props" />
<Import Project="..\..\..\build\Sprache.props" />
<Import Project="..\..\..\build\Rx.props" />

228
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs

@ -1,225 +1,11 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
using OmniXaml;
using Avalonia.Platform;
using Avalonia.Markup.Xaml.Context;
using Avalonia.Markup.Xaml.Styling;
using OmniXaml.ObjectAssembler;
using Avalonia.Controls;
using Avalonia.Markup.Xaml.Data;
namespace Avalonia.Markup.Xaml
namespace Avalonia.Markup.Xaml
{
/// <summary>
/// Loads XAML for a avalonia application.
/// </summary>
public class AvaloniaXamlLoader : XmlLoader
public class AvaloniaXamlLoader : AvaloniaXamlLoaderPortableXaml
{
private static AvaloniaParserFactory s_parserFactory;
private static IInstanceLifeCycleListener s_lifeCycleListener = new AvaloniaLifeCycleListener();
private static Stack<Uri> s_uriStack = new Stack<Uri>();
/// <summary>
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
/// </summary>
public AvaloniaXamlLoader()
: this(GetParserFactory())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
/// </summary>
/// <param name="xamlParserFactory">The parser factory to use.</param>
public AvaloniaXamlLoader(IParserFactory xamlParserFactory)
: base(xamlParserFactory)
{
}
/// <summary>
/// Gets the URI of the XAML file currently being loaded.
/// </summary>
/// <remarks>
/// TODO: Making this internal for now as I'm not sure that this is the correct
/// thing to do, but its needed by <see cref="StyleInclude"/> to get the URL of
/// the currently loading XAML file, as we can't use the OmniXAML parsing context
/// there. Maybe we need a way to inject OmniXAML context into the objects its
/// constructing?
/// </remarks>
internal static Uri UriContext => s_uriStack.Count > 0 ? s_uriStack.Peek() : null;
/// <summary>
/// Loads the XAML into a Avalonia component.
/// </summary>
/// <param name="obj">The object to load the XAML into.</param>
public static void Load(object obj)
{
Contract.Requires<ArgumentNullException>(obj != null);
var loader = new AvaloniaXamlLoader();
loader.Load(obj.GetType(), obj);
}
/// <summary>
/// Loads the XAML for a type.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(Type type, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(type != null);
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
// Ideally we'd be able to use .xaml everywhere
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>();
if (assetLocator == null)
{
throw new InvalidOperationException(
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
}
foreach (var uri in GetUrisFor(type))
{
if (assetLocator.Exists(uri))
{
using (var stream = assetLocator.Open(uri))
{
var initialize = rootInstance as ISupportInitialize;
initialize?.BeginInit();
return Load(stream, rootInstance, uri);
}
}
}
throw new FileNotFoundException("Unable to find view for " + type.FullName);
}
/// <summary>
/// Loads XAML from a URI.
/// </summary>
/// <param name="uri">The URI of the XAML file.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(uri != null);
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>();
if (assetLocator == null)
{
throw new InvalidOperationException(
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
}
using (var stream = assetLocator.Open(uri, baseUri))
{
return Load(stream, rootInstance, uri);
}
}
/// <summary>
/// Loads XAML from a string.
/// </summary>
/// <param name="xaml">The string containing the XAML.</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(string xaml, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(xaml != null);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml)))
{
return Load(stream, rootInstance);
}
}
/// <summary>
/// Loads XAML from a stream.
/// </summary>
/// <param name="stream">The stream containing the XAML.</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <param name="uri">The URI of the XAML</param>
/// <returns>The loaded object.</returns>
public object Load(Stream stream, object rootInstance = null, Uri uri = null)
{
try
{
if (uri != null)
{
s_uriStack.Push(uri);
}
var result = base.Load(stream, new Settings
{
RootInstance = rootInstance,
InstanceLifeCycleListener = s_lifeCycleListener,
ParsingContext = new Dictionary<string, object>
{
{ "Uri", uri }
}
});
var topLevel = result as TopLevel;
if (topLevel != null)
{
DelayedBinding.ApplyBindings(topLevel);
}
return result;
}
finally
{
if (uri != null)
{
s_uriStack.Pop();
}
}
}
private static AvaloniaParserFactory GetParserFactory()
{
if (s_parserFactory == null)
{
s_parserFactory = new AvaloniaParserFactory();
}
return s_parserFactory;
}
/// <summary>
/// Gets the URI for a type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The URI.</returns>
private static IEnumerable<Uri> GetUrisFor(Type type)
{
var asm = type.GetTypeInfo().Assembly.GetName().Name;
var typeName = type.FullName;
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm);
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm);
public static object Parse(string xaml)
=> new AvaloniaXamlLoader().Load(xaml);
}
public static T Parse<T>(string xaml)
=> (T)Parse(xaml);
}
}
}

215
src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoaderPortableXaml.cs

@ -0,0 +1,215 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Controls;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Markup.Xaml.PortableXaml;
using Avalonia.Platform;
using Portable.Xaml;
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Text;
namespace Avalonia.Markup.Xaml
{
/// <summary>
/// Loads XAML for a avalonia application.
/// </summary>
public class AvaloniaXamlLoaderPortableXaml
{
private readonly AvaloniaXamlSchemaContext _context = GetContext();
private static AvaloniaXamlSchemaContext GetContext()
{
var result = AvaloniaLocator.Current.GetService<AvaloniaXamlSchemaContext>();
if (result == null)
{
result = AvaloniaXamlSchemaContext.Create();
AvaloniaLocator.CurrentMutable
.Bind<AvaloniaXamlSchemaContext>()
.ToConstant(result);
}
return result;
}
/// <summary>
/// Initializes a new instance of the <see cref="AvaloniaXamlLoader"/> class.
/// </summary>
public AvaloniaXamlLoaderPortableXaml()
{
}
/// <summary>
/// Loads the XAML into a Avalonia component.
/// </summary>
/// <param name="obj">The object to load the XAML into.</param>
public static void Load(object obj)
{
Contract.Requires<ArgumentNullException>(obj != null);
var loader = new AvaloniaXamlLoader();
loader.Load(obj.GetType(), obj);
}
/// <summary>
/// Loads the XAML for a type.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(Type type, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(type != null);
// HACK: Currently Visual Studio is forcing us to change the extension of xaml files
// in certain situations, so we try to load .xaml and if that's not found we try .xaml.
// Ideally we'd be able to use .xaml everywhere
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>();
if (assetLocator == null)
{
throw new InvalidOperationException(
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
}
foreach (var uri in GetUrisFor(type))
{
if (assetLocator.Exists(uri))
{
using (var stream = assetLocator.Open(uri))
{
var initialize = rootInstance as ISupportInitialize;
initialize?.BeginInit();
try
{
return Load(stream, rootInstance, uri);
}
finally
{
initialize?.EndInit();
}
}
}
}
throw new FileNotFoundException("Unable to find view for " + type.FullName);
}
/// <summary>
/// Loads XAML from a URI.
/// </summary>
/// <param name="uri">The URI of the XAML file.</param>
/// <param name="baseUri">
/// A base URI to use if <paramref name="uri"/> is relative.
/// </param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(Uri uri, Uri baseUri = null, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(uri != null);
var assetLocator = AvaloniaLocator.Current.GetService<IAssetLoader>();
if (assetLocator == null)
{
throw new InvalidOperationException(
"Could not create IAssetLoader : maybe Application.RegisterServices() wasn't called?");
}
using (var stream = assetLocator.Open(uri, baseUri))
{
return Load(stream, rootInstance, uri);
}
}
/// <summary>
/// Loads XAML from a string.
/// </summary>
/// <param name="xaml">The string containing the XAML.</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <returns>The loaded object.</returns>
public object Load(string xaml, object rootInstance = null)
{
Contract.Requires<ArgumentNullException>(xaml != null);
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(xaml)))
{
return Load(stream, rootInstance);
}
}
/// <summary>
/// Loads XAML from a stream.
/// </summary>
/// <param name="stream">The stream containing the XAML.</param>
/// <param name="rootInstance">
/// The optional instance into which the XAML should be loaded.
/// </param>
/// <param name="uri">The URI of the XAML</param>
/// <returns>The loaded object.</returns>
public object Load(Stream stream, object rootInstance = null, Uri uri = null)
{
var readerSettings = new XamlXmlReaderSettings()
{
BaseUri = uri,
LocalAssembly = rootInstance?.GetType().GetTypeInfo().Assembly
};
var reader = new XamlXmlReader(stream, _context, readerSettings);
object result = LoadFromReader(
reader,
AvaloniaXamlContext.For(readerSettings, rootInstance));
var topLevel = result as TopLevel;
if (topLevel != null)
{
DelayedBinding.ApplyBindings(topLevel);
}
return result;
}
internal static object LoadFromReader(XamlReader reader, AvaloniaXamlContext context = null)
{
var writer = AvaloniaXamlObjectWriter.Create(
reader.SchemaContext,
context);
XamlServices.Transform(reader, writer);
return writer.Result;
}
internal static object LoadFromReader(XamlReader reader)
{
//return XamlServices.Load(reader);
return LoadFromReader(reader, null);
}
/// <summary>
/// Gets the URI for a type.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The URI.</returns>
private static IEnumerable<Uri> GetUrisFor(Type type)
{
var asm = type.GetTypeInfo().Assembly.GetName().Name;
var typeName = type.FullName;
yield return new Uri("resm:" + typeName + ".xaml?assembly=" + asm);
yield return new Uri("resm:" + typeName + ".paml?assembly=" + asm);
}
}
}

33
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaAttachableXamlMember.cs

@ -1,33 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Markup.Xaml.Data;
using OmniXaml;
using OmniXaml.Typing;
using System.Reflection;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaAttachableXamlMember : AttachableMember
{
public AvaloniaAttachableXamlMember(string name,
XamlType owner,
MethodInfo getter,
MethodInfo setter,
ITypeRepository xamlTypeRepository,
ITypeFeatureProvider featureProvider)
: base(name, getter, setter, xamlTypeRepository, featureProvider)
{
}
public override string ToString()
{
return "Avalonia Attachable XAML Member " + base.ToString();
}
protected override IMemberValuePlugin LookupXamlMemberValueConnector()
{
return new AvaloniaMemberValuePlugin(this);
}
}
}

58
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaContentPropertyProvider.cs

@ -1,58 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Glass;
using OmniXaml;
using OmniXaml.Builder;
using Avalonia.Metadata;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaContentPropertyProvider : IContentPropertyProvider
{
private readonly Dictionary<Type, string> _values = new Dictionary<Type, string>();
public string GetContentPropertyName(Type type)
{
string result;
if (!_values.TryGetValue(type, out result))
{
result = LookupContentProperty(type);
_values[type] = result;
}
return result;
}
private string LookupContentProperty(Type type)
{
var result = (from member in type.GetRuntimeProperties()
let att = member.GetCustomAttribute<ContentAttribute>()
where att != null
select member).FirstOrDefault();
return result?.Name;
}
void IAdd<ContentPropertyDefinition>.Add(ContentPropertyDefinition item)
{
throw new NotImplementedException();
}
IEnumerator IEnumerable.GetEnumerator()
{
throw new NotImplementedException();
}
IEnumerator<ContentPropertyDefinition> IEnumerable<ContentPropertyDefinition>.GetEnumerator()
{
throw new NotImplementedException();
}
}
}

31
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaLifeCycleListener.cs

@ -1,31 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using OmniXaml;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaLifeCycleListener : IInstanceLifeCycleListener
{
public void OnAfterProperties(object instance)
{
}
public void OnAssociatedToParent(object instance)
{
}
public void OnBegin(object instance)
{
var isi = instance as ISupportInitialize;
isi?.BeginInit();
}
public void OnEnd(object instance)
{
var isi = instance as ISupportInitialize;
isi?.EndInit();
}
}
}

25
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaMemberValuePlugin.cs

@ -1,25 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaMemberValuePlugin : MemberValuePlugin
{
private readonly MutableMember _xamlMember;
public AvaloniaMemberValuePlugin(MutableMember xamlMember)
: base(xamlMember)
{
_xamlMember = xamlMember;
}
public override void SetValue(object instance, object value, IValueContext valueContext)
{
PropertyAccessor.SetValue(instance, _xamlMember, value, valueContext);
}
}
}

181
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaNamespaceRegistry.cs

@ -1,181 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using OmniXaml.Builder;
using OmniXaml.Typing;
using Avalonia.Controls;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Media;
using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.Styling;
using Glass.Core;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaNamespaceRegistry : INamespaceRegistry
{
private const string ClrNamespace = "clr-namespace:";
private const string AvaloniaNs = "https://github.com/avaloniaui";
private static readonly IEnumerable<Assembly> ForcedAssemblies = new[]
{
typeof(AvaloniaObject).GetTypeInfo().Assembly,
typeof(Control).GetTypeInfo().Assembly,
typeof(Style).GetTypeInfo().Assembly,
typeof(DataTemplate).GetTypeInfo().Assembly,
typeof(SolidColorBrush).GetTypeInfo().Assembly,
typeof(IValueConverter).GetTypeInfo().Assembly,
};
private List<ClrNamespace> _clrNamespaces = new List<ClrNamespace>();
private List<XamlNamespace> _namespaces = new List<XamlNamespace>();
private Dictionary<string, string> _prefixes = new Dictionary<string, string>();
private List<Assembly> _scanned = new List<Assembly>();
public AvaloniaNamespaceRegistry()
{
ScanAssemblies(ForcedAssemblies);
ScanNewAssemblies();
RegisterPrefix(new PrefixRegistration(string.Empty, AvaloniaNs));
}
public IEnumerable<PrefixRegistration> RegisteredPrefixes =>
_prefixes.Select(x => new PrefixRegistration(x.Key, x.Value));
public void AddNamespace(XamlNamespace xamlNamespace)
{
_namespaces.Add(xamlNamespace);
}
public Namespace GetNamespace(string name)
{
Namespace result;
if (!IsClrNamespace(name))
{
ScanNewAssemblies();
result = _namespaces.FirstOrDefault(x => x.Name == name);
if (result == null)
{
result = _namespaces.FirstOrDefault(x => x.Name == name);
}
}
else
{
var nsAndAssembly = ParseClrNameSpace(name);
result = _clrNamespaces.FirstOrDefault(x =>
x.Name == nsAndAssembly.Item1 &&
x.Assembly.GetName().Name == nsAndAssembly.Item2);
if (result == null)
{
var clr = CreateClrNamespace(name);
_clrNamespaces.Add(clr);
result = clr;
}
}
return result;
}
public Namespace GetNamespaceByPrefix(string prefix)
{
string uri;
if (_prefixes.TryGetValue(prefix, out uri))
{
return GetNamespace(uri);
}
return null;
}
public void RegisterPrefix(PrefixRegistration prefixRegistration)
{
_prefixes[prefixRegistration.Prefix] = prefixRegistration.Ns;
}
private static bool IsClrNamespace(string ns)
{
return ns.StartsWith(ClrNamespace);
}
private static ClrNamespace CreateClrNamespace(string formattedClrString)
{
var nsAndAssembly = ParseClrNameSpace(formattedClrString);
var assembly = GetAssembly(nsAndAssembly.Item2);
return new ClrNamespace(assembly, nsAndAssembly.Item1);
}
private static Tuple<string, string> ParseClrNameSpace(string clrNamespace)
{
var startOfNamespace = clrNamespace.IndexOf(":", StringComparison.Ordinal) + 1;
var endOfNamespace = clrNamespace.IndexOf(";", startOfNamespace, StringComparison.Ordinal);
if (endOfNamespace < 0)
{
endOfNamespace = clrNamespace.Length - startOfNamespace;
}
var ns = clrNamespace.Substring(startOfNamespace, endOfNamespace - startOfNamespace);
var remainingPartStart = startOfNamespace + ns.Length + 1;
var remainingPartLenght = clrNamespace.Length - remainingPartStart;
var assemblyPart = clrNamespace.Substring(remainingPartStart, remainingPartLenght);
return Tuple.Create(ns, assemblyPart.Dicotomize('=').Item2);
}
private static Assembly GetAssembly(string assemblyName)
{
return Assembly.Load(new AssemblyName(assemblyName));
}
private void ScanAssemblies(IEnumerable<Assembly> assemblies)
{
foreach (var assembly in assemblies)
{
var namespaces = assembly.GetCustomAttributes<XmlnsDefinitionAttribute>()
.Select(x => new { x.XmlNamespace, x.ClrNamespace })
.GroupBy(x => x.XmlNamespace);
foreach (var nsa in namespaces)
{
var xamlNamespace = _namespaces.FirstOrDefault(x => x.Name == nsa.Key);
if (xamlNamespace == null)
{
xamlNamespace = new XamlNamespace(nsa.Key);
_namespaces.Add(xamlNamespace);
}
var clrNamespaces = nsa.Select(x => x.ClrNamespace);
xamlNamespace.Addresses.Add(new ConfiguredAssemblyWithNamespaces(assembly, clrNamespaces));
}
_scanned.Add(assembly);
}
}
private void ScanNewAssemblies()
{
IEnumerable<Assembly> assemblies = AvaloniaLocator.Current
.GetService<IRuntimePlatform>()
?.GetLoadedAssemblies();
if (assemblies != null)
{
assemblies = assemblies.Except(_scanned);
ScanAssemblies(assemblies);
}
}
}
}

79
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaObjectAssembler.cs

@ -1,79 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using OmniXaml;
using OmniXaml.ObjectAssembler;
using OmniXaml.ObjectAssembler.Commands;
using OmniXaml.TypeConversion;
using Avalonia.Markup.Xaml.Templates;
using System.Collections.Generic;
using System.Collections.ObjectModel;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaObjectAssembler : IObjectAssembler
{
private readonly TemplateHostingObjectAssembler objectAssembler;
private readonly ObjectAssembler assembler;
public AvaloniaObjectAssembler(
IRuntimeTypeSource typeSource,
ITopDownValueContext topDownValueContext,
Settings settings = null)
{
var mapping = new DeferredLoaderMapping();
mapping.Map<Template>(x => x.Content, new TemplateLoader());
mapping.Map<ControlTemplate>(x => x.Content, new TemplateLoader());
mapping.Map<DataTemplate>(x => x.Content, new TemplateLoader());
mapping.Map<FocusAdornerTemplate>(x => x.Content, new TemplateLoader());
mapping.Map<TreeDataTemplate>(x => x.Content, new TemplateLoader());
mapping.Map<ItemsPanelTemplate>(x => x.Content, new TemplateLoader());
var parsingDictionary = GetDictionary(settings);
var valueContext = new ValueContext(typeSource, topDownValueContext, parsingDictionary);
assembler = new ObjectAssembler(typeSource, valueContext, settings);
objectAssembler = new TemplateHostingObjectAssembler(assembler, mapping);
}
public object Result => objectAssembler.Result;
public EventHandler<XamlSetValueEventArgs> XamlSetValueHandler { get; set; }
public IRuntimeTypeSource TypeSource => assembler.TypeSource;
public ITopDownValueContext TopDownValueContext => assembler.TopDownValueContext;
public IInstanceLifeCycleListener LifecycleListener
{
get { throw new NotImplementedException(); }
}
public void Process(Instruction node)
{
objectAssembler.Process(node);
}
public void OverrideInstance(object instance)
{
objectAssembler.OverrideInstance(instance);
}
private static IReadOnlyDictionary<string, object> GetDictionary(Settings settings)
{
IReadOnlyDictionary<string, object> dict;
if (settings != null)
{
dict = settings.ParsingContext;
}
else
{
dict = new ReadOnlyDictionary<string, object>(new Dictionary<string, object>());
}
return dict;
}
}
}

41
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaParserFactory.cs

@ -1,41 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using OmniXaml;
using OmniXaml.ObjectAssembler;
using OmniXaml.Parsers.Parser;
using OmniXaml.Parsers.ProtoParser;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaParserFactory : IParserFactory
{
private readonly IRuntimeTypeSource runtimeTypeSource;
public AvaloniaParserFactory()
: this(new TypeFactory())
{
}
public AvaloniaParserFactory(ITypeFactory typeFactory)
{
runtimeTypeSource = new AvaloniaRuntimeTypeSource(typeFactory);
}
public IParser Create(Settings settings)
{
var xamlInstructionParser = new OrderAwareInstructionParser(new InstructionParser(runtimeTypeSource));
IObjectAssembler objectAssembler = new AvaloniaObjectAssembler(
runtimeTypeSource,
new TopDownValueContext(),
settings);
var phaseParserKit = new PhaseParserKit(
new ProtoInstructionParser(runtimeTypeSource),
xamlInstructionParser,
objectAssembler);
return new XmlParser(phaseParserKit);
}
}
}

91
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaRuntimeTypeSource.cs

@ -1,91 +0,0 @@
namespace Avalonia.Markup.Xaml.Context
{
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Collections;
using Controls;
using Controls.Primitives;
using Controls.Templates;
using Converters;
using Data;
using Glass;
using Input;
using Media;
using Media.Imaging;
using Metadata;
using OmniXaml;
using OmniXaml.Builder;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
using Avalonia.Styling;
using Platform;
using Templates;
public class AvaloniaRuntimeTypeSource : IRuntimeTypeSource
{
private readonly RuntimeTypeSource inner;
public AvaloniaRuntimeTypeSource(ITypeFactory typeFactory)
{
var namespaceRegistry = new AvaloniaNamespaceRegistry();
var featureProvider = new AvaloniaTypeFeatureProvider();
var typeRepository = new AvaloniaTypeRepository(namespaceRegistry, typeFactory, featureProvider);
inner = new RuntimeTypeSource(typeRepository, namespaceRegistry);
}
public Namespace GetNamespace(string name)
{
return inner.GetNamespace(name);
}
public Namespace GetNamespaceByPrefix(string prefix)
{
return inner.GetNamespaceByPrefix(prefix);
}
public void RegisterPrefix(PrefixRegistration prefixRegistration)
{
inner.RegisterPrefix(prefixRegistration);
}
public void AddNamespace(XamlNamespace xamlNamespace)
{
inner.AddNamespace(xamlNamespace);
}
public IEnumerable<PrefixRegistration> RegisteredPrefixes => inner.RegisteredPrefixes;
public XamlType GetByType(Type type)
{
return inner.GetByType(type);
}
public XamlType GetByQualifiedName(string qualifiedName)
{
return inner.GetByQualifiedName(qualifiedName);
}
public XamlType GetByPrefix(string prefix, string typeName)
{
return inner.GetByPrefix(prefix, typeName);
}
public XamlType GetByFullAddress(XamlTypeName xamlTypeName)
{
return inner.GetByFullAddress(xamlTypeName);
}
public Member GetMember(PropertyInfo propertyInfo)
{
return inner.GetMember(propertyInfo);
}
public AttachableMember GetAttachableMember(string name, MethodInfo getter, MethodInfo setter)
{
return inner.GetAttachableMember(name, getter, setter);
}
}
}

180
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeFeatureProvider.cs

@ -1,180 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Markup.Xaml.Converters;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Metadata;
using Avalonia.Styling;
using OmniXaml;
using OmniXaml.Builder;
using OmniXaml.TypeConversion;
using OmniXaml.TypeConversion.BuiltInConverters;
using OmniXaml.Typing;
using OmniMetadata = OmniXaml.Typing.Metadata;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaTypeFeatureProvider : ITypeFeatureProvider
{
private Dictionary<Type, OmniMetadata> _metadata =
new Dictionary<Type, OmniMetadata>();
private Dictionary<Type, TypeConverterRegistration> _typeConverters =
new Dictionary<Type, TypeConverterRegistration>();
public IEnumerable<TypeConverterRegistration> TypeConverters => _typeConverters.Values;
public AvaloniaTypeFeatureProvider()
{
RegisterTypeConverters();
}
public string GetContentPropertyName(Type type)
{
return GetMetadata(type)?.ContentProperty;
}
public OmniMetadata GetMetadata(Type type)
{
OmniMetadata result;
if (!_metadata.TryGetValue(type, out result))
{
result = LoadMetadata(type);
_metadata.Add(type, result);
}
return result;
}
public ITypeConverter GetTypeConverter(Type type)
{
TypeConverterRegistration result;
_typeConverters.TryGetValue(type, out result);
return result?.TypeConverter;
}
public void RegisterMetadata(Type type, OmniMetadata metadata)
{
_metadata.Add(type, metadata);
}
public void RegisterTypeConverter(Type type, ITypeConverter converter)
{
_typeConverters.Add(type, new TypeConverterRegistration(type, converter));
}
private static OmniMetadata LoadMetadata(Type type)
{
return new OmniMetadata
{
ContentProperty = GetContentProperty(type),
PropertyDependencies = GetPropertyDependencies(type),
RuntimePropertyName = type.GetRuntimeProperty("Name")?.Name,
};
}
private static string GetContentProperty(Type type)
{
while (type != null)
{
var properties = type.GetTypeInfo().DeclaredProperties
.Where(x => x.GetCustomAttribute<ContentAttribute>() != null);
string result = null;
foreach (var property in properties)
{
if (result != null)
{
throw new Exception($"Content property defined more than once on {type}.");
}
result = property.Name;
}
if (result != null)
{
return result;
}
type = type.GetTypeInfo().BaseType;
}
return null;
}
private static DependencyRegistrations GetPropertyDependencies(Type type)
{
var result = new List<DependencyRegistration>();
while (type != null)
{
var registrations = type.GetTypeInfo().DeclaredProperties
.Select(x => new
{
Property = x.Name,
Attributes = x.GetCustomAttributes<DependsOnAttribute>(),
})
.Where(x => x.Attributes.Any())
.SelectMany(x => x.Attributes.Select(y => new DependencyRegistration(x.Property, y.Name)));
result.AddRange(registrations);
type = type.GetTypeInfo().BaseType;
}
return result.Count > 0 ? new DependencyRegistrations(result) : null;
}
private void RegisterTypeConverters()
{
// HACK: For now these are hard-coded. Hopefully when the .NET Standard Platform
// is available we can use the System.ComponentModel.TypeConverters so don't want to
// spend time for now inventing a mechanism to register type converters if it's all
// going to change.
RegisterTypeConverter(typeof(string), new StringTypeConverter());
RegisterTypeConverter(typeof(int), new IntTypeConverter());
RegisterTypeConverter(typeof(long), new IntTypeConverter());
RegisterTypeConverter(typeof(short), new IntTypeConverter());
RegisterTypeConverter(typeof(double), new DoubleTypeConverter());
RegisterTypeConverter(typeof(float), new IntTypeConverter());
RegisterTypeConverter(typeof(bool), new BooleanConverter());
RegisterTypeConverter(typeof(Type), new TypeTypeConverter());
RegisterTypeConverter(typeof(IBitmap), new BitmapTypeConverter());
RegisterTypeConverter(typeof(IBrush), new BrushTypeConverter());
RegisterTypeConverter(typeof(Color), new ColorTypeConverter());
RegisterTypeConverter(typeof(Classes), new ClassesTypeConverter());
RegisterTypeConverter(typeof(ColumnDefinitions), new ColumnDefinitionsTypeConverter());
RegisterTypeConverter(typeof(DateTime), new DateTimeTypeConverter());
RegisterTypeConverter(typeof(Geometry), new GeometryTypeConverter());
RegisterTypeConverter(typeof(GridLength), new GridLengthTypeConverter());
RegisterTypeConverter(typeof(KeyGesture), new KeyGestureConverter());
RegisterTypeConverter(typeof(AvaloniaList<double>), new AvaloniaListTypeConverter<double>());
RegisterTypeConverter(typeof(IMemberSelector), new MemberSelectorTypeConverter());
RegisterTypeConverter(typeof(Point), new PointTypeConverter());
RegisterTypeConverter(typeof(IList<Point>), new PointsListTypeConverter());
RegisterTypeConverter(typeof(AvaloniaProperty), new AvaloniaPropertyTypeConverter());
RegisterTypeConverter(typeof(RelativePoint), new RelativePointTypeConverter());
RegisterTypeConverter(typeof(RelativeRect), new RelativeRectTypeConverter());
RegisterTypeConverter(typeof(RowDefinitions), new RowDefinitionsTypeConverter());
RegisterTypeConverter(typeof(Size), new SizeTypeConverter());
RegisterTypeConverter(typeof(Selector), new SelectorTypeConverter());
RegisterTypeConverter(typeof(SolidColorBrush), new BrushTypeConverter());
RegisterTypeConverter(typeof(Thickness), new ThicknessTypeConverter());
RegisterTypeConverter(typeof(TimeSpan), new TimeSpanTypeConverter());
RegisterTypeConverter(typeof(Uri), new UriTypeConverter());
RegisterTypeConverter(typeof(Cursor), new CursorTypeConverter());
RegisterTypeConverter(typeof(WindowIcon), new IconTypeConverter());
RegisterTypeConverter(typeof(FontWeight), new FontWeightConverter());
}
}
}

28
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaTypeRepository.cs

@ -1,28 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using OmniXaml;
using OmniXaml.Typing;
using Glass.Core;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaTypeRepository : TypeRepository
{
private readonly ITypeFactory _typeFactory;
public AvaloniaTypeRepository(INamespaceRegistry xamlNamespaceRegistry,
ITypeFactory typeFactory,
ITypeFeatureProvider featureProvider) : base(xamlNamespaceRegistry, typeFactory, featureProvider)
{
_typeFactory = typeFactory;
}
public override XamlType GetByType(Type type)
{
Guard.ThrowIfNull(type, nameof(type));
return new AvaloniaXamlType(type, this, _typeFactory, FeatureProvider);
}
}
}

126
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaWiringContext.cs

@ -1,126 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using System.Reflection;
using Glass;
using OmniXaml;
using OmniXaml.Builder;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Input;
using Avalonia.Markup.Xaml.Converters;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Metadata;
using Avalonia.Platform;
using Avalonia.Styling;
using System.Collections.Generic;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaWiringContext : WiringContext
{
private const string AvaloniaNs = "https://github.com/avaloniaui";
public AvaloniaWiringContext(ITypeFactory typeFactory)
: this(typeFactory, new TypeFeatureProvider(GetContentPropertyProvider(), GetConverterProvider()))
{
}
public AvaloniaWiringContext(ITypeFactory typeFactory, TypeFeatureProvider featureProvider)
: base(CreateTypeContext(typeFactory, featureProvider), featureProvider)
{
}
private static ITypeContext CreateTypeContext(ITypeFactory typeFactory, TypeFeatureProvider featureProvider)
{
var xamlNamespaceRegistry = CreateXamlNamespaceRegistry();
var typeRepository = new AvaloniaTypeRepository(xamlNamespaceRegistry, typeFactory, featureProvider);
typeRepository.RegisterMetadata(new GenericMetadata<Visual>().WithRuntimeNameProperty(d => d.Name));
typeRepository.RegisterMetadata(new GenericMetadata<Setter>().WithMemberDependency(x => x.Value, x => x.Property));
typeRepository.RegisterMetadata(
new GenericMetadata<SelectingItemsControl>()
.WithMemberDependency(x => x.SelectedIndex, x => x.Items)
.WithMemberDependency(x => x.SelectedItem, x => x.Items));
return new TypeContext(typeRepository, xamlNamespaceRegistry, typeFactory);
}
private static XamlNamespaceRegistry CreateXamlNamespaceRegistry()
{
var xamlNamespaceRegistry = new XamlNamespaceRegistry();
var forcedAssemblies = new[]
{
typeof(Binding),
typeof(Control),
typeof(IValueConverter),
typeof(Style),
}.Select(t => t.GetTypeInfo().Assembly);
foreach (var nsa in
forcedAssemblies
.Concat(AvaloniaLocator.Current.GetService<IPclPlatformWrapper>().GetLoadedAssemblies())
.Distinct()
.SelectMany(asm
=> asm.GetCustomAttributes<XmlnsDefinitionAttribute>().Select(attr => new {asm, attr}))
.GroupBy(entry => entry.attr.XmlNamespace))
{
var def = XamlNamespace.Map(nsa.Key)
.With(nsa.GroupBy(x => x.asm).Select(
a => Route.Assembly(a.Key)
.WithNamespaces(a.Select(entry => entry.attr.ClrNamespace).ToList())
));
xamlNamespaceRegistry.AddNamespace(def);
}
xamlNamespaceRegistry.RegisterPrefix(new PrefixRegistration(string.Empty, AvaloniaNs));
return xamlNamespaceRegistry;
}
private static ITypeConverterProvider GetConverterProvider()
{
var typeConverterProvider = new TypeConverterProvider();
var converters = new[]
{
new TypeConverterRegistration(typeof(IBitmap), new BitmapTypeConverter()),
new TypeConverterRegistration(typeof(Brush), new BrushTypeConverter()),
new TypeConverterRegistration(typeof(Color), new ColorTypeConverter()),
new TypeConverterRegistration(typeof(Classes), new ClassesTypeConverter()),
new TypeConverterRegistration(typeof(ColumnDefinitions), new ColumnDefinitionsTypeConverter()),
new TypeConverterRegistration(typeof(Geometry), new GeometryTypeConverter()),
new TypeConverterRegistration(typeof(GridLength), new GridLengthTypeConverter()),
new TypeConverterRegistration(typeof(KeyGesture), new KeyGestureConverter()),
new TypeConverterRegistration(typeof(AvaloniaList<double>), new AvaloniaListTypeConverter<double>()),
new TypeConverterRegistration(typeof(IMemberSelector), new MemberSelectorTypeConverter()),
new TypeConverterRegistration(typeof(Point), new PointTypeConverter()),
new TypeConverterRegistration(typeof(IList<Point>), new PointsListTypeConverter()),
new TypeConverterRegistration(typeof(AvaloniaProperty), new AvaloniaPropertyTypeConverter()),
new TypeConverterRegistration(typeof(RelativePoint), new RelativePointTypeConverter()),
new TypeConverterRegistration(typeof(RelativeRect), new RelativeRectTypeConverter()),
new TypeConverterRegistration(typeof(RowDefinitions), new RowDefinitionsTypeConverter()),
new TypeConverterRegistration(typeof(Selector), new SelectorTypeConverter()),
new TypeConverterRegistration(typeof(Thickness), new ThicknessTypeConverter()),
new TypeConverterRegistration(typeof(TimeSpan), new TimeSpanTypeConverter()),
new TypeConverterRegistration(typeof(Uri), new UriTypeConverter()),
new TypeConverterRegistration(typeof(Cursor), new CursorTypeConverter())
};
typeConverterProvider.AddAll(converters);
return typeConverterProvider;
}
private static IContentPropertyProvider GetContentPropertyProvider()
{
return new AvaloniaContentPropertyProvider();
}
}
}

31
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaXamlMember.cs

@ -1,31 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using Avalonia.Markup.Xaml.Data;
using OmniXaml;
using OmniXaml.Typing;
using System;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaXamlMember : Member
{
public AvaloniaXamlMember(string name,
XamlType owner,
ITypeRepository xamlTypeRepository,
ITypeFeatureProvider featureProvider)
: base(name, owner, xamlTypeRepository, featureProvider)
{
}
protected override IMemberValuePlugin LookupXamlMemberValueConnector()
{
return new AvaloniaMemberValuePlugin(this);
}
public override string ToString()
{
return "Avalonia XAML Member " + base.ToString();
}
}
}

61
src/Markup/Avalonia.Markup.Xaml/Context/AvaloniaXamlType.cs

@ -1,61 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Reflection;
using OmniXaml;
using OmniXaml.Typing;
using Avalonia.Controls;
namespace Avalonia.Markup.Xaml.Context
{
public class AvaloniaXamlType : XamlType
{
public AvaloniaXamlType(Type type,
ITypeRepository typeRepository,
ITypeFactory typeFactory,
ITypeFeatureProvider featureProvider) : base(type, typeRepository, typeFactory, featureProvider)
{
}
public override OmniXaml.INameScope GetNamescope(object instance)
{
var result = instance as OmniXaml.INameScope;
if (result == null)
{
var control = instance as Control;
if (control != null)
{
var avaloniaNs = (instance as Avalonia.Controls.INameScope) ?? NameScope.GetNameScope(control);
if (avaloniaNs != null)
{
result = new NameScopeWrapper(avaloniaNs);
}
}
}
return result;
}
protected override Member LookupMember(string name)
{
return new AvaloniaXamlMember(name, this, TypeRepository, FeatureProvider);
}
protected override AttachableMember LookupAttachableMember(string name)
{
// OmniXAML seems to require a getter and setter even though we don't use them.
var getter = UnderlyingType.GetTypeInfo().GetDeclaredMethod("Get" + name);
var setter = UnderlyingType.GetTypeInfo().GetDeclaredMethod("Set" + name);
return new AvaloniaAttachableXamlMember(name, this, getter, setter, TypeRepository, FeatureProvider);
}
public override string ToString()
{
return "Avalonia XAML Type " + base.ToString();
}
}
}

30
src/Markup/Avalonia.Markup.Xaml/Context/NameScopeWrapper.cs

@ -1,30 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
namespace Avalonia.Markup.Xaml.Context
{
internal class NameScopeWrapper : OmniXaml.INameScope
{
private readonly Avalonia.Controls.INameScope _inner;
public NameScopeWrapper(Avalonia.Controls.INameScope inner)
{
_inner = inner;
}
public object Find(string name)
{
return _inner.Find(name);
}
public void Register(string name, object scopedElement)
{
_inner.Register(name, scopedElement);
}
public void Unregister(string name)
{
_inner.Unregister(name);
}
}
}

174
src/Markup/Avalonia.Markup.Xaml/Context/PropertyAccessor.cs

@ -1,174 +0,0 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using OmniXaml.ObjectAssembler;
using OmniXaml.TypeConversion;
using OmniXaml.Typing;
using Avalonia.Controls;
using Avalonia.Data;
using Avalonia.Markup.Xaml.Data;
using Avalonia.Styling;
namespace Avalonia.Markup.Xaml.Context
{
internal static class PropertyAccessor
{
public static void SetValue(
object instance,
MutableMember member,
object value,
IValueContext context)
{
var avaloniaProperty = FindAvaloniaProperty(instance, member);
if (value is IBinding)
{
SetBinding(instance, member, avaloniaProperty, context, (IBinding)value);
}
else if (avaloniaProperty != null)
{
((AvaloniaObject)instance).SetValue(avaloniaProperty, value);
}
else if (instance is Setter && member.Name == "Value")
{
// TODO: Make this more generic somehow.
var setter = (Setter)instance;
var targetType = setter.Property.PropertyType;
var xamlType = member.TypeRepository.GetByType(targetType);
var convertedValue = default(object);
if (CommonValueConversion.TryConvert(value, xamlType, context, out convertedValue))
{
SetClrProperty(instance, member, convertedValue);
}
}
else
{
SetClrProperty(instance, member, value);
}
}
private static AvaloniaProperty FindAvaloniaProperty(object instance, MutableMember member)
{
var registry = AvaloniaPropertyRegistry.Instance;
var attached = member as AvaloniaAttachableXamlMember;
var target = instance as AvaloniaObject;
if (target == null)
{
return null;
}
if (attached == null)
{
return registry.FindRegistered(target, member.Name);
}
else
{
var ownerType = attached.DeclaringType.UnderlyingType;
RuntimeHelpers.RunClassConstructor(ownerType.TypeHandle);
return registry.GetRegistered(target)
.Where(x => x.OwnerType == ownerType && x.Name == attached.Name)
.FirstOrDefault();
}
}
private static void SetBinding(
object instance,
MutableMember member,
AvaloniaProperty property,
IValueContext context,
IBinding binding)
{
if (!(AssignBinding(instance, member, binding) ||
ApplyBinding(instance, property, context, binding)))
{
throw new InvalidOperationException(
$"Cannot assign to '{member.Name}' on '{instance.GetType()}");
}
}
private static void SetClrProperty(object instance, MutableMember member, object value)
{
if (member.IsAttachable)
{
member.Setter.Invoke(null, new[] { instance, value });
}
else
{
member.Setter.Invoke(instance, new[] { value });
}
}
private static bool AssignBinding(object instance, MutableMember member, IBinding binding)
{
var property = instance.GetType()
.GetRuntimeProperties()
.FirstOrDefault(x => x.Name == member.Name);
if (property?.GetCustomAttribute<AssignBindingAttribute>() != null)
{
property.SetValue(instance, binding);
return true;
}
return false;
}
private static bool ApplyBinding(
object instance,
AvaloniaProperty property,
IValueContext context,
IBinding binding)
{
if (property == null)
{
return false;
}
var control = instance as IControl;
if (control != null)
{
if (property != Control.DataContextProperty)
{
DelayedBinding.Add(control, property, binding);
}
else
{
control.Bind(property, binding);
}
}
else
{
// The target is not a control, so we need to find an anchor that will let us look
// up named controls and style resources. First look for the closest IControl in
// the TopDownValueContext.
object anchor = context.TopDownValueContext.StoredInstances
.Select(x => x.Instance)
.OfType<IControl>()
.LastOrDefault();
// If a control was not found, then try to find the highest-level style as the XAML
// file could be a XAML file containing only styles.
if (anchor == null)
{
anchor = context.TopDownValueContext.StoredInstances
.Select(x => x.Instance)
.OfType<IStyle>()
.FirstOrDefault();
}
((IAvaloniaObject)instance).Bind(property, binding, anchor);
}
return true;
}
}
}

21
src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaListTypeConverter.cs

@ -3,26 +3,22 @@
using System;
using System.Globalization;
using System.Linq;
using OmniXaml.TypeConversion;
using Avalonia.Collections;
using Avalonia.Utilities;
namespace Avalonia.Markup.Xaml.Converters
{
public class AvaloniaListTypeConverter<T> : ITypeConverter
using Portable.Xaml.ComponentModel;
using System.ComponentModel;
public class AvaloniaListTypeConverter<T> : TypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var result = new AvaloniaList<T>();
var values = ((string)value).Split(',');
@ -43,10 +39,5 @@ namespace Avalonia.Markup.Xaml.Converters
return result;
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

44
src/Markup/Avalonia.Markup.Xaml/Converters/AvaloniaPropertyTypeConverter.cs

@ -4,53 +4,52 @@
using System;
using System.Globalization;
using System.Linq;
using OmniXaml;
using OmniXaml.TypeConversion;
using Avalonia.Styling;
namespace Avalonia.Markup.Xaml.Converters
{
public class AvaloniaPropertyTypeConverter : ITypeConverter
using Avalonia.Styling;
using Portable.Xaml;
using Portable.Xaml.ComponentModel;
using System.ComponentModel;
using Portable.Xaml.Markup;
public class AvaloniaPropertyTypeConverter : TypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var s = (string)value;
string typeName;
string propertyName;
Type type;
Type type = null;
ParseProperty(s, out typeName, out propertyName);
if (typeName == null)
{
var styleType = context.TypeRepository.GetByType(typeof(Style));
var style = (Style)context.TopDownValueContext.GetLastInstance(styleType);
type = style.Selector?.TargetType;
var style = context.GetFirstAmbientValue<Style>();
type = style?.Selector?.TargetType;
if (type == null)
{
throw new ParseException(
throw new Exception(
"Could not determine the target type. Please fully qualify the property name.");
}
}
else
{
type = context.TypeRepository.GetByQualifiedName(typeName)?.UnderlyingType;
var typeResolver = context.GetService<IXamlTypeResolver>();
type = typeResolver.Resolve(typeName);
if (type == null)
{
throw new ParseException($"Could not find type '{typeName}'.");
throw new Exception($"Could not find type '{typeName}'.");
}
}
@ -61,18 +60,13 @@ namespace Avalonia.Markup.Xaml.Converters
if (property == null)
{
throw new ParseException(
throw new Exception(
$"Could not find AvaloniaProperty '{type.Name}.{propertyName}'.");
}
return property;
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
private void ParseProperty(string s, out string typeName, out string propertyName)
{
var split = s.Split('.');
@ -89,7 +83,7 @@ namespace Avalonia.Markup.Xaml.Converters
}
else
{
throw new ParseException($"Invalid property name: '{s}'.");
throw new Exception($"Invalid property name: '{s}'.");
}
}
}

31
src/Markup/Avalonia.Markup.Xaml/Converters/BitmapTypeConverter.cs

@ -3,50 +3,35 @@
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Avalonia.Media.Imaging;
using Avalonia.Platform;
namespace Avalonia.Markup.Xaml.Converters
{
public class BitmapTypeConverter : ITypeConverter
using Portable.Xaml.ComponentModel;
using System.ComponentModel;
public class BitmapTypeConverter : TypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
var uri = new Uri((string)value, UriKind.RelativeOrAbsolute);
var baseUri = GetBaseUri(context);
var scheme = uri.IsAbsoluteUri ? uri.Scheme : "file";
switch (scheme)
{
case "file":
return new Bitmap((string)value);
default:
var assets = AvaloniaLocator.Current.GetService<IAssetLoader>();
return new Bitmap(assets.Open(uri, baseUri));
return new Bitmap(assets.Open(uri, context.GetBaseUri()));
}
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
private Uri GetBaseUri(IValueContext context)
{
object result;
context.ParsingDictionary.TryGetValue("Uri", out result);
return result as Uri;
}
}
}

21
src/Markup/Avalonia.Markup.Xaml/Converters/BrushTypeConverter.cs

@ -3,31 +3,24 @@
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Avalonia.Media;
namespace Avalonia.Markup.Xaml.Converters
{
public class BrushTypeConverter : ITypeConverter
using Portable.Xaml.ComponentModel;
using System.ComponentModel;
public class BrushTypeConverter : TypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return Brush.Parse((string)value);
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

20
src/Markup/Avalonia.Markup.Xaml/Converters/ClassesTypeConverter.cs

@ -3,32 +3,20 @@
using System;
using System.Globalization;
using OmniXaml.TypeConversion;
using Avalonia.Controls;
using Avalonia.Styling;
using System.ComponentModel;
namespace Avalonia.Markup.Xaml.Converters
{
public class ClassesTypeConverter : ITypeConverter
public class ClassesTypeConverter : TypeConverter
{
public bool CanConvertFrom(IValueContext context, Type sourceType)
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
return sourceType == typeof(string);
}
public bool CanConvertTo(IValueContext context, Type destinationType)
{
return false;
}
public object ConvertFrom(IValueContext context, CultureInfo culture, object value)
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
return new Classes(((string)value).Split(' '));
}
public object ConvertTo(IValueContext context, CultureInfo culture, object value, Type destinationType)
{
throw new NotImplementedException();
}
}
}

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

Loading…
Cancel
Save