Browse Source

Merge remote-tracking branch 'AvaloniaUI/master' into CleanupPackageDeps

pull/1815/head
Jeremy Koritzinsky 8 years ago
parent
commit
124656714f
  1. 156
      .editorconfig
  2. 13
      .gitignore
  3. 5
      .ncrunch/Avalonia.Designer.HostApp.NetFX.v3.ncrunchproject
  4. 5
      .ncrunch/BindingDemo.net461.v3.ncrunchproject
  5. 5
      .ncrunch/BindingDemo.netcoreapp2.0.v3.ncrunchproject
  6. 5
      .ncrunch/Previewer.v3.ncrunchproject
  7. 5
      .ncrunch/RemoteDemo.v3.ncrunchproject
  8. 5
      .ncrunch/RenderDemo.net461.v3.ncrunchproject
  9. 5
      .ncrunch/RenderDemo.netcoreapp2.0.v3.ncrunchproject
  10. 5
      .ncrunch/VirtualizationDemo.net461.v3.ncrunchproject
  11. 5
      .ncrunch/VirtualizationDemo.netcoreapp2.0.v3.ncrunchproject
  12. 57
      Avalonia.sln
  13. 232
      build.cake
  14. 4
      build/SkiaSharp.props
  15. 5
      build/Sprache.props
  16. 8
      build/System.Memory.props
  17. 1
      build/readme.md
  18. 85
      packages.cake
  19. 12
      parameters.cake
  20. 2
      readme.md
  21. 0
      samples/BindingDemo/App.config
  22. 0
      samples/BindingDemo/App.xaml
  23. 2
      samples/BindingDemo/App.xaml.cs
  24. 0
      samples/BindingDemo/BindingDemo.csproj
  25. 30
      samples/BindingDemo/MainWindow.xaml
  26. 4
      samples/BindingDemo/MainWindow.xaml.cs
  27. 0
      samples/BindingDemo/TestItemView.xaml
  28. 2
      samples/BindingDemo/TestItemView.xaml.cs
  29. 2
      samples/BindingDemo/ViewModels/DataAnnotationsErrorViewModel.cs
  30. 2
      samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs
  31. 2
      samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs
  32. 2
      samples/BindingDemo/ViewModels/MainWindowViewModel.cs
  33. 2
      samples/BindingDemo/ViewModels/NestedCommandViewModel.cs
  34. 2
      samples/BindingDemo/ViewModels/TestItem.cs
  35. 4
      samples/ControlCatalog.NetCore/Program.cs
  36. 3
      samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj
  37. 6
      samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml
  38. 6
      samples/ControlCatalog/Pages/BorderPage.xaml
  39. 10
      samples/ControlCatalog/Pages/ButtonPage.xaml
  40. 6
      samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml
  41. 6
      samples/ControlCatalog/Pages/CalendarPage.xaml
  42. 4
      samples/ControlCatalog/Pages/CanvasPage.xaml
  43. 10
      samples/ControlCatalog/Pages/CarouselPage.xaml
  44. 10
      samples/ControlCatalog/Pages/CheckBoxPage.xaml
  45. 6
      samples/ControlCatalog/Pages/ContextMenuPage.xaml
  46. 6
      samples/ControlCatalog/Pages/DatePickerPage.xaml
  47. 4
      samples/ControlCatalog/Pages/DialogsPage.xaml
  48. 6
      samples/ControlCatalog/Pages/DragAndDropPage.xaml
  49. 6
      samples/ControlCatalog/Pages/DropDownPage.xaml
  50. 6
      samples/ControlCatalog/Pages/ExpanderPage.xaml
  51. 4
      samples/ControlCatalog/Pages/ImagePage.xaml
  52. 4
      samples/ControlCatalog/Pages/MenuPage.xaml
  53. 6
      samples/ControlCatalog/Pages/NumericUpDownPage.xaml
  54. 6
      samples/ControlCatalog/Pages/ProgressBarPage.xaml
  55. 8
      samples/ControlCatalog/Pages/RadioButtonPage.xaml
  56. 4
      samples/ControlCatalog/Pages/SliderPage.xaml
  57. 11
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  58. 2
      samples/ControlCatalog/Pages/ToolTipPage.xaml
  59. 4
      samples/ControlCatalog/Pages/TreeViewPage.xaml
  60. 4
      samples/ControlCatalog/SideBar.xaml
  61. 2
      samples/RemoteDemo/Program.cs
  62. 0
      samples/RemoteDemo/RemoteDemo.csproj
  63. 0
      samples/RenderDemo/App.config
  64. 2
      samples/RenderDemo/App.xaml
  65. 2
      samples/RenderDemo/App.xaml.cs
  66. 2
      samples/RenderDemo/MainWindow.xaml
  67. 4
      samples/RenderDemo/MainWindow.xaml.cs
  68. 0
      samples/RenderDemo/Pages/AnimationsPage.xaml
  69. 4
      samples/RenderDemo/Pages/AnimationsPage.xaml.cs
  70. 0
      samples/RenderDemo/Pages/ClippingPage.xaml
  71. 2
      samples/RenderDemo/Pages/ClippingPage.xaml.cs
  72. 0
      samples/RenderDemo/Pages/DrawingPage.xaml
  73. 2
      samples/RenderDemo/Pages/DrawingPage.xaml.cs
  74. 0
      samples/RenderDemo/RenderDemo.csproj
  75. 4
      samples/RenderDemo/SideBar.xaml
  76. 2
      samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs
  77. 2
      samples/RenderDemo/ViewModels/MainWindowViewModel.cs
  78. 0
      samples/VirtualizationDemo/App.config
  79. 0
      samples/VirtualizationDemo/App.xaml
  80. 2
      samples/VirtualizationDemo/App.xaml.cs
  81. 2
      samples/VirtualizationDemo/MainWindow.xaml
  82. 4
      samples/VirtualizationDemo/MainWindow.xaml.cs
  83. 2
      samples/VirtualizationDemo/Program.cs
  84. 2
      samples/VirtualizationDemo/ViewModels/ItemViewModel.cs
  85. 2
      samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs
  86. 0
      samples/VirtualizationDemo/VirtualizationDemo.csproj
  87. 2
      src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj
  88. 126
      src/Avalonia.Animation/Animation.cs
  89. 66
      src/Avalonia.Animation/AnimatorKeyFrame.cs
  90. 191
      src/Avalonia.Animation/AnimatorStateMachine`1.cs
  91. 80
      src/Avalonia.Animation/Animator`1.cs
  92. 2
      src/Avalonia.Animation/Cue.cs
  93. 8
      src/Avalonia.Animation/DoubleAnimator.cs
  94. 10
      src/Avalonia.Animation/IAnimation.cs
  95. 2
      src/Avalonia.Animation/IAnimationSetter.cs
  96. 2
      src/Avalonia.Animation/IAnimator.cs
  97. 16
      src/Avalonia.Animation/KeyFrame.cs
  98. 8
      src/Avalonia.Animation/KeyFramePair`1.cs
  99. 3
      src/Avalonia.Base/Avalonia.Base.csproj
  100. 217
      src/Avalonia.Base/AvaloniaObject.cs

156
.editorconfig

@ -1,11 +1,159 @@
; This file is for unifying the coding style for different editors and IDEs.
; More information at http://EditorConfig.org
# editorconfig.org
# top-most EditorConfig file
root = true
# Default settings:
# A newline ending every file
# Use 4 spaces as indentation
[*]
end_of_line = CRLF
insert_final_newline = true
indent_style = space
indent_size = 4
# C# files
[*.cs]
indent_style = space
# New line preferences
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_indent_labels = one_less_than_current
# avoid this. unless absolutely necessary
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
# prefer var
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere = true:suggestion
# use language keywords instead of BCL types
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# static fields should have s_ prefix
dotnet_naming_rule.static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.static_fields_should_have_prefix.symbols = static_fields
dotnet_naming_rule.static_fields_should_have_prefix.style = static_prefix_style
dotnet_naming_symbols.static_fields.applicable_kinds = field
dotnet_naming_symbols.static_fields.required_modifiers = static
dotnet_naming_style.static_prefix_style.required_prefix = s_
dotnet_naming_style.static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# use accessibility modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
# Code style defaults
dotnet_sort_system_directives_first = true
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
# Expression-bodied members
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Pattern matching
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
# Null checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = do_not_ignore
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Xaml files
[*.xaml]
indent_size = 4
# Xml project files
[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
indent_size = 2
# Xml build files
[*.builds]
indent_size = 2
# Xml files
[*.{xml,stylecop,resx,ruleset}]
indent_size = 2
# Xml config files
[*.{props,targets,config,nuspec}]
indent_size = 2
# Shell scripts
[*.sh]
end_of_line = lf
[*.{cmd, bat}]
end_of_line = crlf

13
.gitignore

@ -165,6 +165,11 @@ $RECYCLE.BIN/
#################
.idea
#################
## VS Code
#################
.vscode/
#################
## Cake
#################
@ -176,5 +181,9 @@ nuget
Avalonia.XBuild.sln
project.lock.json
.idea/*
**/obj-Skia/*
**/obj-Direct2D1/*
##################
## BenchmarkDotNet
##################
BenchmarkDotNet.Artifacts/

5
.ncrunch/Avalonia.Designer.HostApp.NetFX.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/BindingDemo.net461.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/BindingDemo.netcoreapp2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/Previewer.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/RemoteDemo.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/RenderDemo.net461.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/RenderDemo.netcoreapp2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/VirtualizationDemo.net461.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

5
.ncrunch/VirtualizationDemo.netcoreapp2.0.v3.ncrunchproject

@ -0,0 +1,5 @@
<ProjectConfiguration>
<Settings>
<IgnoreThisComponentCompletely>True</IgnoreThisComponentCompletely>
</Settings>
</ProjectConfiguration>

57
Avalonia.sln

@ -58,6 +58,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Samples", "Samples", "{9B9E
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
src\Shared\SharedAssemblyInfo.cs = src\Shared\SharedAssemblyInfo.cs
EndProjectSection
EndProject
@ -71,7 +72,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Mark
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingTest", "samples\BindingTest\BindingTest.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BindingDemo", "samples\BindingDemo\BindingDemo.csproj", "{08B3E6B9-1CD5-443C-9F61-6D49D1C5F162}"
EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
EndProject
@ -109,7 +110,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Te
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualizationTest", "samples\VirtualizationTest\VirtualizationTest.csproj", "{FBCAF3D0-2808-4934-8E96-3F607594517B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VirtualizationDemo", "samples\VirtualizationDemo\VirtualizationDemo.csproj", "{FBCAF3D0-2808-4934-8E96-3F607594517B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC0258-D18C-4AB3-854F-7101680FC3F9}"
EndProject
@ -117,7 +118,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInteropTest", "sampl
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetFrameworkRuntime", "src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj", "{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderTest", "samples\RenderTest\RenderTest.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RenderDemo", "samples\RenderDemo\RenderDemo.csproj", "{F1FDC5B0-4654-416F-AE69-E3E9BBD87801}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
EndProject
@ -140,6 +141,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props
build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props
build\ReactiveUI.props = build\ReactiveUI.props
build\Rx.props = build\Rx.props
build\SampleApp.props = build\SampleApp.props
@ -147,7 +149,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\SharpDX.props = build\SharpDX.props
build\SkiaSharp.props = build\SkiaSharp.props
build\Splat.props = build\Splat.props
build\Sprache.props = build\Sprache.props
build\System.Memory.props = build\System.Memory.props
build\XUnit.props = build\XUnit.props
EndProjectSection
EndProject
@ -168,7 +170,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Remote.Protocol", "src\Avalonia.Remote.Protocol\Avalonia.Remote.Protocol.csproj", "{D78A720C-C0C6-478B-8564-F167F9BDD01B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RemoteTest", "samples\RemoteTest\RemoteTest.csproj", "{E2999E4A-9086-401F-898C-AEB0AD38E676}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RemoteDemo", "samples\RemoteDemo\RemoteDemo.csproj", "{E2999E4A-9086-401F-898C-AEB0AD38E676}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{4ED8B739-6F4E-4CD4-B993-545E6B5CE637}"
EndProject
@ -182,6 +184,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MonoMac", "src\OSX
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.Designer.HostApp.NetFX", "src\tools\Avalonia.Designer.HostApp.NetFX\Avalonia.Designer.HostApp.NetFX.csproj", "{4ADA61C8-D191-428D-9066-EF4F0D86520F}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.UnitTests", "tests\Avalonia.Skia.UnitTests\Avalonia.Skia.UnitTests.csproj", "{E1240B49-7B4B-4371-A00E-068778C5CF0B}"
EndProject
Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13
@ -394,6 +398,7 @@ Global
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|x86.ActiveCfg = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|x86.Build.0 = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|Any CPU.ActiveCfg = Release|Any CPU
@ -403,6 +408,7 @@ Global
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|NetCoreOnly.Build.0 = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|x86.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|x86.Build.0 = Release|Any CPU
{62024B2D-53EB-4638-B26B-85EEAA54866E}.Ad-Hoc|Any CPU.ActiveCfg = Release|Any CPU
@ -2467,6 +2473,46 @@ Global
{4ADA61C8-D191-428D-9066-EF4F0D86520F}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU
{4ADA61C8-D191-428D-9066-EF4F0D86520F}.Release|x86.ActiveCfg = Release|Any CPU
{4ADA61C8-D191-428D-9066-EF4F0D86520F}.Release|x86.Build.0 = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|NetCoreOnly.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|NetCoreOnly.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|x86.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Ad-Hoc|x86.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|Any CPU.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|iPhone.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|iPhone.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|NetCoreOnly.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|NetCoreOnly.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|x86.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.AppStore|x86.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|iPhone.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|iPhone.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|NetCoreOnly.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|NetCoreOnly.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|x86.ActiveCfg = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Debug|x86.Build.0 = Debug|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|Any CPU.Build.0 = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhone.ActiveCfg = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhone.Build.0 = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|NetCoreOnly.ActiveCfg = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|NetCoreOnly.Build.0 = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|x86.ActiveCfg = Release|Any CPU
{E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -2519,6 +2565,7 @@ Global
{F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{CBFD5788-567D-401B-9DFA-74E4224025A0} = {A59C4C0A-64DF-4621-B450-2BA00D6F61E2}
{4ADA61C8-D191-428D-9066-EF4F0D86520F} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{E1240B49-7B4B-4371-A00E-068778C5CF0B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

232
build.cake

@ -6,6 +6,7 @@
#addin "nuget:?package=NuGet.Core&version=2.14.0"
#tool "nuget:?package=NuGet.CommandLine&version=4.3.0"
#tool "nuget:?package=JetBrains.ReSharper.CommandLineTools&version=2017.1.20170613.162720"
///////////////////////////////////////////////////////////////////////////////
// TOOLS
///////////////////////////////////////////////////////////////////////////////
@ -98,7 +99,7 @@ Teardown<AvaloniaBuildData>((context, buildContext) =>
// TASKS
///////////////////////////////////////////////////////////////////////////////
Task("Clean")
Task("Clean-Impl")
.Does<AvaloniaBuildData>(data =>
{
CleanDirectories(data.Parameters.BuildDirs);
@ -108,9 +109,9 @@ Task("Clean")
CleanDirectory(data.Parameters.BinRoot);
});
Task("Restore-NuGet-Packages")
.IsDependentOn("Clean")
Task("Restore-NuGet-Packages-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPlatformNetCoreOnly)
.Does<AvaloniaBuildData>(data =>
{
var maxRetryCount = 5;
@ -148,11 +149,10 @@ void DotNetCoreBuild(Parameters parameters)
DotNetCoreBuild(parameters.MSBuildSolution, settings);
}
Task("Build")
.IsDependentOn("Restore-NuGet-Packages")
Task("Build-Impl")
.Does<AvaloniaBuildData>(data =>
{
if(data.Parameters.IsRunningOnWindows)
if(data.Parameters.IsRunningOnWindows && !data.Parameters.IsPlatformNetCoreOnly)
{
MSBuild(data.Parameters.MSBuildSolution, settings => {
settings.SetConfiguration(data.Parameters.Configuration);
@ -171,7 +171,6 @@ Task("Build")
}
});
void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
{
if(!project.EndsWith(".csproj"))
@ -194,93 +193,91 @@ void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
}
}
Task("Run-Unit-Tests")
.IsDependentOn("Build")
Task("Run-Unit-Tests-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.Base.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Controls.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Input.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Layout.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Styling.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data.Parameters, false);
if (data.Parameters.IsRunningOnWindows)
{
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data.Parameters, true);
}
});
.Does<AvaloniaBuildData>(data =>
{
RunCoreTest("./tests/Avalonia.Base.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Controls.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Input.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Layout.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Styling.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Skia.UnitTests", data.Parameters, false);
if (data.Parameters.IsRunningOnWindows && !data.Parameters.IsPlatformNetCoreOnly)
{
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data.Parameters, true);
}
});
Task("Run-Designer-Tests")
.IsDependentOn("Build")
Task("Run-Designer-Tests-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data.Parameters, false);
});
.Does<AvaloniaBuildData>(data =>
{
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data.Parameters, false);
});
Task("Run-Render-Tests")
.IsDependentOn("Build")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests && data.Parameters.IsRunningOnWindows)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data.Parameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data.Parameters, true);
});
Task("Run-Render-Tests-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPlatformNetCoreOnly)
.Does<AvaloniaBuildData>(data =>
{
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data.Parameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data.Parameters, true);
});
Task("Run-Leak-Tests")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests && data.Parameters.IsRunningOnWindows)
.IsDependentOn("Build")
Task("Run-Leak-Tests-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPlatformNetCoreOnly)
.Does(() =>
{
var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe");
var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings
{
var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe");
var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings
{
Arguments = new ProcessArgumentBuilder()
.Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath)
.Append("--propagate-exit-code")
.Append("--")
.Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"),
Timeout = 120000
});
if (leakTestsExitCode != 0)
{
throw new Exception("Leak Tests failed");
}
Arguments = new ProcessArgumentBuilder()
.Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath)
.Append("--propagate-exit-code")
.Append("--")
.Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"),
Timeout = 120000
});
Task("Run-Tests")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Run-Render-Tests")
.IsDependentOn("Run-Designer-Tests")
.IsDependentOn("Run-Leak-Tests");
if (leakTestsExitCode != 0)
{
throw new Exception("Leak Tests failed");
}
});
Task("Copy-Files")
.IsDependentOn("Run-Tests")
Task("Copy-Files-Impl")
.Does<AvaloniaBuildData>(data =>
{
CopyFiles(data.Packages.BinFiles, data.Parameters.BinRoot);
});
Task("Zip-Files")
.IsDependentOn("Copy-Files")
Task("Zip-Files-Impl")
.Does<AvaloniaBuildData>(data =>
{
Zip(data.Parameters.BinRoot, data.Parameters.ZipCoreArtifacts);
Zip(data.Parameters.ZipSourceControlCatalogDesktopDirs,
data.Parameters.ZipTargetControlCatalogDesktopDirs,
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
Zip(data.Parameters.NugetRoot, data.Parameters.ZipNuGetArtifacts);
if (!data.Parameters.IsPlatformNetCoreOnly) {
Zip(data.Parameters.ZipSourceControlCatalogDesktopDirs,
data.Parameters.ZipTargetControlCatalogDesktopDirs,
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
GetFiles(data.Parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
}
});
Task("Create-NuGet-Packages")
.IsDependentOn("Run-Tests")
.IsDependentOn("Inspect")
Task("Create-NuGet-Packages-Impl")
.Does<AvaloniaBuildData>(data =>
{
foreach(var nuspec in data.Packages.NuspecNuGetSettings)
@ -289,8 +286,7 @@ Task("Create-NuGet-Packages")
}
});
Task("Publish-MyGet")
.IsDependentOn("Create-NuGet-Packages")
Task("Publish-MyGet-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsLocalBuild)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPullRequest)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsMainRepo)
@ -323,8 +319,7 @@ Task("Publish-MyGet")
Information("Publish-MyGet Task failed, but continuing with next Task...");
});
Task("Publish-NuGet")
.IsDependentOn("Create-NuGet-Packages")
Task("Publish-NuGet-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsLocalBuild)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPullRequest)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsMainRepo)
@ -356,54 +351,67 @@ Task("Publish-NuGet")
Information("Publish-NuGet Task failed, but continuing with next Task...");
});
Task("Inspect")
Task("Inspect-Impl")
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.IsDependentOn("Restore-NuGet-Packages")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.IsPlatformNetCoreOnly)
.Does(() =>
{
var badIssues = new []{"PossibleNullReferenceException"};
var whitelist = new []{"tests", "src\\android", "src\\ios",
"src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"};
Information("Running code inspections");
var exitCode = StartProcess(Context.Tools.Resolve("inspectcode.exe"),
new ProcessSettings
{
Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln",
RedirectStandardOutput = true
});
{
var badIssues = new []{"PossibleNullReferenceException"};
var whitelist = new []{"tests", "src\\android", "src\\ios",
"src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"};
Information("Running code inspections");
var exitCode = StartProcess(Context.Tools.Resolve("inspectcode.exe"),
new ProcessSettings
{
Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln",
RedirectStandardOutput = true
});
Information("Analyzing report");
var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));
var failBuild = false;
foreach(var xml in doc.Descendants("Issue"))
Information("Analyzing report");
var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));
var failBuild = false;
foreach(var xml in doc.Descendants("Issue"))
{
var typeId = xml.Attribute("TypeId").Value.ToString();
if(badIssues.Contains(typeId))
{
var typeId = xml.Attribute("TypeId").Value.ToString();
if(badIssues.Contains(typeId))
{
var file = xml.Attribute("File").Value.ToString().ToLower();
if(whitelist.Any(wh => file.StartsWith(wh)))
continue;
var line = xml.Attribute("Line").Value.ToString();
Error(typeId + " - " + file + " on line " + line);
failBuild = true;
}
var file = xml.Attribute("File").Value.ToString().ToLower();
if(whitelist.Any(wh => file.StartsWith(wh)))
continue;
var line = xml.Attribute("Line").Value.ToString();
Error(typeId + " - " + file + " on line " + line);
failBuild = true;
}
if(failBuild)
throw new Exception("Issues found");
});
}
if(failBuild)
throw new Exception("Issues found");
});
///////////////////////////////////////////////////////////////////////////////
// TARGETS
///////////////////////////////////////////////////////////////////////////////
Task("Run-Tests")
.IsDependentOn("Clean-Impl")
.IsDependentOn("Restore-NuGet-Packages-Impl")
.IsDependentOn("Build-Impl")
.IsDependentOn("Run-Unit-Tests-Impl")
.IsDependentOn("Run-Render-Tests-Impl")
.IsDependentOn("Run-Designer-Tests-Impl")
.IsDependentOn("Run-Leak-Tests-Impl");
Task("Package")
.IsDependentOn("Create-NuGet-Packages");
.IsDependentOn("Run-Tests")
.IsDependentOn("Inspect-Impl")
.IsDependentOn("Create-NuGet-Packages-Impl");
Task("AppVeyor")
.IsDependentOn("Zip-Files")
.IsDependentOn("Publish-MyGet")
.IsDependentOn("Publish-NuGet");
.IsDependentOn("Package")
.IsDependentOn("Copy-Files-Impl")
.IsDependentOn("Zip-Files-Impl")
.IsDependentOn("Publish-MyGet-Impl")
.IsDependentOn("Publish-NuGet-Impl");
Task("Travis")
.IsDependentOn("Run-Tests");

4
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="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.57.1.3" />
<PackageReference Include="SkiaSharp" Version="1.60.0" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.60.0.1" />
</ItemGroup>
</Project>

5
build/Sprache.props

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

8
build/System.Memory.props

@ -0,0 +1,8 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<PackageReference Include="System.Memory" Version="4.5.1" />
<!-- WORKAROUND: The packages below are transitively referenced by System.Memory, but Xamarin.Android needs them directly referenced for the linker. -->
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.1" />
<PackageReference Include="System.Buffers" Version="4.5.0" />
</ItemGroup>
</Project>

1
build/readme.md

@ -15,7 +15,6 @@
<Import Project="..\..\build\SkiaSharp.Desktop.props" />
<Import Project="..\..\build\SkiaSharp.props" />
<Import Project="..\..\build\Splat.props" />
<Import Project="..\..\build\Sprache.props" />
<Import Project="..\..\build\XUnit.props" />
```

85
packages.cake

@ -1,3 +1,6 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Xml.Linq;
public class Packages
@ -9,12 +12,11 @@ public class Packages
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;
@ -24,8 +26,7 @@ public class Packages
{
return _parent.PackageVersions[name].First().Item1;
}
public DependencyBuilder Dep(string name, params string[] fws)
{
if(fws.Length == 0)
@ -109,7 +110,6 @@ public class Packages
var SerilogVersion = packageVersions["Serilog"].FirstOrDefault().Item1;
var SerilogSinksDebugVersion = packageVersions["Serilog.Sinks.Debug"].FirstOrDefault().Item1;
var SerilogSinksTraceVersion = packageVersions["Serilog.Sinks.Trace"].FirstOrDefault().Item1;
var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1;
var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1;
var ReactiveUIVersion = packageVersions["reactiveui"].FirstOrDefault().Item1;
var SystemValueTupleVersion = packageVersions["System.ValueTuple"].FirstOrDefault().Item1;
@ -120,10 +120,10 @@ public class Packages
var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1;
var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1;
var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].FirstOrDefault().Item1;
var SystemComponentModelAnnotationsVersion = packageVersions["System.ComponentModel.Annotations"].FirstOrDefault().Item1;
var SystemMemoryVersion = packageVersions["System.Memory"].FirstOrDefault().Item1;
var SystemComponentModeTypeConverterVersion = packageVersions["System.ComponentModel.TypeConverter"].FirstOrDefault().Item1;
context.Information("Package: Serilog, version: {0}", SerilogVersion);
context.Information("Package: Sprache, version: {0}", SpracheVersion);
context.Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
context.Information("Package: reactiveui, version: {0}", ReactiveUIVersion);
context.Information("Package: System.ValueTuple, version: {0}", SystemValueTupleVersion);
@ -134,6 +134,7 @@ public class Packages
context.Information("Package: SharpDX.Direct3D11, version: {0}", SharpDXDirect3D11Version);
context.Information("Package: SharpDX.Direct3D9, version: {0}", SharpDXDirect3D9Version);
context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
context.Information("Package: System.Memory, version: {0}", SystemMemoryVersion);
var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME")
?? System.IO.Path.Combine(System.Environment.GetEnvironmentVariable("USERPROFILE") ?? System.Environment.GetEnvironmentVariable("HOME"), ".nuget");
@ -212,17 +213,33 @@ public class Packages
};
});
var toolsContent = new[] {
new NuSpecContent{
Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp/bin/" + parameters.DirSuffix + "/netcoreapp2.0/Avalonia.Designer.HostApp.dll")).FullPath,
Target = "tools/netcoreapp2.0/previewer"
},
new NuSpecContent{
Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp.NetFx/bin/" + parameters.DirSuffix + "/Avalonia.Designer.HostApp.exe")).FullPath,
Target = "tools/net461/previewer"
}
var toolHostApp = new NuSpecContent{
Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp/bin/" + parameters.DirSuffix + "/netcoreapp2.0/Avalonia.Designer.HostApp.dll")).FullPath,
Target = "tools/netcoreapp2.0/previewer"
};
var toolHostAppNetFx = new NuSpecContent{
Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp.NetFx/bin/" + parameters.DirSuffix + "/Avalonia.Designer.HostApp.exe")).FullPath,
Target = "tools/net461/previewer"
};
IList<NuSpecContent> coreFiles;
if (!parameters.IsPlatformNetCoreOnly) {
var toolsContent = new[] { toolHostApp, toolHostAppNetFx };
coreFiles = coreLibrariesNuSpecContent
.Concat(win32CoreLibrariesNuSpecContent).Concat(net45RuntimePlatform)
.Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
.Concat(toolsContent)
.ToList();
} else {
var toolsContent = new[] { toolHostApp };
coreFiles = coreLibrariesNuSpecContent
.Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
.Concat(toolsContent)
.ToList();
}
var nuspecNuGetSettingsCore = new []
{
///////////////////////////////////////////////////////////////////////////////
@ -237,17 +254,14 @@ public class Packages
new NuSpecDependency() { Id = "Avalonia.Remote.Protocol", Version = parameters.Version, TargetFramework="netcoreapp2.0" },
new NuSpecDependency() { Id = "Avalonia.Remote.Protocol", Version = parameters.Version, TargetFramework="net461" },
new NuSpecDependency() { Id = "System.ValueTuple", Version = SystemValueTupleVersion, TargetFramework="net461" },
new NuSpecDependency() { Id = "System.ComponentModel.TypeConverter", Version = SystemComponentModeTypeConverterVersion, TargetFramework="net461" },
new NuSpecDependency() { Id = "NETStandard.Library", Version = "2.0.0", TargetFramework="net461"}
}
.Deps(new string[]{"netstandard2.0", "netcoreapp2.0", "net461"},
"Serilog", "Serilog.Sinks.Debug", "Serilog.Sinks.Trace", "Sprache",
"System.Reactive", "System.ComponentModel.Annotations")
"Serilog", "Serilog.Sinks.Debug", "Serilog.Sinks.Trace",
"System.Memory", "System.Reactive", "System.ComponentModel.Annotations")
.ToArray(),
Files = coreLibrariesNuSpecContent
.Concat(netFrameworkCoreLibrariesNuSpecContent).Concat(netFrameworkRuntimePlatform)
.Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
.Concat(toolsContent)
.ToList(),
Files = coreFiles,
BasePath = context.Directory("./"),
OutputDirectory = parameters.NugetRoot
},
@ -475,11 +489,32 @@ public class Packages
}
};
var nuspecNuGetSettingInterop = 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
};
NuspecNuGetSettings = new List<NuGetPackSettings>();
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsCore);
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsDesktop);
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
if (!parameters.IsPlatformNetCoreOnly) {
NuspecNuGetSettings.Add(nuspecNuGetSettingInterop);
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
}
NuspecNuGetSettings.ForEach((nuspec) => SetNuGetNuspecCommonProperties(nuspec));

12
parameters.cake

@ -8,11 +8,11 @@ public class Parameters
public string AssemblyInfoPath { get; private set; }
public string ReleasePlatform { get; private set; }
public string ReleaseConfiguration { get; private set; }
public string MSBuildSolution { get; private set; }
public string XBuildSolution { get; private set; }
public string MSBuildSolution { get; private set; }
public bool IsPlatformAnyCPU { get; private set; }
public bool IsPlatformX86 { get; private set; }
public bool IsPlatformX64 { get; private set; }
public bool IsPlatformNetCoreOnly { get; private set; }
public bool IsLocalBuild { get; private set; }
public bool IsRunningOnUnix { get; private set; }
public bool IsRunningOnWindows { get; private set; }
@ -34,6 +34,7 @@ public class Parameters
public DirectoryPathCollection BuildDirs { get; private set; }
public string FileZipSuffix { get; private set; }
public FilePath ZipCoreArtifacts { get; private set; }
public FilePath ZipNuGetArtifacts { get; private set; }
public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; }
public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; }
@ -53,12 +54,12 @@ public class Parameters
ReleasePlatform = "Any CPU";
ReleaseConfiguration = "Release";
MSBuildSolution = "./Avalonia.sln";
XBuildSolution = "./Avalonia.XBuild.sln";
// PARAMETERS
IsPlatformAnyCPU = StringComparer.OrdinalIgnoreCase.Equals(Platform, "Any CPU");
IsPlatformX86 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x86");
IsPlatformX64 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x64");
IsPlatformNetCoreOnly = StringComparer.OrdinalIgnoreCase.Equals(Platform, "NetCoreOnly");
IsLocalBuild = buildSystem.IsLocalBuild;
IsRunningOnUnix = context.IsRunningOnUnix();
IsRunningOnWindows = context.IsRunningOnWindows();
@ -71,7 +72,6 @@ public class Parameters
IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleasePlatform, Platform)
&& StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
IsMyGetRelease = !IsTagged && IsReleasable;
// VERSION
Version = context.Argument("force-nuget-version", context.ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion);
@ -103,14 +103,12 @@ public class Parameters
NugetRoot = ArtifactsDir.Combine("nuget");
ZipRoot = ArtifactsDir.Combine("zip");
BinRoot = ArtifactsDir.Combine("bin");
BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj");
DirSuffix = Configuration;
DirSuffixIOS = "iPhone" + "/" + Configuration;
FileZipSuffix = Version + ".zip";
ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix);
ZipNuGetArtifacts = ZipRoot.CombineWithFilePath("Avalonia-NuGet-" + FileZipSuffix);
ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix);
}

2
readme.md

@ -20,6 +20,8 @@ Avalonia is a WPF-inspired cross-platform XAML-based UI framework providing a fl
Avalonia [Visual Studio Extension](https://marketplace.visualstudio.com/items?itemName=AvaloniaTeam.AvaloniaforVisualStudio) contains project and control templates that will help you get started. After installing it, open "New Project" dialog in Visual Studio, choose "Avalonia" in "Visual C#" section, select "Avalonia .NET Core Application" and press OK (<a href="http://avaloniaui.net/docs/quickstart/images/new-project-dialog.png">screenshot</a>). Now you can write code and markup that will work on multiple platforms!
For those without Visual Studio, starter guide for .NET Core CLI can be found [here](http://avaloniaui.net/docs/quickstart/create-new-project#net-core).
Avalonia is delivered via <b>NuGet</b> package manager. You can find the packages here: ([stable(ish)](https://www.nuget.org/packages/Avalonia/), [nightly](https://github.com/AvaloniaUI/Avalonia/wiki/Using-nightly-build-feed))
Use these commands in Package Manager console to install Avalonia manually:

0
samples/BindingTest/App.config → samples/BindingDemo/App.config

0
samples/BindingTest/App.xaml → samples/BindingDemo/App.xaml

2
samples/BindingTest/App.xaml.cs → samples/BindingDemo/App.xaml.cs

@ -5,7 +5,7 @@ using Avalonia.Logging.Serilog;
using Avalonia.Markup.Xaml;
using Serilog;
namespace BindingTest
namespace BindingDemo
{
public class App : Application
{

0
samples/BindingTest/BindingTest.csproj → samples/BindingDemo/BindingDemo.csproj

30
samples/BindingTest/MainWindow.xaml → samples/BindingDemo/MainWindow.xaml

@ -1,7 +1,7 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:vm="clr-namespace:BindingTest.ViewModels"
xmlns:local="clr-namespace:BindingTest"
xmlns:vm="clr-namespace:BindingDemo.ViewModels"
xmlns:local="clr-namespace:BindingDemo"
Title="AvaloniaUI Bindings Test"
Width="800"
Height="600">
@ -18,18 +18,18 @@
<TabItem Header="Basic">
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<StackPanel Margin="18" Gap="4" Width="200">
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Simple Bindings"/>
<TextBox Watermark="Two Way" UseFloatingWatermark="True" Text="{Binding Path=StringValue}" Name="first"/>
<TextBox Watermark="One Way" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneWay}"/>
<TextBox Watermark="One Time" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneTime}"/>
</StackPanel>
<StackPanel Margin="18" Gap="4" Width="200">
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Collection Bindings"/>
<TextBox Watermark="Items[1].StringValue" UseFloatingWatermark="True" Text="{Binding Path=Items[1].StringValue}"/>
<Button Command="{Binding ShuffleItems}">Shuffle</Button>
</StackPanel>
<StackPanel Margin="18" Gap="4" Width="200">
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Negated Bindings"/>
<TextBox Watermark="Boolean String" UseFloatingWatermark="True" Text="{Binding Path=BooleanString}"/>
<CheckBox IsChecked="{Binding !BooleanString}">!BooleanString</CheckBox>
@ -37,13 +37,13 @@
</StackPanel>
</StackPanel>
<StackPanel Orientation="Horizontal">
<StackPanel Margin="18" Gap="4" Width="200" HorizontalAlignment="Left">
<StackPanel Margin="18" Spacing="4" Width="200" HorizontalAlignment="Left">
<TextBlock FontSize="16" Text="Numeric Bindings"/>
<TextBox Watermark="Double" UseFloatingWatermark="True" Text="{Binding Path=DoubleValue, Mode=TwoWay}"/>
<TextBlock Text="{Binding Path=DoubleValue}"/>
<ProgressBar Maximum="10" Value="{Binding DoubleValue}"/>
</StackPanel>
<StackPanel Margin="18" Gap="4" Width="200" HorizontalAlignment="Left">
<StackPanel Margin="18" Spacing="4" Width="200" HorizontalAlignment="Left">
<TextBlock FontSize="16" Text="Binding Sources"/>
<TextBox Watermark="Value of first TextBox" UseFloatingWatermark="True"
Text="{Binding #first.Text, Mode=TwoWay}"/>
@ -52,7 +52,7 @@
<TextBox Watermark="Value of SharedItem.StringValue (duplicate)" UseFloatingWatermark="True"
Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay}"/>
</StackPanel>
<StackPanel Margin="18" Gap="4" Width="200" HorizontalAlignment="Left">
<StackPanel Margin="18" Spacing="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"/>
@ -68,11 +68,11 @@
<TextBlock Text="{Binding StringValue}"/>
</DataTemplate>
</StackPanel.DataTemplates>
<StackPanel Margin="18" Gap="4" Width="200">
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Multiple"/>
<ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/>
</StackPanel>
<StackPanel Margin="18" Gap="4" Width="200">
<StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Multiple"/>
<ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/>
</StackPanel>
@ -87,16 +87,16 @@
</TabItem>
<TabItem Header="Property Validation">
<StackPanel Orientation="Horizontal">
<StackPanel Margin="18" Gap="4" MinWidth="200" DataContext="{Binding ExceptionDataValidation}">
<StackPanel Margin="18" Spacing="4" MinWidth="200" DataContext="{Binding ExceptionDataValidation}">
<TextBlock FontSize="16" Text="Exception Validation"/>
<TextBox Watermark="Less Than 10" UseFloatingWatermark="True" Text="{Binding Path=LessThan10}"/>
</StackPanel>
<StackPanel Margin="18" Gap="4" MinWidth="200" DataContext="{Binding IndeiDataValidation}">
<StackPanel Margin="18" Spacing="4" MinWidth="200" DataContext="{Binding IndeiDataValidation}">
<TextBlock FontSize="16" Text="INotifyDataErrorInfo Validation"/>
<TextBox Watermark="Maximum" UseFloatingWatermark="True" Text="{Binding Path=Maximum}"/>
<TextBox Watermark="Value" UseFloatingWatermark="True" Text="{Binding Path=Value}"/>
</StackPanel>
<StackPanel Margin="18" Gap="4" MinWidth="200" DataContext="{Binding DataAnnotationsValidation}">
<StackPanel Margin="18" Spacing="4" MinWidth="200" DataContext="{Binding DataAnnotationsValidation}">
<TextBlock FontSize="16" Text="Data Annotations Validation"/>
<TextBox Watermark="Phone #" UseFloatingWatermark="True" Text="{Binding PhoneNumber}"/>
<TextBox Watermark="Less Than 10" UseFloatingWatermark="True" Text="{Binding Path=LessThan10}"/>
@ -104,7 +104,7 @@
</StackPanel>
</TabItem>
<TabItem Header="Commands">
<StackPanel Margin="18" Gap="4" Width="200">
<StackPanel Margin="18" Spacing="4" Width="200">
<Button Content="Button" Command="{Binding StringValueCommand}" CommandParameter="Button"/>
<ToggleButton Content="ToggleButton" IsChecked="{Binding BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="ToggleButton"/>
<CheckBox Content="CheckBox" IsChecked="{Binding !BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="CheckBox"/>
@ -114,4 +114,4 @@
</StackPanel>
</TabItem>
</TabControl>
</Window>
</Window>

4
samples/BindingTest/MainWindow.xaml.cs → samples/BindingDemo/MainWindow.xaml.cs

@ -1,9 +1,9 @@
using BindingTest.ViewModels;
using BindingDemo.ViewModels;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace BindingTest
namespace BindingDemo
{
public class MainWindow : Window
{

0
samples/BindingTest/TestItemView.xaml → samples/BindingDemo/TestItemView.xaml

2
samples/BindingTest/TestItemView.xaml.cs → samples/BindingDemo/TestItemView.xaml.cs

@ -1,7 +1,7 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace BindingTest
namespace BindingDemo
{
public class TestItemView : UserControl
{

2
samples/BindingTest/ViewModels/DataAnnotationsErrorViewModel.cs → samples/BindingDemo/ViewModels/DataAnnotationsErrorViewModel.cs

@ -3,7 +3,7 @@
using System.ComponentModel.DataAnnotations;
namespace BindingTest.ViewModels
namespace BindingDemo.ViewModels
{
public class DataAnnotationsErrorViewModel
{

2
samples/BindingTest/ViewModels/ExceptionErrorViewModel.cs → samples/BindingDemo/ViewModels/ExceptionErrorViewModel.cs

@ -4,7 +4,7 @@
using ReactiveUI;
using System;
namespace BindingTest.ViewModels
namespace BindingDemo.ViewModels
{
public class ExceptionErrorViewModel : ReactiveObject
{

2
samples/BindingTest/ViewModels/IndeiErrorViewModel.cs → samples/BindingDemo/ViewModels/IndeiErrorViewModel.cs

@ -6,7 +6,7 @@ using System;
using System.ComponentModel;
using System.Collections;
namespace BindingTest.ViewModels
namespace BindingDemo.ViewModels
{
public class IndeiErrorViewModel : ReactiveObject, INotifyDataErrorInfo
{

2
samples/BindingTest/ViewModels/MainWindowViewModel.cs → samples/BindingDemo/ViewModels/MainWindowViewModel.cs

@ -6,7 +6,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Threading;
namespace BindingTest.ViewModels
namespace BindingDemo.ViewModels
{
public class MainWindowViewModel : ReactiveObject
{

2
samples/BindingTest/ViewModels/NestedCommandViewModel.cs → samples/BindingDemo/ViewModels/NestedCommandViewModel.cs

@ -6,7 +6,7 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BindingTest.ViewModels
namespace BindingDemo.ViewModels
{
public class NestedCommandViewModel : ReactiveObject
{

2
samples/BindingTest/ViewModels/TestItem.cs → samples/BindingDemo/ViewModels/TestItem.cs

@ -1,6 +1,6 @@
using ReactiveUI;
namespace BindingTest.ViewModels
namespace BindingDemo.ViewModels
{
public class TestItem : ReactiveObject
{

4
samples/ControlCatalog.NetCore/Program.cs

@ -1,9 +1,9 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia;
using Avalonia.Skia;
namespace ControlCatalog.NetCore
{
@ -37,7 +37,7 @@ namespace ControlCatalog.NetCore
/// This method is needed for IDE previewer infrastructure
/// </summary>
public static AppBuilder BuildAvaloniaApp()
=> AppBuilder.Configure<App>().UsePlatformDetect().UseReactiveUI();
=> AppBuilder.Configure<App>().UsePlatformDetect().UseSkia().UseReactiveUI();
static void ConsoleSilencer()
{

3
samples/ControlCatalog.iOS/ControlCatalog.iOS.csproj

@ -174,6 +174,5 @@
<Name>ControlCatalog</Name>
</ProjectReference>
</ItemGroup>
<Import Project="..\..\build\Sprache.props" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
</Project>
</Project>

6
samples/ControlCatalog/Pages/AutoCompleteBoxPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">AutoCompleteBox</TextBlock>
<TextBlock Classes="h2">A control into which the user can input text</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="8">
Spacing="8">
<StackPanel Orientation="Vertical">
<TextBlock Text="MinimumPrefixLength: 1"/>
<AutoCompleteBox Width="200"
@ -56,4 +56,4 @@
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/BorderPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Border</TextBlock>
<TextBlock Classes="h2">A control which decorates a child with a border and background</TextBlock>
<StackPanel Orientation="Vertical"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16">
<TextBlock>Border</TextBlock>
</Border>
@ -29,4 +29,4 @@
</Border>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

10
samples/ControlCatalog/Pages/ButtonPage.xaml

@ -1,14 +1,14 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Button</TextBlock>
<TextBlock Classes="h2">A button control</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
<StackPanel Orientation="Vertical" Gap="8" Width="150">
Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8" Width="150">
<Button>Button</Button>
<Button Foreground="White">Foreground</Button>
<Button Background="{DynamicResource ThemeAccentBrush}">Background</Button>
@ -25,7 +25,7 @@
</Button>
</StackPanel>
<StackPanel Orientation="Vertical" Gap="8" Width="150">
<StackPanel Orientation="Vertical" Spacing="8" Width="150">
<Button BorderThickness="0">No Border</Button>
<Button BorderBrush="{DynamicResource ThemeAccentBrush}">Border Color</Button>
<Button BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="4">Thick Border</Button>
@ -33,4 +33,4 @@
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml

@ -1,11 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">ButtonSpinner</TextBlock>
<TextBlock Classes="h2">The ButtonSpinner control allows you to add button spinners to any element and then respond to the Spin event to manipulate that element.</TextBlock>
<StackPanel Orientation="Vertical" Gap="8" Width="200" Margin="0,20,0,0">
<StackPanel Orientation="Vertical" Spacing="8" Width="200" Margin="0,20,0,0">
<CheckBox Name="allowSpinCheck" IsChecked="True">AllowSpin</CheckBox>
<CheckBox Name="showSpinCheck" IsChecked="True">ShowButtonSpinner</CheckBox>
<ButtonSpinner Spin="OnSpin" Height="30"
@ -21,4 +21,4 @@
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/CalendarPage.xaml

@ -1,13 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Calendar</TextBlock>
<TextBlock Classes="h2">A calendar control for selecting dates</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<StackPanel Orientation="Vertical">
<TextBlock Text="SelectionMode: None"/>
<Calendar SelectionMode="None"
@ -44,4 +44,4 @@
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

4
samples/ControlCatalog/Pages/CanvasPage.xaml

@ -1,5 +1,5 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Canvas</TextBlock>
<TextBlock Classes="h2">A panel which lays out its children by explicit coordinates</TextBlock>
<Canvas Background="Yellow" Width="300" Height="400">
@ -31,4 +31,4 @@
<Polyline Points="0,0 65,0 78,-26 91,39 104,-39 117,13 130,0 195,0" Stroke="Brown" Canvas.Left="30" Canvas.Top="350"/>
</Canvas>
</StackPanel>
</UserControl>
</UserControl>

10
samples/ControlCatalog/Pages/CarouselPage.xaml

@ -1,9 +1,9 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Carousel</TextBlock>
<TextBlock Classes="h2">An items control that displays its items as pages that fill the control.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Gap="8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Spacing="8">
<Button Name="left" VerticalAlignment="Center" Padding="20">
<Path Data="M20,11V13H8L13.5,18.5L12.08,19.92L4.16,12L12.08,4.08L13.5,5.5L8,11H20Z" Fill="Black"/>
</Button>
@ -20,7 +20,7 @@
</Button>
</StackPanel>
<StackPanel Orientation="Horizontal" Gap="4">
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBlock VerticalAlignment="Center">Transition</TextBlock>
<DropDown Name="transition" SelectedIndex="1" VerticalAlignment="Center">
<DropDownItem>None</DropDownItem>
@ -29,7 +29,7 @@
</DropDown>
</StackPanel>
<StackPanel Orientation="Horizontal" Gap="4">
<StackPanel Orientation="Horizontal" Spacing="4">
<TextBlock VerticalAlignment="Center">Orientation</TextBlock>
<DropDown Name="orientation" SelectedIndex="1" VerticalAlignment="Center">
<DropDownItem>Horizontal</DropDownItem>
@ -38,4 +38,4 @@
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

10
samples/ControlCatalog/Pages/CheckBoxPage.xaml

@ -1,15 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">CheckBox</TextBlock>
<TextBlock Classes="h2">A check box control</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<StackPanel Orientation="Vertical"
Gap="16">
Spacing="16">
<CheckBox>Unchecked</CheckBox>
<CheckBox IsChecked="True">Checked</CheckBox>
<CheckBox IsChecked="{x:Null}">Indeterminate</CheckBox>
@ -17,7 +17,7 @@
</StackPanel>
<StackPanel Orientation="Vertical"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<CheckBox IsChecked="False" IsThreeState="True">Three State: Unchecked</CheckBox>
<CheckBox IsChecked="True" IsThreeState="True">Three State: Checked</CheckBox>
<CheckBox IsChecked="{x:Null}" IsThreeState="True">Three State: Indeterminate</CheckBox>
@ -25,4 +25,4 @@
</StackPanel>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/ContextMenuPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Context Menu</TextBlock>
<TextBlock Classes="h2">A right click menu that can be applied to any control.</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<Border Background="{DynamicResource ThemeAccentBrush}"
Padding="48,48,48,48">
<Border.ContextMenu>
@ -33,4 +33,4 @@
</Border>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/DatePickerPage.xaml

@ -1,13 +1,13 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">DatePicker</TextBlock>
<TextBlock Classes="h2">A control for selecting dates with a calendar drop-down</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<StackPanel Orientation="Vertical"
Width="200">
<TextBlock Text="SelectedDateFormat: Short"/>
@ -43,4 +43,4 @@
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

4
samples/ControlCatalog/Pages/DialogsPage.xaml

@ -1,5 +1,5 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4" Margin="4">
<StackPanel Orientation="Vertical" Spacing="4" Margin="4">
<Button Name="OpenFile">Open File</Button>
<Button Name="SaveFile">Save File</Button>
<Button Name="SelectFolder">Select Folder</Button>
@ -9,4 +9,4 @@
</StackPanel>
<Button Name="DecoratedWindow">Decorated window</Button>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/DragAndDropPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Drag+Drop</TextBlock>
<TextBlock Classes="h2">Example of Drag+Drop capabilities</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<Border BorderBrush="{DynamicResource ThemeAccentBrush}" BorderThickness="2" Padding="16" Name="DragMe">
<TextBlock Name="DragState">Drag Me</TextBlock>
</Border>
@ -16,4 +16,4 @@
</Border>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/DropDownPage.xaml

@ -1,9 +1,9 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">DropDown</TextBlock>
<TextBlock Classes="h2">A drop-down list.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Gap="8">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Spacing="8">
<DropDown SelectedIndex="0">
<DropDownItem>Inline Items</DropDownItem>
<DropDownItem>Inline Item 2</DropDownItem>
@ -28,4 +28,4 @@
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

6
samples/ControlCatalog/Pages/ExpanderPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Expander</TextBlock>
<TextBlock Classes="h2">Expands to show nested content</TextBlock>
<StackPanel Orientation="Vertical"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<Expander Header="Expand Up" ExpandDirection="Up">
<StackPanel>
<TextBlock>Expanded content</TextBlock>
@ -29,4 +29,4 @@
</Expander>
</StackPanel>
</StackPanel>
</UserControl>
</UserControl>

4
samples/ControlCatalog/Pages/ImagePage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Image</TextBlock>
<TextBlock Classes="h2">Displays an image</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<StackPanel Orientation="Vertical">
<TextBlock>No Stretch</TextBlock>
<Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg"

4
samples/ControlCatalog/Pages/MenuPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Menu</TextBlock>
<TextBlock Classes="h2">A window menu</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<Menu>
<MenuItem Header="_First">
<MenuItem Header="Standard _Menu Item"/>

6
samples/ControlCatalog/Pages/NumericUpDownPage.xaml

@ -1,6 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Margin="2" Classes="h1">Numeric up-down control</TextBlock>
<TextBlock Margin="2" Classes="h2" TextWrapping="Wrap">Numeric up-down control provides a TextBox with button spinners that allow incrementing and decrementing numeric values by using the spinner buttons, keyboard up/down arrows, or mouse wheel.</TextBlock>
@ -26,7 +26,7 @@
VerticalAlignment="Center" Margin="2">
<DropDown.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Gap="2">
<StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="-"/>
<TextBlock Text="{Binding Value}"/>
@ -69,7 +69,7 @@
</Grid>
</Grid>
<StackPanel Margin="2,10,2,2" Orientation="Horizontal" Gap="10">
<StackPanel Margin="2,10,2,2" Orientation="Horizontal" Spacing="10">
<TextBlock FontSize="14" FontWeight="Bold" VerticalAlignment="Center">Usage of NumericUpDown:</TextBlock>
<NumericUpDown Name="upDown" Minimum="0" Maximum="10" Increment="0.5"
CultureInfo="en-US" VerticalAlignment="Center" Height="25" Width="100"

6
samples/ControlCatalog/Pages/ProgressBarPage.xaml

@ -1,5 +1,5 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">ProgressBar</TextBlock>
<TextBlock Classes="h2">A progress bar control</TextBlock>
@ -7,8 +7,8 @@
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
<StackPanel Gap="16">
Spacing="16">
<StackPanel Spacing="16">
<ProgressBar Value="{Binding #hprogress.Value}" />
<ProgressBar IsIndeterminate="True"/>
</StackPanel>

8
samples/ControlCatalog/Pages/RadioButtonPage.xaml

@ -1,22 +1,22 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">RadioButton</TextBlock>
<TextBlock Classes="h2">Allows the selection of a single option of many</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<StackPanel Orientation="Vertical"
Gap="16">
Spacing="16">
<RadioButton IsChecked="True">Option 1</RadioButton>
<RadioButton>Option 2</RadioButton>
<RadioButton IsChecked="{x:Null}">Option 3</RadioButton>
<RadioButton IsEnabled="False">Disabled</RadioButton>
</StackPanel>
<StackPanel Orientation="Vertical"
Gap="16">
Spacing="16">
<RadioButton IsChecked="True" IsThreeState="True">Three States: Option 1</RadioButton>
<RadioButton IsChecked="False" IsThreeState="True">Three States: Option 2</RadioButton>
<RadioButton IsChecked="{x:Null}" IsThreeState="True">Three States: Option 3</RadioButton>

4
samples/ControlCatalog/Pages/SliderPage.xaml

@ -1,9 +1,9 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Slider</TextBlock>
<TextBlock Classes="h2">A control that lets the user select from a range of values by moving a Thumb control along a Track.</TextBlock>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Gap="16">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 16 0 0" Spacing="16">
<Slider Value="0"
Minimum="0"
Maximum="100"

11
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -1,14 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">TextBox</TextBlock>
<TextBlock Classes="h2">A control into which the user can input text</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
<StackPanel Orientation="Vertical" Gap="8">
Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8">
<TextBox Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit." Width="200" />
<TextBox Watermark="ReadOnly" IsReadOnly="True" Text="This is read only"/>
<TextBox Width="200" Watermark="Watermark" />
<TextBox Width="200"
Watermark="Floating Watermark"
@ -25,13 +26,13 @@
<TextBox Width="200" Text="Right aligned text" TextAlignment="Right" />
</StackPanel>
<StackPanel Orientation="Vertical" Gap="8">
<StackPanel Orientation="Vertical" Spacing="8">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Width="200" Height="125"
Text="Multiline TextBox with TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
<TextBox AcceptsReturn="True" Width="200" Height="125"
Text="Multiline TextBox with no TextWrapping.&#xD;&#xD;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus magna. Cras in mi at felis aliquet congue. Ut a est eget ligula molestie gravida. Curabitur massa. Donec eleifend, libero at sagittis mollis, tellus est malesuada tellus, at luctus turpis elit sit amet quam. Vivamus pretium ornare est." />
</StackPanel>
<StackPanel Orientation="Vertical" Gap="8">
<StackPanel Orientation="Vertical" Spacing="8">
<TextBox Width="200" Text="Custom font regular" FontWeight="Normal" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font bold" FontWeight="Bold" FontStyle="Normal" FontFamily="resm:ControlCatalog.Assets.Fonts?assembly=ControlCatalog#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="resm:ControlCatalog.Assets.Fonts.SourceSansPro-Italic.ttf?assembly=ControlCatalog#Source Sans Pro"/>

2
samples/ControlCatalog/Pages/ToolTipPage.xaml

@ -1,6 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical"
Gap="4">
Spacing="4">
<TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</TextBlock>

4
samples/ControlCatalog/Pages/TreeViewPage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4">
<StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">TreeView</TextBlock>
<TextBlock Classes="h2">Displays a hierachical tree of data.</TextBlock>
<StackPanel Orientation="Horizontal"
Margin="0,16,0,0"
HorizontalAlignment="Center"
Gap="16">
Spacing="16">
<TreeView Items="{Binding}" Width="250" Height="350">
<TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}">

4
samples/ControlCatalog/SideBar.xaml

@ -8,7 +8,7 @@
<TabStrip Name="PART_TabStrip"
MemberSelector="{x:Static TabControl.HeaderSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex, Mode=TwoWay}">
SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabStrip.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
@ -20,7 +20,7 @@
Margin="8 0 0 0"
MemberSelector="{x:Static TabControl.ContentSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex}"
SelectedIndex="{TemplateBinding SelectedIndex}"
PageTransition="{TemplateBinding PageTransition}"
Grid.Row="1"/>
</DockPanel>

2
samples/RemoteTest/Program.cs → samples/RemoteDemo/Program.cs

@ -9,7 +9,7 @@ using Avalonia.Remote.Protocol;
using Avalonia.Threading;
using ControlCatalog;
namespace RemoteTest
namespace RemoteDemo
{
class Program
{

0
samples/RemoteTest/RemoteTest.csproj → samples/RemoteDemo/RemoteDemo.csproj

0
samples/RenderTest/App.config → samples/RenderDemo/App.config

2
samples/RenderTest/App.xaml → samples/RenderDemo/App.xaml

@ -2,6 +2,6 @@
<Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:RenderTest.SideBar.xaml"/>
<StyleInclude Source="resm:RenderDemo.SideBar.xaml"/>
</Application.Styles>
</Application>

2
samples/RenderTest/App.xaml.cs → samples/RenderDemo/App.xaml.cs

@ -5,7 +5,7 @@ using Avalonia;
using Avalonia.Logging.Serilog;
using Avalonia.Markup.Xaml;
namespace RenderTest
namespace RenderDemo
{
public class App : Application
{

2
samples/RenderTest/MainWindow.xaml → samples/RenderDemo/MainWindow.xaml

@ -1,6 +1,6 @@
<Window xmlns="https://github.com/avaloniaui"
Title="AvaloniaUI Rendering Test"
xmlns:pages="clr-namespace:RenderTest.Pages"
xmlns:pages="clr-namespace:RenderDemo.Pages"
Width="800"
Height="600">
<DockPanel>

4
samples/RenderTest/MainWindow.xaml.cs → samples/RenderDemo/MainWindow.xaml.cs

@ -5,10 +5,10 @@ using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using RenderTest.ViewModels;
using RenderDemo.ViewModels;
using ReactiveUI;
namespace RenderTest
namespace RenderDemo
{
public class MainWindow : Window
{

0
samples/RenderTest/Pages/AnimationsPage.xaml → samples/RenderDemo/Pages/AnimationsPage.xaml

4
samples/RenderTest/Pages/AnimationsPage.xaml.cs → samples/RenderDemo/Pages/AnimationsPage.xaml.cs

@ -7,9 +7,9 @@ using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using RenderTest.ViewModels;
using RenderDemo.ViewModels;
namespace RenderTest.Pages
namespace RenderDemo.Pages
{
public class AnimationsPage : UserControl
{

0
samples/RenderTest/Pages/ClippingPage.xaml → samples/RenderDemo/Pages/ClippingPage.xaml

2
samples/RenderTest/Pages/ClippingPage.xaml.cs → samples/RenderDemo/Pages/ClippingPage.xaml.cs

@ -7,7 +7,7 @@ using Avalonia.Data;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
namespace RenderTest.Pages
namespace RenderDemo.Pages
{
public class ClippingPage : UserControl
{

0
samples/RenderTest/Pages/DrawingPage.xaml → samples/RenderDemo/Pages/DrawingPage.xaml

2
samples/RenderTest/Pages/DrawingPage.xaml.cs → samples/RenderDemo/Pages/DrawingPage.xaml.cs

@ -1,7 +1,7 @@
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
namespace RenderTest.Pages
namespace RenderDemo.Pages
{
public class DrawingPage : UserControl
{

0
samples/RenderTest/RenderTest.csproj → samples/RenderDemo/RenderDemo.csproj

4
samples/RenderTest/SideBar.xaml → samples/RenderDemo/SideBar.xaml

@ -9,7 +9,7 @@
<TabStrip Name="PART_TabStrip"
MemberSelector="{x:Static TabControl.HeaderSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex, Mode=TwoWay}">
SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabStrip.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/>
@ -21,7 +21,7 @@
Margin="8 0 0 0"
MemberSelector="{x:Static TabControl.ContentSelector}"
Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex}"
SelectedIndex="{TemplateBinding SelectedIndex}"
PageTransition="{TemplateBinding PageTransition}"
Grid.Row="1"/>
</DockPanel>

2
samples/RenderTest/ViewModels/AnimationsPageViewModel.cs → samples/RenderDemo/ViewModels/AnimationsPageViewModel.cs

@ -2,7 +2,7 @@
using ReactiveUI;
using Avalonia.Animation;
namespace RenderTest.ViewModels
namespace RenderDemo.ViewModels
{
public class AnimationsPageViewModel : ReactiveObject
{

2
samples/RenderTest/ViewModels/MainWindowViewModel.cs → samples/RenderDemo/ViewModels/MainWindowViewModel.cs

@ -1,7 +1,7 @@
using System;
using ReactiveUI;
namespace RenderTest.ViewModels
namespace RenderDemo.ViewModels
{
public class MainWindowViewModel : ReactiveObject
{

0
samples/VirtualizationTest/App.config → samples/VirtualizationDemo/App.config

0
samples/VirtualizationTest/App.xaml → samples/VirtualizationDemo/App.xaml

2
samples/VirtualizationTest/App.xaml.cs → samples/VirtualizationDemo/App.xaml.cs

@ -4,7 +4,7 @@
using Avalonia;
using Avalonia.Markup.Xaml;
namespace VirtualizationTest
namespace VirtualizationDemo
{
public class App : Application
{

2
samples/VirtualizationTest/MainWindow.xaml → samples/VirtualizationDemo/MainWindow.xaml

@ -6,7 +6,7 @@
<StackPanel DockPanel.Dock="Right"
Margin="16 0 0 0"
MinWidth="150"
Gap="4">
Spacing="4">
<DropDown Items="{Binding VirtualizationModes}"
SelectedItem="{Binding VirtualizationMode}"/>
<DropDown Items="{Binding Orientations}"

4
samples/VirtualizationTest/MainWindow.xaml.cs → samples/VirtualizationDemo/MainWindow.xaml.cs

@ -4,9 +4,9 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using VirtualizationTest.ViewModels;
using VirtualizationDemo.ViewModels;
namespace VirtualizationTest
namespace VirtualizationDemo
{
public class MainWindow : Window
{

2
samples/VirtualizationTest/Program.cs → samples/VirtualizationDemo/Program.cs

@ -7,7 +7,7 @@ using Avalonia.Controls;
using Avalonia.Logging.Serilog;
using Serilog;
namespace VirtualizationTest
namespace VirtualizationDemo
{
class Program
{

2
samples/VirtualizationTest/ViewModels/ItemViewModel.cs → samples/VirtualizationDemo/ViewModels/ItemViewModel.cs

@ -4,7 +4,7 @@
using System;
using ReactiveUI;
namespace VirtualizationTest.ViewModels
namespace VirtualizationDemo.ViewModels
{
internal class ItemViewModel : ReactiveObject
{

2
samples/VirtualizationTest/ViewModels/MainWindowViewModel.cs → samples/VirtualizationDemo/ViewModels/MainWindowViewModel.cs

@ -9,7 +9,7 @@ using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using ReactiveUI;
namespace VirtualizationTest.ViewModels
namespace VirtualizationDemo.ViewModels
{
internal class MainWindowViewModel : ReactiveObject
{

0
samples/VirtualizationTest/VirtualizationTest.csproj → samples/VirtualizationDemo/VirtualizationDemo.csproj

2
src/Android/Avalonia.AndroidTestApplication/Avalonia.AndroidTestApplication.csproj

@ -150,6 +150,6 @@
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\..\..\build\Serilog.props" />
<Import Project="..\..\..\build\Sprache.props" />
<Import Project="..\..\..\build\Rx.props" />
<Import Project="..\..\..\build\System.Memory.props" />
</Project>

126
src/Avalonia.Animation/Animation.cs

@ -10,13 +10,16 @@ using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.Linq;
using System.Threading.Tasks;
using System.Reactive.Linq;
using System.Reactive.Disposables;
namespace Avalonia.Animation
{
/// <summary>
/// Tracks the progress of an animation.
/// </summary>
public class Animation : AvaloniaList<KeyFrame>, IDisposable, IAnimation
public class Animation : AvaloniaList<KeyFrame>, IAnimation
{
private readonly static List<(Func<AvaloniaProperty, bool> Condition, Type Animator)> Animators = new List<(Func<AvaloniaProperty, bool>, Type)>
{
@ -24,7 +27,7 @@ namespace Avalonia.Animation
};
public static void RegisterAnimator<TAnimator>(Func<AvaloniaProperty, bool> condition)
where TAnimator: IAnimator
where TAnimator : IAnimator
{
Animators.Insert(0, (condition, typeof(TAnimator)));
}
@ -41,8 +44,6 @@ namespace Avalonia.Animation
return null;
}
private bool _isChildrenChanged = false;
private List<IDisposable> _subscription = new List<IDisposable>();
public AvaloniaList<IAnimator> _animators { get; set; } = new AvaloniaList<IAnimator>();
/// <summary>
@ -68,22 +69,18 @@ namespace Avalonia.Animation
/// <summary>
/// The value fill mode for this animation.
/// </summary>
public FillMode FillMode { get; set; }
public FillMode FillMode { get; set; }
/// <summary>
/// Easing function to be used.
/// </summary>
/// </summary>
public Easing Easing { get; set; } = new LinearEasing();
public Animation()
{
this.CollectionChanged += delegate { _isChildrenChanged = true; };
}
private void InterpretKeyframes()
private (IList<IAnimator> Animators, IList<IDisposable> subscriptions) InterpretKeyframes(Animatable control)
{
var handlerList = new List<(Type, AvaloniaProperty)>();
var kfList = new List<AnimatorKeyFrame>();
var handlerList = new List<(Type type, AvaloniaProperty property)>();
var animatorKeyFrames = new List<AnimatorKeyFrame>();
var subscriptions = new List<IDisposable>();
foreach (var keyframe in this)
{
@ -99,68 +96,87 @@ namespace Avalonia.Animation
if (!handlerList.Contains((handler, setter.Property)))
handlerList.Add((handler, setter.Property));
var newKF = new AnimatorKeyFrame()
var cue = keyframe.Cue;
if (keyframe.TimingMode == KeyFrameTimingMode.TimeSpan)
{
Handler = handler,
Property = setter.Property,
Cue = keyframe.Cue,
KeyTime = keyframe.KeyTime,
timeSpanSet = keyframe.timeSpanSet,
cueSet = keyframe.cueSet,
Value = setter.Value
};
kfList.Add(newKF);
cue = new Cue(keyframe.KeyTime.Ticks / Duration.Ticks);
}
var newKF = new AnimatorKeyFrame(handler, cue);
subscriptions.Add(newKF.BindSetter(setter, control));
animatorKeyFrames.Add(newKF);
}
}
var newAnimatorInstances = new List<(Type handler, AvaloniaProperty prop, IAnimator inst)>();
var newAnimatorInstances = new List<IAnimator>();
foreach (var handler in handlerList)
foreach (var (handlerType, property) in handlerList)
{
var newInstance = (IAnimator)Activator.CreateInstance(handler.Item1);
newInstance.Property = handler.Item2;
newAnimatorInstances.Add((handler.Item1, handler.Item2, newInstance));
var newInstance = (IAnimator)Activator.CreateInstance(handlerType);
newInstance.Property = property;
newAnimatorInstances.Add(newInstance);
}
foreach (var kf in kfList)
foreach (var keyframe in animatorKeyFrames)
{
var parent = newAnimatorInstances.Where(p => p.handler == kf.Handler &&
p.prop == kf.Property)
.First();
parent.inst.Add(kf);
var animator = newAnimatorInstances.First(a => a.GetType() == keyframe.AnimatorType &&
a.Property == keyframe.Property);
animator.Add(keyframe);
}
foreach(var instance in newAnimatorInstances)
_animators.Add(instance.inst);
return (newAnimatorInstances, subscriptions);
}
/// <summary>
/// Cancels the animation.
/// </summary>
public void Dispose()
/// <inheritdocs/>
public IDisposable Apply(Animatable control, IObservable<bool> match, Action onComplete)
{
foreach (var sub in _subscription)
var (animators, subscriptions) = InterpretKeyframes(control);
if (animators.Count == 1)
{
subscriptions.Add(animators[0].Apply(this, control, match, onComplete));
}
else
{
sub.Dispose();
var completionTasks = onComplete != null ? new List<Task>() : null;
foreach (IAnimator animator in animators)
{
Action animatorOnComplete = null;
if (onComplete != null)
{
var tcs = new TaskCompletionSource<object>();
animatorOnComplete = () => tcs.SetResult(null);
completionTasks.Add(tcs.Task);
}
subscriptions.Add(animator.Apply(this, control, match, animatorOnComplete));
}
if (onComplete != null)
{
Task.WhenAll(completionTasks).ContinueWith(_ => onComplete());
}
}
return new CompositeDisposable(subscriptions);
}
/// <inheritdocs/>
public IDisposable Apply(Animatable control, IObservable<bool> matchObs)
public Task RunAsync(Animatable control)
{
if (_isChildrenChanged)
{
InterpretKeyframes();
_isChildrenChanged = false;
}
var run = new TaskCompletionSource<object>();
foreach (IAnimator keyframes in _animators)
if (this.RepeatCount == RepeatCount.Loop)
run.SetException(new InvalidOperationException("Looping animations must not use the Run method."));
IDisposable subscriptions = null;
subscriptions = this.Apply(control, Observable.Return(true), () =>
{
_subscription.Add(keyframes.Apply(this, control, matchObs));
}
return this;
run.SetResult(null);
subscriptions?.Dispose();
});
return run.Task;
}
}
}
}

66
src/Avalonia.Animation/AnimatorKeyFrame.cs

@ -4,6 +4,8 @@ using System.Text;
using System.ComponentModel;
using Avalonia.Metadata;
using Avalonia.Collections;
using Avalonia.Data;
using Avalonia.Reactive;
namespace Avalonia.Animation
{
@ -11,13 +13,63 @@ namespace Avalonia.Animation
/// Defines a KeyFrame that is used for
/// <see cref="Animator{T}"/> objects.
/// </summary>
public class AnimatorKeyFrame
public class AnimatorKeyFrame : AvaloniaObject
{
public Type Handler;
public Cue Cue;
public TimeSpan KeyTime;
internal bool timeSpanSet, cueSet;
public AvaloniaProperty Property;
public object Value;
public static readonly DirectProperty<AnimatorKeyFrame, object> ValueProperty =
AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object>(nameof(Value), k => k.Value, (k, v) => k.Value = v);
public AnimatorKeyFrame()
{
}
public AnimatorKeyFrame(Type animatorType, Cue cue)
{
AnimatorType = animatorType;
Cue = cue;
}
public Type AnimatorType { get; }
public Cue Cue { get; }
public AvaloniaProperty Property { get; private set; }
private object _value;
public object Value
{
get => _value;
set => SetAndRaise(ValueProperty, ref _value, value);
}
public IDisposable BindSetter(IAnimationSetter setter, Animatable targetControl)
{
Property = setter.Property;
var value = setter.Value;
if (value is IBinding binding)
{
return this.Bind(ValueProperty, binding, targetControl);
}
else
{
return this.Bind(ValueProperty, ObservableEx.SingleValue(value).ToBinding(), targetControl);
}
}
public T GetTypedValue<T>()
{
var typeConv = TypeDescriptor.GetConverter(typeof(T));
if (Value == null)
{
throw new ArgumentNullException($"KeyFrame value can't be null.");
}
if (!typeConv.CanConvertTo(Value.GetType()))
{
throw new InvalidCastException($"KeyFrame value doesnt match property type.");
}
return (T)typeConv.ConvertTo(Value, typeof(T));
}
}
}

191
src/Avalonia.Animation/AnimatorStateMachine`1.cs

@ -35,6 +35,7 @@ namespace Avalonia.Animation
private T _neutralValue;
internal bool _unsubscribe = false;
private IObserver<object> _targetObserver;
private readonly Action _onComplete;
[Flags]
private enum KeyFramesStates
@ -51,9 +52,9 @@ namespace Avalonia.Animation
Disposed
}
public void Initialize(Animation animation, Animatable control, Animator<T> keyframes)
public AnimatorStateMachine(Animation animation, Animatable control, Animator<T> animator, Action onComplete)
{
_parent = keyframes;
_parent = animator;
_targetAnimation = animation;
_targetControl = control;
_neutralValue = (T)_targetControl.GetValue(_parent.Property);
@ -82,6 +83,7 @@ namespace Avalonia.Animation
_currentState = KeyFramesStates.DoDelay;
else
_currentState = KeyFramesStates.DoRun;
_onComplete = onComplete;
}
public void Step(PlayState _playState, Func<double, T, T> Interpolator)
@ -123,121 +125,136 @@ namespace Avalonia.Animation
double _tempDuration = 0d, _easedTime;
checkstate:
switch (_currentState)
bool handled = false;
while (!handled)
{
case KeyFramesStates.DoDelay:
switch (_currentState)
{
case KeyFramesStates.DoDelay:
if (_fillMode == FillMode.Backward
|| _fillMode == FillMode.Both)
{
if (_currentIteration == 0)
if (_fillMode == FillMode.Backward
|| _fillMode == FillMode.Both)
{
_targetObserver.OnNext(_firstKFValue);
if (_currentIteration == 0)
{
_targetObserver.OnNext(_firstKFValue);
}
else
{
_targetObserver.OnNext(_lastInterpValue);
}
}
if (_delayFrameCount > _delayTotalFrameCount)
{
_currentState = KeyFramesStates.DoRun;
}
else
{
_targetObserver.OnNext(_lastInterpValue);
handled = true;
_delayFrameCount++;
}
}
if (_delayFrameCount > _delayTotalFrameCount)
{
_currentState = KeyFramesStates.DoRun;
goto checkstate;
}
_delayFrameCount++;
break;
case KeyFramesStates.DoRun:
if (_isReversed)
_currentState = KeyFramesStates.RunBackwards;
else
_currentState = KeyFramesStates.RunForwards;
goto checkstate;
case KeyFramesStates.RunForwards:
if (_durationFrameCount > _durationTotalFrameCount)
{
_currentState = KeyFramesStates.RunComplete;
goto checkstate;
}
break;
_tempDuration = (double)_durationFrameCount / _durationTotalFrameCount;
_currentState = KeyFramesStates.RunApplyValue;
case KeyFramesStates.DoRun:
goto checkstate;
if (_isReversed)
_currentState = KeyFramesStates.RunBackwards;
else
_currentState = KeyFramesStates.RunForwards;
case KeyFramesStates.RunBackwards:
break;
if (_durationFrameCount > _durationTotalFrameCount)
{
_currentState = KeyFramesStates.RunComplete;
goto checkstate;
}
case KeyFramesStates.RunForwards:
_tempDuration = (double)(_durationTotalFrameCount - _durationFrameCount) / _durationTotalFrameCount;
_currentState = KeyFramesStates.RunApplyValue;
if (_durationFrameCount > _durationTotalFrameCount)
{
_currentState = KeyFramesStates.RunComplete;
}
else
{
_tempDuration = (double)_durationFrameCount / _durationTotalFrameCount;
_currentState = KeyFramesStates.RunApplyValue;
goto checkstate;
}
break;
case KeyFramesStates.RunApplyValue:
case KeyFramesStates.RunBackwards:
_easedTime = _targetAnimation.Easing.Ease(_tempDuration);
if (_durationFrameCount > _durationTotalFrameCount)
{
_currentState = KeyFramesStates.RunComplete;
}
else
{
_tempDuration = (double)(_durationTotalFrameCount - _durationFrameCount) / _durationTotalFrameCount;
_currentState = KeyFramesStates.RunApplyValue;
}
break;
_durationFrameCount++;
_lastInterpValue = Interpolator(_easedTime, _neutralValue);
_targetObserver.OnNext(_lastInterpValue);
_currentState = KeyFramesStates.DoRun;
case KeyFramesStates.RunApplyValue:
break;
_easedTime = _targetAnimation.Easing.Ease(_tempDuration);
case KeyFramesStates.RunComplete:
_durationFrameCount++;
_lastInterpValue = Interpolator(_easedTime, _neutralValue);
_targetObserver.OnNext(_lastInterpValue);
_currentState = KeyFramesStates.DoRun;
handled = true;
break;
if (_checkLoopAndRepeat)
{
_delayFrameCount = 0;
_durationFrameCount = 0;
case KeyFramesStates.RunComplete:
if (_isLooping)
{
_currentState = KeyFramesStates.DoRun;
}
else if (_isRepeating)
if (_checkLoopAndRepeat)
{
if (_currentIteration >= _repeatCount)
_delayFrameCount = 0;
_durationFrameCount = 0;
if (_isLooping)
{
_currentState = KeyFramesStates.Stop;
_currentState = KeyFramesStates.DoRun;
}
else
else if (_isRepeating)
{
_currentState = KeyFramesStates.DoRun;
if (_currentIteration >= _repeatCount)
{
_currentState = KeyFramesStates.Stop;
}
else
{
_currentState = KeyFramesStates.DoRun;
}
_currentIteration++;
}
_currentIteration++;
}
if (_animationDirection == PlaybackDirection.Alternate
|| _animationDirection == PlaybackDirection.AlternateReverse)
_isReversed = !_isReversed;
if (_animationDirection == PlaybackDirection.Alternate
|| _animationDirection == PlaybackDirection.AlternateReverse)
_isReversed = !_isReversed;
break;
}
_currentState = KeyFramesStates.Stop;
break;
}
_currentState = KeyFramesStates.Stop;
goto checkstate;
case KeyFramesStates.Stop:
case KeyFramesStates.Stop:
if (_fillMode == FillMode.Forward
|| _fillMode == FillMode.Both)
{
_targetControl.SetValue(_parent.Property, _lastInterpValue, BindingPriority.LocalValue);
}
if (_fillMode == FillMode.Forward
|| _fillMode == FillMode.Both)
{
_targetControl.SetValue(_parent.Property, _lastInterpValue, BindingPriority.LocalValue);
}
_targetObserver.OnCompleted();
break;
_targetObserver.OnCompleted();
_onComplete?.Invoke();
Dispose();
handled = true;
break;
default:
handled = true;
break;
}
}
}
@ -253,4 +270,4 @@ namespace Avalonia.Animation
_currentState = KeyFramesStates.Disposed;
}
}
}
}

80
src/Avalonia.Animation/Animator`1.cs

@ -19,7 +19,7 @@ namespace Avalonia.Animation
/// <summary>
/// List of type-converted keyframes.
/// </summary>
private Dictionary<double, (T, bool isNeutral)> _convertedKeyframes = new Dictionary<double, (T, bool)>();
private readonly SortedList<double, (AnimatorKeyFrame, bool isNeutral)> _convertedKeyframes = new SortedList<double, (AnimatorKeyFrame, bool)>();
private bool _isVerfifiedAndConverted;
@ -35,18 +35,17 @@ namespace Avalonia.Animation
}
/// <inheritdoc/>
public virtual IDisposable Apply(Animation animation, Animatable control, IObservable<bool> obsMatch)
public virtual IDisposable Apply(Animation animation, Animatable control, IObservable<bool> obsMatch, Action onComplete)
{
if (!_isVerfifiedAndConverted)
VerifyConvertKeyFrames(animation, typeof(T));
VerifyConvertKeyFrames();
return obsMatch
.Where(p => p == true)
// Ignore triggers when global timers are paused.
.Where(p => Timing.GetGlobalPlayState() != PlayState.Pause)
.Where(p => p && Timing.GetGlobalPlayState() != PlayState.Pause)
.Subscribe(_ =>
{
var timerObs = RunKeyFrames(animation, control);
var timerObs = RunKeyFrames(animation, control, onComplete);
});
}
@ -60,8 +59,8 @@ namespace Avalonia.Animation
/// <param name="t">The time parameter, relative to the total animation time</param>
protected (double IntraKFTime, KeyFramePair<T> KFPair) GetKFPairAndIntraKFTime(double t)
{
KeyValuePair<double, (T, bool)> firstCue, lastCue;
int kvCount = _convertedKeyframes.Count();
KeyValuePair<double, (AnimatorKeyFrame frame, bool isNeutral)> firstCue, lastCue;
int kvCount = _convertedKeyframes.Count;
if (kvCount > 2)
{
if (DoubleUtils.AboutEqual(t, 0.0) || t < 0.0)
@ -76,8 +75,8 @@ namespace Avalonia.Animation
}
else
{
firstCue = _convertedKeyframes.Where(j => j.Key <= t).Last();
lastCue = _convertedKeyframes.Where(j => j.Key >= t).First();
firstCue = _convertedKeyframes.Last(j => j.Key <= t);
lastCue = _convertedKeyframes.First(j => j.Key >= t);
}
}
else
@ -89,26 +88,24 @@ namespace Avalonia.Animation
double t0 = firstCue.Key;
double t1 = lastCue.Key;
var intraframeTime = (t - t0) / (t1 - t0);
return (intraframeTime, new KeyFramePair<T>(firstCue, lastCue));
var firstFrameData = (firstCue.Value.frame.GetTypedValue<T>(), firstCue.Value.isNeutral);
var lastFrameData = (lastCue.Value.frame.GetTypedValue<T>(), lastCue.Value.isNeutral);
return (intraframeTime, new KeyFramePair<T>(firstFrameData, lastFrameData));
}
/// <summary>
/// Runs the KeyFrames Animation.
/// </summary>
private IDisposable RunKeyFrames(Animation animation, Animatable control)
private IDisposable RunKeyFrames(Animation animation, Animatable control, Action onComplete)
{
var _kfStateMach = new AnimatorStateMachine<T>();
_kfStateMach.Initialize(animation, control, this);
var stateMachine = new AnimatorStateMachine<T>(animation, control, this, onComplete);
Timing.AnimationStateTimer
.TakeWhile(_ => !_kfStateMach._unsubscribe)
.Subscribe(p =>
{
_kfStateMach.Step(p, DoInterpolation);
});
.TakeWhile(_ => !stateMachine._unsubscribe)
.Subscribe(p => stateMachine.Step(p, DoInterpolation));
return control.Bind(Property, _kfStateMach, BindingPriority.Animation);
return control.Bind(Property, stateMachine, BindingPriority.Animation);
}
/// <summary>
@ -119,39 +116,19 @@ namespace Avalonia.Animation
/// <summary>
/// Verifies and converts keyframe values according to this class's target type.
/// </summary>
private void VerifyConvertKeyFrames(Animation animation, Type type)
private void VerifyConvertKeyFrames()
{
var typeConv = TypeDescriptor.GetConverter(type);
foreach (AnimatorKeyFrame k in this)
foreach (AnimatorKeyFrame keyframe in this)
{
if (k.Value == null)
{
throw new ArgumentNullException($"KeyFrame value can't be null.");
}
if (!typeConv.CanConvertTo(k.Value.GetType()))
{
throw new InvalidCastException($"KeyFrame value doesnt match property type.");
}
T convertedValue = (T)typeConv.ConvertTo(k.Value, type);
Cue _normalizedCue = k.Cue;
if (k.timeSpanSet)
{
_normalizedCue = new Cue(k.KeyTime.Ticks / animation.Duration.Ticks);
}
_convertedKeyframes.Add(_normalizedCue.CueValue, (convertedValue, false));
_convertedKeyframes.Add(keyframe.Cue.CueValue, (keyframe, false));
}
SortKeyFrameCues(_convertedKeyframes);
AddNeutralKeyFramesIfNeeded();
_isVerfifiedAndConverted = true;
}
private void SortKeyFrameCues(Dictionary<double, (T, bool)> convertedValues)
private void AddNeutralKeyFramesIfNeeded()
{
bool hasStartKey, hasEndKey;
hasStartKey = hasEndKey = false;
@ -170,23 +147,20 @@ namespace Avalonia.Animation
}
if (!hasStartKey || !hasEndKey)
AddNeutralKeyFrames(hasStartKey, hasEndKey, _convertedKeyframes);
_convertedKeyframes = _convertedKeyframes.OrderBy(p => p.Key)
.ToDictionary((k) => k.Key, (v) => v.Value);
AddNeutralKeyFrames(hasStartKey, hasEndKey);
}
private void AddNeutralKeyFrames(bool hasStartKey, bool hasEndKey, Dictionary<double, (T, bool)> convertedKeyframes)
private void AddNeutralKeyFrames(bool hasStartKey, bool hasEndKey)
{
if (!hasStartKey)
{
convertedKeyframes.Add(0.0d, (default(T), true));
_convertedKeyframes.Add(0.0d, (new AnimatorKeyFrame { Value = default(T) }, true));
}
if (!hasEndKey)
{
convertedKeyframes.Add(1.0d, (default(T), true));
_convertedKeyframes.Add(1.0d, (new AnimatorKeyFrame { Value = default(T) }, true));
}
}
}
}
}

2
src/Avalonia.Animation/Cue.cs

@ -10,7 +10,7 @@ namespace Avalonia.Animation
/// A Cue object for <see cref="KeyFrame"/>.
/// </summary>
[TypeConverter(typeof(CueTypeConverter))]
public struct Cue : IEquatable<Cue>, IEquatable<double>
public readonly struct Cue : IEquatable<Cue>, IEquatable<double>
{
/// <summary>
/// The normalized percent value, ranging from 0.0 to 1.0

8
src/Avalonia.Animation/DoubleAnimator.cs

@ -24,15 +24,15 @@ namespace Avalonia.Animation
var firstKF = pair.KFPair.FirstKeyFrame;
var secondKF = pair.KFPair.SecondKeyFrame;
if (firstKF.Value.isNeutral)
if (firstKF.isNeutral)
y0 = neutralValue;
else
y0 = firstKF.Value.TargetValue;
y0 = firstKF.TargetValue;
if (secondKF.Value.isNeutral)
if (secondKF.isNeutral)
y1 = neutralValue;
else
y1 = secondKF.Value.TargetValue;
y1 = secondKF.TargetValue;
// Do linear parametric interpolation
return y0 + (pair.IntraKFTime) * (y1 - y0);

10
src/Avalonia.Animation/IAnimation.cs

@ -1,6 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Animation
{
@ -12,6 +13,11 @@ namespace Avalonia.Animation
/// <summary>
/// Apply the animation to the specified control
/// </summary>
IDisposable Apply(Animatable control, IObservable<bool> match);
IDisposable Apply(Animatable control, IObservable<bool> match, Action onComplete = null);
/// <summary>
/// Run the animation to the specified control
/// </summary>
Task RunAsync(Animatable control);
}
}

2
src/Avalonia.Animation/IAnimationSetter.cs

@ -5,4 +5,4 @@ namespace Avalonia.Animation
AvaloniaProperty Property { get; set; }
object Value { get; set; }
}
}
}

2
src/Avalonia.Animation/IAnimator.cs

@ -17,6 +17,6 @@ namespace Avalonia.Animation
/// <summary>
/// Applies the current KeyFrame group to the specified control.
/// </summary>
IDisposable Apply(Animation animation, Animatable control, IObservable<bool> obsMatch);
IDisposable Apply(Animation animation, Animatable control, IObservable<bool> obsMatch, Action onComplete);
}
}

16
src/Avalonia.Animation/KeyFrame.cs

@ -7,6 +7,11 @@ using Avalonia.Collections;
namespace Avalonia.Animation
{
internal enum KeyFrameTimingMode
{
TimeSpan = 1,
Cue
}
/// <summary>
/// Stores data regarding a specific key
@ -14,7 +19,6 @@ namespace Avalonia.Animation
/// </summary>
public class KeyFrame : AvaloniaList<IAnimationSetter>
{
internal bool timeSpanSet, cueSet;
private TimeSpan _ktimeSpan;
private Cue _kCue;
@ -30,6 +34,8 @@ namespace Avalonia.Animation
{
}
internal KeyFrameTimingMode TimingMode { get; private set; }
/// <summary>
/// Gets or sets the key time of this <see cref="KeyFrame"/>.
/// </summary>
@ -42,11 +48,11 @@ namespace Avalonia.Animation
}
set
{
if (cueSet)
if (TimingMode == KeyFrameTimingMode.Cue)
{
throw new InvalidOperationException($"You can only set either {nameof(KeyTime)} or {nameof(Cue)}.");
}
timeSpanSet = true;
TimingMode = KeyFrameTimingMode.TimeSpan;
_ktimeSpan = value;
}
}
@ -63,11 +69,11 @@ namespace Avalonia.Animation
}
set
{
if (timeSpanSet)
if (TimingMode == KeyFrameTimingMode.TimeSpan)
{
throw new InvalidOperationException($"You can only set either {nameof(KeyTime)} or {nameof(Cue)}.");
}
cueSet = true;
TimingMode = KeyFrameTimingMode.Cue;
_kCue = value;
}
}

8
src/Avalonia.Animation/KeyFramePair`1.cs

@ -22,7 +22,7 @@ namespace Avalonia.Animation
/// </summary>
/// <param name="FirstKeyFrame"></param>
/// <param name="LastKeyFrame"></param>
public KeyFramePair(KeyValuePair<double, (T, bool)> FirstKeyFrame, KeyValuePair<double, (T, bool)> LastKeyFrame) : this()
public KeyFramePair((T TargetValue, bool isNeutral) FirstKeyFrame, (T TargetValue, bool isNeutral) LastKeyFrame) : this()
{
this.FirstKeyFrame = FirstKeyFrame;
this.SecondKeyFrame = LastKeyFrame;
@ -31,11 +31,11 @@ namespace Avalonia.Animation
/// <summary>
/// First <see cref="KeyFrame"/> object.
/// </summary>
public KeyValuePair<double, (T TargetValue, bool isNeutral)> FirstKeyFrame { get; private set; }
public (T TargetValue, bool isNeutral) FirstKeyFrame { get; }
/// <summary>
/// Second <see cref="KeyFrame"/> object.
/// </summary>
public KeyValuePair<double, (T TargetValue, bool isNeutral)> SecondKeyFrame { get; private set; }
public (T TargetValue, bool isNeutral) SecondKeyFrame { get; }
}
}
}

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

@ -8,4 +8,5 @@
<Import Project="..\..\build\Binding.props" />
<Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" />
</Project>
<Import Project="..\..\build\System.Memory.props" />
</Project>

217
src/Avalonia.Base/AvaloniaObject.cs

@ -10,6 +10,7 @@ using System.Reactive.Linq;
using Avalonia.Data;
using Avalonia.Diagnostics;
using Avalonia.Logging;
using Avalonia.Reactive;
using Avalonia.Threading;
using Avalonia.Utilities;
@ -21,24 +22,18 @@ namespace Avalonia
/// <remarks>
/// This class is analogous to DependencyObject in WPF.
/// </remarks>
public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged, IPriorityValueOwner
public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged
{
/// <summary>
/// The parent object that inherited values are inherited from.
/// </summary>
private IAvaloniaObject _inheritanceParent;
/// <summary>
/// The set values/bindings on this object.
/// </summary>
private readonly Dictionary<AvaloniaProperty, PriorityValue> _values =
new Dictionary<AvaloniaProperty, PriorityValue>();
/// <summary>
/// Maintains a list of direct property binding subscriptions so that the binding source
/// doesn't get collected.
/// </summary>
private List<IDisposable> _directBindings;
private List<DirectBindingSubscription> _directBindings;
/// <summary>
/// Event handler for <see cref="INotifyPropertyChanged"/> implementation.
@ -50,20 +45,8 @@ namespace Avalonia
/// </summary>
private EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChanged;
private DeferredSetter<AvaloniaProperty, object> _directDeferredSetter;
/// <summary>
/// Delayed setter helper for direct properties. Used to fix #855.
/// </summary>
private DeferredSetter<AvaloniaProperty, object> DirectPropertyDeferredSetter
{
get
{
return _directDeferredSetter ??
(_directDeferredSetter = new DeferredSetter<AvaloniaProperty, object>());
}
}
private ValueStore _values;
private ValueStore Values => _values ?? (_values = new ValueStore(this));
/// <summary>
/// Initializes a new instance of the <see cref="AvaloniaObject"/> class.
@ -227,9 +210,20 @@ namespace Avalonia
{
return ((IDirectPropertyAccessor)GetRegistered(property)).GetValue(this);
}
else if (_values != null)
{
var result = Values.GetValue(property);
if (result == AvaloniaProperty.UnsetValue)
{
result = GetDefaultValue(property);
}
return result;
}
else
{
return GetValueInternal(property);
return GetDefaultValue(property);
}
}
@ -256,7 +250,7 @@ namespace Avalonia
Contract.Requires<ArgumentNullException>(property != null);
VerifyAccess();
return _values.TryGetValue(property, out PriorityValue value) ? value.IsAnimating : false;
return _values?.IsAnimating(property) ?? false;
}
/// <summary>
@ -273,14 +267,7 @@ namespace Avalonia
Contract.Requires<ArgumentNullException>(property != null);
VerifyAccess();
PriorityValue value;
if (_values.TryGetValue(property, out value))
{
return value.Value != AvaloniaProperty.UnsetValue;
}
return false;
return _values?.IsSet(property) ?? false;
}
/// <summary>
@ -359,36 +346,15 @@ namespace Avalonia
property,
description);
IDisposable subscription = null;
if (_directBindings == null)
{
_directBindings = new List<IDisposable>();
_directBindings = new List<DirectBindingSubscription>();
}
subscription = source
.Select(x => CastOrDefault(x, property.PropertyType))
.Do(_ => { }, () => _directBindings.Remove(subscription))
.Subscribe(x => SetDirectValue(property, x));
_directBindings.Add(subscription);
return Disposable.Create(() =>
{
subscription.Dispose();
_directBindings.Remove(subscription);
});
return new DirectBindingSubscription(this, property, source);
}
else
{
PriorityValue v;
if (!_values.TryGetValue(property, out v))
{
v = CreatePriorityValue(property);
_values.Add(property, v);
}
Logger.Verbose(
LogArea.Property,
this,
@ -397,7 +363,7 @@ namespace Avalonia
description,
priority);
return v.Add(source, (int)priority);
return Values.AddBinding(property, source, priority);
}
}
@ -428,20 +394,11 @@ namespace Avalonia
public void Revalidate(AvaloniaProperty property)
{
VerifyAccess();
PriorityValue value;
if (_values.TryGetValue(property, out value))
{
value.Revalidate();
}
_values?.Revalidate(property);
}
/// <inheritdoc/>
void IPriorityValueOwner.Changed(PriorityValue sender, object oldValue, object newValue)
internal void PriorityValueChanged(AvaloniaProperty property, int priority, object oldValue, object newValue)
{
var property = sender.Property;
var priority = (BindingPriority)sender.ValuePriority;
oldValue = (oldValue == AvaloniaProperty.UnsetValue) ?
GetDefaultValue(property) :
oldValue;
@ -451,7 +408,7 @@ namespace Avalonia
if (!Equals(oldValue, newValue))
{
RaisePropertyChanged(property, oldValue, newValue, priority);
RaisePropertyChanged(property, oldValue, newValue, (BindingPriority)priority);
Logger.Verbose(
LogArea.Property,
@ -460,14 +417,13 @@ namespace Avalonia
property,
oldValue,
newValue,
priority);
(BindingPriority)priority);
}
}
/// <inheritdoc/>
void IPriorityValueOwner.BindingNotificationReceived(PriorityValue sender, BindingNotification notification)
internal void BindingNotificationReceived(AvaloniaProperty property, BindingNotification notification)
{
UpdateDataValidation(sender.Property, notification);
UpdateDataValidation(property, notification);
}
/// <inheritdoc/>
@ -480,10 +436,7 @@ namespace Avalonia
/// Gets all priority values set on the object.
/// </summary>
/// <returns>A collection of property/value tuples.</returns>
internal IDictionary<AvaloniaProperty, PriorityValue> GetSetValues()
{
return _values;
}
internal IDictionary<AvaloniaProperty, object> GetSetValues() => Values?.GetSetValues();
/// <summary>
/// Forces revalidation of properties when a property value changes.
@ -593,12 +546,12 @@ namespace Avalonia
T value)
{
Contract.Requires<ArgumentNullException>(setterCallback != null);
return DirectPropertyDeferredSetter.SetAndNotify(
return Values.Setter.SetAndNotify(
property,
ref field,
(object val, ref T backing, Action<Action> notify) =>
(object update, ref T backing, Action<Action> notify) =>
{
setterCallback((T)val, ref backing, notify);
setterCallback((T)update, ref backing, notify);
return true;
},
value);
@ -672,68 +625,18 @@ namespace Avalonia
}
}
/// <summary>
/// Creates a <see cref="PriorityValue"/> for a <see cref="AvaloniaProperty"/>.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The <see cref="PriorityValue"/>.</returns>
private PriorityValue CreatePriorityValue(AvaloniaProperty property)
{
var validate = ((IStyledPropertyAccessor)property).GetValidationFunc(GetType());
Func<object, object> validate2 = null;
if (validate != null)
{
validate2 = v => validate(this, v);
}
PriorityValue result = new PriorityValue(
this,
property,
property.PropertyType,
validate2);
return result;
}
/// <summary>
/// Gets the default value for a property.
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The default value.</returns>
private object GetDefaultValue(AvaloniaProperty property)
internal object GetDefaultValue(AvaloniaProperty property)
{
if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
return aobj.GetValueInternal(property);
return aobj.GetValue(property);
return ((IStyledPropertyAccessor) property).GetDefaultValue(GetType());
}
/// <summary>
/// Gets a <see cref="AvaloniaProperty"/> value
/// without check for registered as this can slow getting the value
/// this method is intended for internal usage in AvaloniaObject only
/// it's called only after check the property is registered
/// </summary>
/// <param name="property">The property.</param>
/// <returns>The value.</returns>
private object GetValueInternal(AvaloniaProperty property)
{
object result = AvaloniaProperty.UnsetValue;
PriorityValue value;
if (_values.TryGetValue(property, out value))
{
result = value.Value;
}
if (result == AvaloniaProperty.UnsetValue)
{
result = GetDefaultValue(property);
}
return result;
}
/// <summary>
/// Sets the value of a direct property.
/// </summary>
@ -814,21 +717,8 @@ namespace Avalonia
originalValue?.GetType().FullName ?? "(null)"));
}
PriorityValue v;
if (!_values.TryGetValue(property, out v))
{
if (value == AvaloniaProperty.UnsetValue)
{
return;
}
v = CreatePriorityValue(property);
_values.Add(property, v);
}
LogPropertySet(property, value, priority);
v.SetValue(value, (int)priority);
Values.AddValue(property, value, (int)priority);
}
/// <summary>
@ -908,5 +798,38 @@ namespace Avalonia
value,
priority);
}
private class DirectBindingSubscription : IObserver<object>, IDisposable
{
readonly AvaloniaObject _owner;
readonly AvaloniaProperty _property;
IDisposable _subscription;
public DirectBindingSubscription(
AvaloniaObject owner,
AvaloniaProperty property,
IObservable<object> source)
{
_owner = owner;
_property = property;
_owner._directBindings.Add(this);
_subscription = source.Subscribe(this);
}
public void Dispose()
{
_subscription.Dispose();
_owner._directBindings.Remove(this);
}
public void OnCompleted() => Dispose();
public void OnError(Exception error) => Dispose();
public void OnNext(object value)
{
var castValue = CastOrDefault(value, _property.PropertyType);
_owner.SetDirectValue(_property, castValue);
}
}
}
}

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

Loading…
Cancel
Save