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. # editorconfig.org
; More information at http://EditorConfig.org
# top-most EditorConfig file
root = true 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] [*.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 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 .idea
#################
## VS Code
#################
.vscode/
################# #################
## Cake ## Cake
################# #################
@ -176,5 +181,9 @@ nuget
Avalonia.XBuild.sln Avalonia.XBuild.sln
project.lock.json project.lock.json
.idea/* .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 EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{A689DEF5-D50F-4975-8B72-124C9EB54066}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
src\Shared\SharedAssemblyInfo.cs = src\Shared\SharedAssemblyInfo.cs src\Shared\SharedAssemblyInfo.cs = src\Shared\SharedAssemblyInfo.cs
EndProjectSection EndProjectSection
EndProject EndProject
@ -71,7 +72,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup", "src\Mark
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Markup.UnitTests", "tests\Avalonia.Markup.UnitTests\Avalonia.Markup.UnitTests.csproj", "{8EF392D5-1416-45AA-9956-7CBBC3229E8A}"
EndProject 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 EndProject
Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}" Project("{D954291E-2A0B-460D-934E-DC6B0785DB48}") = "RenderHelpers", "src\Shared\RenderHelpers\RenderHelpers.shproj", "{3C4C0CB4-0C0F-4450-A37B-148C84FF905F}"
EndProject EndProject
@ -109,7 +110,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.Te
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DesignerSupport.TestApp", "tests\Avalonia.DesignerSupport.TestApp\Avalonia.DesignerSupport.TestApp.csproj", "{F1381F98-4D24-409A-A6C5-1C5B1E08BB08}"
EndProject 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 EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC0258-D18C-4AB3-854F-7101680FC3F9}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Interop", "Interop", "{A0CC0258-D18C-4AB3-854F-7101680FC3F9}"
EndProject EndProject
@ -117,7 +118,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsInteropTest", "sampl
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetFrameworkRuntime", "src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj", "{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.DotNetFrameworkRuntime", "src\Avalonia.DotNetFrameworkRuntime\Avalonia.DotNetFrameworkRuntime.csproj", "{4A1ABB09-9047-4BD5-A4AD-A055E52C5EE0}"
EndProject 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 EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ControlCatalog.Android", "samples\ControlCatalog.Android\ControlCatalog.Android.csproj", "{29132311-1848-4FD6-AE0C-4FF841151BD3}"
EndProject 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\Microsoft.Reactive.Testing.props = build\Microsoft.Reactive.Testing.props
build\Moq.props = build\Moq.props build\Moq.props = build\Moq.props
build\NetCore.props = build\NetCore.props build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props
build\ReactiveUI.props = build\ReactiveUI.props build\ReactiveUI.props = build\ReactiveUI.props
build\Rx.props = build\Rx.props build\Rx.props = build\Rx.props
build\SampleApp.props = build\SampleApp.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\SharpDX.props = build\SharpDX.props
build\SkiaSharp.props = build\SkiaSharp.props build\SkiaSharp.props = build\SkiaSharp.props
build\Splat.props = build\Splat.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 build\XUnit.props = build\XUnit.props
EndProjectSection EndProjectSection
EndProject EndProject
@ -168,7 +170,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.RenderTests",
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Remote.Protocol", "src\Avalonia.Remote.Protocol\Avalonia.Remote.Protocol.csproj", "{D78A720C-C0C6-478B-8564-F167F9BDD01B}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Remote.Protocol", "src\Avalonia.Remote.Protocol\Avalonia.Remote.Protocol.csproj", "{D78A720C-C0C6-478B-8564-F167F9BDD01B}"
EndProject 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 EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{4ED8B739-6F4E-4CD4-B993-545E6B5CE637}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tools", "Tools", "{4ED8B739-6F4E-4CD4-B993-545E6B5CE637}"
EndProject EndProject
@ -182,6 +184,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.MonoMac", "src\OSX
EndProject 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}" 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 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 Global
GlobalSection(SharedMSBuildProjectFiles) = preSolution GlobalSection(SharedMSBuildProjectFiles) = preSolution
src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13 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.ActiveCfg = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|iPhoneSimulator.Build.0 = 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.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.ActiveCfg = Debug|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Debug|x86.Build.0 = 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 {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.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|iPhoneSimulator.Build.0 = 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.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.ActiveCfg = Release|Any CPU
{3E908F67-5543-4879-A1DC-08EACE79B3CD}.Release|x86.Build.0 = 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 {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|NetCoreOnly.ActiveCfg = Release|Any CPU
{4ADA61C8-D191-428D-9066-EF4F0D86520F}.Release|x86.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 {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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@ -2519,6 +2565,7 @@ Global
{F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE} = {9B9E3891-2366-4253-A952-D08BCEB71098} {F40FC0A2-1BC3-401C-BFC1-928EC4D4A9CE} = {9B9E3891-2366-4253-A952-D08BCEB71098}
{CBFD5788-567D-401B-9DFA-74E4224025A0} = {A59C4C0A-64DF-4621-B450-2BA00D6F61E2} {CBFD5788-567D-401B-9DFA-74E4224025A0} = {A59C4C0A-64DF-4621-B450-2BA00D6F61E2}
{4ADA61C8-D191-428D-9066-EF4F0D86520F} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637} {4ADA61C8-D191-428D-9066-EF4F0D86520F} = {4ED8B739-6F4E-4CD4-B993-545E6B5CE637}
{E1240B49-7B4B-4371-A00E-068778C5CF0B} = {C5A00AC3-B34C-4564-9BDD-2DA473EF4D8B}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A} SolutionGuid = {87366D66-1391-4D90-8999-95A620AD786A}

232
build.cake

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

4
build/SkiaSharp.props

@ -1,6 +1,6 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup> <ItemGroup>
<PackageReference Include="SkiaSharp" Version="1.57.1" /> <PackageReference Include="SkiaSharp" Version="1.60.0" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.57.1.3" /> <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="Avalonia.Skia.Linux.Natives" Version="1.60.0.1" />
</ItemGroup> </ItemGroup>
</Project> </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.Desktop.props" />
<Import Project="..\..\build\SkiaSharp.props" /> <Import Project="..\..\build\SkiaSharp.props" />
<Import Project="..\..\build\Splat.props" /> <Import Project="..\..\build\Splat.props" />
<Import Project="..\..\build\Sprache.props" />
<Import Project="..\..\build\XUnit.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; using System.Xml.Linq;
public class Packages public class Packages
@ -9,12 +12,11 @@ public class Packages
public string SkiaSharpVersion {get; private set; } public string SkiaSharpVersion {get; private set; }
public string SkiaSharpLinuxVersion {get; private set; } public string SkiaSharpLinuxVersion {get; private set; }
public Dictionary<string, IList<Tuple<string,string>>> PackageVersions{get; private set;} public Dictionary<string, IList<Tuple<string,string>>> PackageVersions{get; private set;}
class DependencyBuilder : List<NuSpecDependency> class DependencyBuilder : List<NuSpecDependency>
{ {
Packages _parent; Packages _parent;
public DependencyBuilder(Packages parent) public DependencyBuilder(Packages parent)
{ {
_parent = parent; _parent = parent;
@ -24,8 +26,7 @@ public class Packages
{ {
return _parent.PackageVersions[name].First().Item1; return _parent.PackageVersions[name].First().Item1;
} }
public DependencyBuilder Dep(string name, params string[] fws) public DependencyBuilder Dep(string name, params string[] fws)
{ {
if(fws.Length == 0) if(fws.Length == 0)
@ -109,7 +110,6 @@ public class Packages
var SerilogVersion = packageVersions["Serilog"].FirstOrDefault().Item1; var SerilogVersion = packageVersions["Serilog"].FirstOrDefault().Item1;
var SerilogSinksDebugVersion = packageVersions["Serilog.Sinks.Debug"].FirstOrDefault().Item1; var SerilogSinksDebugVersion = packageVersions["Serilog.Sinks.Debug"].FirstOrDefault().Item1;
var SerilogSinksTraceVersion = packageVersions["Serilog.Sinks.Trace"].FirstOrDefault().Item1; var SerilogSinksTraceVersion = packageVersions["Serilog.Sinks.Trace"].FirstOrDefault().Item1;
var SpracheVersion = packageVersions["Sprache"].FirstOrDefault().Item1;
var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1; var SystemReactiveVersion = packageVersions["System.Reactive"].FirstOrDefault().Item1;
var ReactiveUIVersion = packageVersions["reactiveui"].FirstOrDefault().Item1; var ReactiveUIVersion = packageVersions["reactiveui"].FirstOrDefault().Item1;
var SystemValueTupleVersion = packageVersions["System.ValueTuple"].FirstOrDefault().Item1; var SystemValueTupleVersion = packageVersions["System.ValueTuple"].FirstOrDefault().Item1;
@ -120,10 +120,10 @@ public class Packages
var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1; var SharpDXDirect3D11Version = packageVersions["SharpDX.Direct3D11"].FirstOrDefault().Item1;
var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1; var SharpDXDirect3D9Version = packageVersions["SharpDX.Direct3D9"].FirstOrDefault().Item1;
var SharpDXDXGIVersion = packageVersions["SharpDX.DXGI"].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: Serilog, version: {0}", SerilogVersion);
context.Information("Package: Sprache, version: {0}", SpracheVersion);
context.Information("Package: System.Reactive, version: {0}", SystemReactiveVersion); context.Information("Package: System.Reactive, version: {0}", SystemReactiveVersion);
context.Information("Package: reactiveui, version: {0}", ReactiveUIVersion); context.Information("Package: reactiveui, version: {0}", ReactiveUIVersion);
context.Information("Package: System.ValueTuple, version: {0}", SystemValueTupleVersion); 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.Direct3D11, version: {0}", SharpDXDirect3D11Version);
context.Information("Package: SharpDX.Direct3D9, version: {0}", SharpDXDirect3D9Version); context.Information("Package: SharpDX.Direct3D9, version: {0}", SharpDXDirect3D9Version);
context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion); context.Information("Package: SharpDX.DXGI, version: {0}", SharpDXDXGIVersion);
context.Information("Package: System.Memory, version: {0}", SystemMemoryVersion);
var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME") var nugetPackagesDir = System.Environment.GetEnvironmentVariable("NUGET_HOME")
?? System.IO.Path.Combine(System.Environment.GetEnvironmentVariable("USERPROFILE") ?? System.Environment.GetEnvironmentVariable("HOME"), ".nuget"); ?? System.IO.Path.Combine(System.Environment.GetEnvironmentVariable("USERPROFILE") ?? System.Environment.GetEnvironmentVariable("HOME"), ".nuget");
@ -212,17 +213,33 @@ public class Packages
}; };
}); });
var toolsContent = new[] { var toolHostApp = new NuSpecContent{
new NuSpecContent{ Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp/bin/" + parameters.DirSuffix + "/netcoreapp2.0/Avalonia.Designer.HostApp.dll")).FullPath,
Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp/bin/" + parameters.DirSuffix + "/netcoreapp2.0/Avalonia.Designer.HostApp.dll")).FullPath, Target = "tools/netcoreapp2.0/previewer"
Target = "tools/netcoreapp2.0/previewer" };
},
new NuSpecContent{ var toolHostAppNetFx = new NuSpecContent{
Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp.NetFx/bin/" + parameters.DirSuffix + "/Avalonia.Designer.HostApp.exe")).FullPath, Source = ((FilePath)context.File("./src/tools/Avalonia.Designer.HostApp.NetFx/bin/" + parameters.DirSuffix + "/Avalonia.Designer.HostApp.exe")).FullPath,
Target = "tools/net461/previewer" 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 [] 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="netcoreapp2.0" },
new NuSpecDependency() { Id = "Avalonia.Remote.Protocol", Version = parameters.Version, TargetFramework="net461" }, new NuSpecDependency() { Id = "Avalonia.Remote.Protocol", Version = parameters.Version, TargetFramework="net461" },
new NuSpecDependency() { Id = "System.ValueTuple", Version = SystemValueTupleVersion, 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"} new NuSpecDependency() { Id = "NETStandard.Library", Version = "2.0.0", TargetFramework="net461"}
} }
.Deps(new string[]{"netstandard2.0", "netcoreapp2.0", "net461"}, .Deps(new string[]{"netstandard2.0", "netcoreapp2.0", "net461"},
"Serilog", "Serilog.Sinks.Debug", "Serilog.Sinks.Trace", "Sprache", "Serilog", "Serilog.Sinks.Debug", "Serilog.Sinks.Trace",
"System.Reactive", "System.ComponentModel.Annotations") "System.Memory", "System.Reactive", "System.ComponentModel.Annotations")
.ToArray(), .ToArray(),
Files = coreLibrariesNuSpecContent Files = coreFiles,
.Concat(netFrameworkCoreLibrariesNuSpecContent).Concat(netFrameworkRuntimePlatform)
.Concat(netcoreappCoreLibrariesNuSpecContent).Concat(netCoreRuntimePlatform)
.Concat(toolsContent)
.ToList(),
BasePath = context.Directory("./"), BasePath = context.Directory("./"),
OutputDirectory = parameters.NugetRoot 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 = new List<NuGetPackSettings>();
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsCore); NuspecNuGetSettings.AddRange(nuspecNuGetSettingsCore);
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsDesktop); NuspecNuGetSettings.AddRange(nuspecNuGetSettingsDesktop);
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
if (!parameters.IsPlatformNetCoreOnly) {
NuspecNuGetSettings.Add(nuspecNuGetSettingInterop);
NuspecNuGetSettings.AddRange(nuspecNuGetSettingsMobile);
}
NuspecNuGetSettings.ForEach((nuspec) => SetNuGetNuspecCommonProperties(nuspec)); NuspecNuGetSettings.ForEach((nuspec) => SetNuGetNuspecCommonProperties(nuspec));

12
parameters.cake

@ -8,11 +8,11 @@ public class Parameters
public string AssemblyInfoPath { get; private set; } public string AssemblyInfoPath { get; private set; }
public string ReleasePlatform { get; private set; } public string ReleasePlatform { get; private set; }
public string ReleaseConfiguration { get; private set; } public string ReleaseConfiguration { get; private set; }
public string MSBuildSolution { get; private set; } public string MSBuildSolution { get; private set; }
public string XBuildSolution { get; private set; }
public bool IsPlatformAnyCPU { get; private set; } public bool IsPlatformAnyCPU { get; private set; }
public bool IsPlatformX86 { get; private set; } public bool IsPlatformX86 { get; private set; }
public bool IsPlatformX64 { get; private set; } public bool IsPlatformX64 { get; private set; }
public bool IsPlatformNetCoreOnly { get; private set; }
public bool IsLocalBuild { get; private set; } public bool IsLocalBuild { get; private set; }
public bool IsRunningOnUnix { get; private set; } public bool IsRunningOnUnix { get; private set; }
public bool IsRunningOnWindows { get; private set; } public bool IsRunningOnWindows { get; private set; }
@ -34,6 +34,7 @@ public class Parameters
public DirectoryPathCollection BuildDirs { get; private set; } public DirectoryPathCollection BuildDirs { get; private set; }
public string FileZipSuffix { get; private set; } public string FileZipSuffix { get; private set; }
public FilePath ZipCoreArtifacts { get; private set; } public FilePath ZipCoreArtifacts { get; private set; }
public FilePath ZipNuGetArtifacts { get; private set; }
public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; } public DirectoryPath ZipSourceControlCatalogDesktopDirs { get; private set; }
public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; } public FilePath ZipTargetControlCatalogDesktopDirs { get; private set; }
@ -53,12 +54,12 @@ public class Parameters
ReleasePlatform = "Any CPU"; ReleasePlatform = "Any CPU";
ReleaseConfiguration = "Release"; ReleaseConfiguration = "Release";
MSBuildSolution = "./Avalonia.sln"; MSBuildSolution = "./Avalonia.sln";
XBuildSolution = "./Avalonia.XBuild.sln";
// PARAMETERS // PARAMETERS
IsPlatformAnyCPU = StringComparer.OrdinalIgnoreCase.Equals(Platform, "Any CPU"); IsPlatformAnyCPU = StringComparer.OrdinalIgnoreCase.Equals(Platform, "Any CPU");
IsPlatformX86 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x86"); IsPlatformX86 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x86");
IsPlatformX64 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x64"); IsPlatformX64 = StringComparer.OrdinalIgnoreCase.Equals(Platform, "x64");
IsPlatformNetCoreOnly = StringComparer.OrdinalIgnoreCase.Equals(Platform, "NetCoreOnly");
IsLocalBuild = buildSystem.IsLocalBuild; IsLocalBuild = buildSystem.IsLocalBuild;
IsRunningOnUnix = context.IsRunningOnUnix(); IsRunningOnUnix = context.IsRunningOnUnix();
IsRunningOnWindows = context.IsRunningOnWindows(); IsRunningOnWindows = context.IsRunningOnWindows();
@ -71,7 +72,6 @@ public class Parameters
IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleasePlatform, Platform) IsReleasable = StringComparer.OrdinalIgnoreCase.Equals(ReleasePlatform, Platform)
&& StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration); && StringComparer.OrdinalIgnoreCase.Equals(ReleaseConfiguration, Configuration);
IsMyGetRelease = !IsTagged && IsReleasable; IsMyGetRelease = !IsTagged && IsReleasable;
// VERSION // VERSION
Version = context.Argument("force-nuget-version", context.ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion); Version = context.Argument("force-nuget-version", context.ParseAssemblyInfo(AssemblyInfoPath).AssemblyVersion);
@ -103,14 +103,12 @@ public class Parameters
NugetRoot = ArtifactsDir.Combine("nuget"); NugetRoot = ArtifactsDir.Combine("nuget");
ZipRoot = ArtifactsDir.Combine("zip"); ZipRoot = ArtifactsDir.Combine("zip");
BinRoot = ArtifactsDir.Combine("bin"); BinRoot = ArtifactsDir.Combine("bin");
BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj"); BuildDirs = context.GetDirectories("**/bin") + context.GetDirectories("**/obj");
DirSuffix = Configuration; DirSuffix = Configuration;
DirSuffixIOS = "iPhone" + "/" + Configuration; DirSuffixIOS = "iPhone" + "/" + Configuration;
FileZipSuffix = Version + ".zip"; FileZipSuffix = Version + ".zip";
ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix); ZipCoreArtifacts = ZipRoot.CombineWithFilePath("Avalonia-" + FileZipSuffix);
ZipNuGetArtifacts = ZipRoot.CombineWithFilePath("Avalonia-NuGet-" + FileZipSuffix);
ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461"); ZipSourceControlCatalogDesktopDirs = (DirectoryPath)context.Directory("./samples/ControlCatalog.Desktop/bin/" + DirSuffix + "/net461");
ZipTargetControlCatalogDesktopDirs = ZipRoot.CombineWithFilePath("ControlCatalog.Desktop-" + FileZipSuffix); 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! 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)) 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: 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 Avalonia.Markup.Xaml;
using Serilog; using Serilog;
namespace BindingTest namespace BindingDemo
{ {
public class App : Application 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" <Window xmlns="https://github.com/avaloniaui"
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml' xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'
xmlns:vm="clr-namespace:BindingTest.ViewModels" xmlns:vm="clr-namespace:BindingDemo.ViewModels"
xmlns:local="clr-namespace:BindingTest" xmlns:local="clr-namespace:BindingDemo"
Title="AvaloniaUI Bindings Test" Title="AvaloniaUI Bindings Test"
Width="800" Width="800"
Height="600"> Height="600">
@ -18,18 +18,18 @@
<TabItem Header="Basic"> <TabItem Header="Basic">
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<StackPanel Margin="18" Gap="4" Width="200"> <StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Simple Bindings"/> <TextBlock FontSize="16" Text="Simple Bindings"/>
<TextBox Watermark="Two Way" UseFloatingWatermark="True" Text="{Binding Path=StringValue}" Name="first"/> <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 Way" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneWay}"/>
<TextBox Watermark="One Time" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneTime}"/> <TextBox Watermark="One Time" UseFloatingWatermark="True" Text="{Binding Path=StringValue, Mode=OneTime}"/>
</StackPanel> </StackPanel>
<StackPanel Margin="18" Gap="4" Width="200"> <StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Collection Bindings"/> <TextBlock FontSize="16" Text="Collection Bindings"/>
<TextBox Watermark="Items[1].StringValue" UseFloatingWatermark="True" Text="{Binding Path=Items[1].StringValue}"/> <TextBox Watermark="Items[1].StringValue" UseFloatingWatermark="True" Text="{Binding Path=Items[1].StringValue}"/>
<Button Command="{Binding ShuffleItems}">Shuffle</Button> <Button Command="{Binding ShuffleItems}">Shuffle</Button>
</StackPanel> </StackPanel>
<StackPanel Margin="18" Gap="4" Width="200"> <StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Negated Bindings"/> <TextBlock FontSize="16" Text="Negated Bindings"/>
<TextBox Watermark="Boolean String" UseFloatingWatermark="True" Text="{Binding Path=BooleanString}"/> <TextBox Watermark="Boolean String" UseFloatingWatermark="True" Text="{Binding Path=BooleanString}"/>
<CheckBox IsChecked="{Binding !BooleanString}">!BooleanString</CheckBox> <CheckBox IsChecked="{Binding !BooleanString}">!BooleanString</CheckBox>
@ -37,13 +37,13 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal"> <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"/> <TextBlock FontSize="16" Text="Numeric Bindings"/>
<TextBox Watermark="Double" UseFloatingWatermark="True" Text="{Binding Path=DoubleValue, Mode=TwoWay}"/> <TextBox Watermark="Double" UseFloatingWatermark="True" Text="{Binding Path=DoubleValue, Mode=TwoWay}"/>
<TextBlock Text="{Binding Path=DoubleValue}"/> <TextBlock Text="{Binding Path=DoubleValue}"/>
<ProgressBar Maximum="10" Value="{Binding DoubleValue}"/> <ProgressBar Maximum="10" Value="{Binding DoubleValue}"/>
</StackPanel> </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"/> <TextBlock FontSize="16" Text="Binding Sources"/>
<TextBox Watermark="Value of first TextBox" UseFloatingWatermark="True" <TextBox Watermark="Value of first TextBox" UseFloatingWatermark="True"
Text="{Binding #first.Text, Mode=TwoWay}"/> Text="{Binding #first.Text, Mode=TwoWay}"/>
@ -52,7 +52,7 @@
<TextBox Watermark="Value of SharedItem.StringValue (duplicate)" UseFloatingWatermark="True" <TextBox Watermark="Value of SharedItem.StringValue (duplicate)" UseFloatingWatermark="True"
Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay}"/> Text="{Binding StringValue, Source={StaticResource SharedItem}, Mode=TwoWay}"/>
</StackPanel> </StackPanel>
<StackPanel Margin="18" Gap="4" Width="200" HorizontalAlignment="Left"> <StackPanel Margin="18" Spacing="4" Width="200" HorizontalAlignment="Left">
<TextBlock FontSize="16" Text="Scheduler"/> <TextBlock FontSize="16" Text="Scheduler"/>
<TextBox Watermark="Background Thread" Text="{Binding CurrentTime, Mode=OneWay}"/> <TextBox Watermark="Background Thread" Text="{Binding CurrentTime, Mode=OneWay}"/>
<TextBlock FontSize="16" Text="Stream Operator"/> <TextBlock FontSize="16" Text="Stream Operator"/>
@ -68,11 +68,11 @@
<TextBlock Text="{Binding StringValue}"/> <TextBlock Text="{Binding StringValue}"/>
</DataTemplate> </DataTemplate>
</StackPanel.DataTemplates> </StackPanel.DataTemplates>
<StackPanel Margin="18" Gap="4" Width="200"> <StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Multiple"/> <TextBlock FontSize="16" Text="Multiple"/>
<ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/> <ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/>
</StackPanel> </StackPanel>
<StackPanel Margin="18" Gap="4" Width="200"> <StackPanel Margin="18" Spacing="4" Width="200">
<TextBlock FontSize="16" Text="Multiple"/> <TextBlock FontSize="16" Text="Multiple"/>
<ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/> <ListBox Items="{Binding Items}" SelectionMode="Multiple" SelectedItems="{Binding SelectedItems}"/>
</StackPanel> </StackPanel>
@ -87,16 +87,16 @@
</TabItem> </TabItem>
<TabItem Header="Property Validation"> <TabItem Header="Property Validation">
<StackPanel Orientation="Horizontal"> <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"/> <TextBlock FontSize="16" Text="Exception Validation"/>
<TextBox Watermark="Less Than 10" UseFloatingWatermark="True" Text="{Binding Path=LessThan10}"/> <TextBox Watermark="Less Than 10" UseFloatingWatermark="True" Text="{Binding Path=LessThan10}"/>
</StackPanel> </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"/> <TextBlock FontSize="16" Text="INotifyDataErrorInfo Validation"/>
<TextBox Watermark="Maximum" UseFloatingWatermark="True" Text="{Binding Path=Maximum}"/> <TextBox Watermark="Maximum" UseFloatingWatermark="True" Text="{Binding Path=Maximum}"/>
<TextBox Watermark="Value" UseFloatingWatermark="True" Text="{Binding Path=Value}"/> <TextBox Watermark="Value" UseFloatingWatermark="True" Text="{Binding Path=Value}"/>
</StackPanel> </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"/> <TextBlock FontSize="16" Text="Data Annotations Validation"/>
<TextBox Watermark="Phone #" UseFloatingWatermark="True" Text="{Binding PhoneNumber}"/> <TextBox Watermark="Phone #" UseFloatingWatermark="True" Text="{Binding PhoneNumber}"/>
<TextBox Watermark="Less Than 10" UseFloatingWatermark="True" Text="{Binding Path=LessThan10}"/> <TextBox Watermark="Less Than 10" UseFloatingWatermark="True" Text="{Binding Path=LessThan10}"/>
@ -104,7 +104,7 @@
</StackPanel> </StackPanel>
</TabItem> </TabItem>
<TabItem Header="Commands"> <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"/> <Button Content="Button" Command="{Binding StringValueCommand}" CommandParameter="Button"/>
<ToggleButton Content="ToggleButton" IsChecked="{Binding BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="ToggleButton"/> <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"/> <CheckBox Content="CheckBox" IsChecked="{Binding !BooleanFlag, Mode=OneWay}" Command="{Binding StringValueCommand}" CommandParameter="CheckBox"/>
@ -114,4 +114,4 @@
</StackPanel> </StackPanel>
</TabItem> </TabItem>
</TabControl> </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;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace BindingTest namespace BindingDemo
{ {
public class MainWindow : Window 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.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace BindingTest namespace BindingDemo
{ {
public class TestItemView : UserControl public class TestItemView : UserControl
{ {

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

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

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

@ -4,7 +4,7 @@
using ReactiveUI; using ReactiveUI;
using System; using System;
namespace BindingTest.ViewModels namespace BindingDemo.ViewModels
{ {
public class ExceptionErrorViewModel : ReactiveObject 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.ComponentModel;
using System.Collections; using System.Collections;
namespace BindingTest.ViewModels namespace BindingDemo.ViewModels
{ {
public class IndeiErrorViewModel : ReactiveObject, INotifyDataErrorInfo 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.Tasks;
using System.Threading; using System.Threading;
namespace BindingTest.ViewModels namespace BindingDemo.ViewModels
{ {
public class MainWindowViewModel : ReactiveObject 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.Threading.Tasks;
using System.Windows.Input; using System.Windows.Input;
namespace BindingTest.ViewModels namespace BindingDemo.ViewModels
{ {
public class NestedCommandViewModel : ReactiveObject public class NestedCommandViewModel : ReactiveObject
{ {

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

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

4
samples/ControlCatalog.NetCore/Program.cs

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

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

@ -174,6 +174,5 @@
<Name>ControlCatalog</Name> <Name>ControlCatalog</Name>
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Sprache.props" />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" /> <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"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">AutoCompleteBox</TextBlock> <TextBlock Classes="h1">AutoCompleteBox</TextBlock>
<TextBlock Classes="h2">A control into which the user can input text</TextBlock> <TextBlock Classes="h2">A control into which the user can input text</TextBlock>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Gap="8"> Spacing="8">
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock Text="MinimumPrefixLength: 1"/> <TextBlock Text="MinimumPrefixLength: 1"/>
<AutoCompleteBox Width="200" <AutoCompleteBox Width="200"
@ -56,4 +56,4 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

6
samples/ControlCatalog/Pages/BorderPage.xaml

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

10
samples/ControlCatalog/Pages/ButtonPage.xaml

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

6
samples/ControlCatalog/Pages/ButtonSpinnerPage.xaml

@ -1,11 +1,11 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 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="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> <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="allowSpinCheck" IsChecked="True">AllowSpin</CheckBox>
<CheckBox Name="showSpinCheck" IsChecked="True">ShowButtonSpinner</CheckBox> <CheckBox Name="showSpinCheck" IsChecked="True">ShowButtonSpinner</CheckBox>
<ButtonSpinner Spin="OnSpin" Height="30" <ButtonSpinner Spin="OnSpin" Height="30"
@ -21,4 +21,4 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

6
samples/ControlCatalog/Pages/CalendarPage.xaml

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

4
samples/ControlCatalog/Pages/CanvasPage.xaml

@ -1,5 +1,5 @@
<UserControl xmlns="https://github.com/avaloniaui"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Canvas</TextBlock> <TextBlock Classes="h1">Canvas</TextBlock>
<TextBlock Classes="h2">A panel which lays out its children by explicit coordinates</TextBlock> <TextBlock Classes="h2">A panel which lays out its children by explicit coordinates</TextBlock>
<Canvas Background="Yellow" Width="300" Height="400"> <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"/> <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> </Canvas>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

10
samples/ControlCatalog/Pages/CarouselPage.xaml

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

10
samples/ControlCatalog/Pages/CheckBoxPage.xaml

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

6
samples/ControlCatalog/Pages/ContextMenuPage.xaml

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

6
samples/ControlCatalog/Pages/DatePickerPage.xaml

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

4
samples/ControlCatalog/Pages/DialogsPage.xaml

@ -1,5 +1,5 @@
<UserControl xmlns="https://github.com/avaloniaui"> <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="OpenFile">Open File</Button>
<Button Name="SaveFile">Save File</Button> <Button Name="SaveFile">Save File</Button>
<Button Name="SelectFolder">Select Folder</Button> <Button Name="SelectFolder">Select Folder</Button>
@ -9,4 +9,4 @@
</StackPanel> </StackPanel>
<Button Name="DecoratedWindow">Decorated window</Button> <Button Name="DecoratedWindow">Decorated window</Button>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

6
samples/ControlCatalog/Pages/DragAndDropPage.xaml

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

6
samples/ControlCatalog/Pages/DropDownPage.xaml

@ -1,9 +1,9 @@
<UserControl xmlns="https://github.com/avaloniaui"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">DropDown</TextBlock> <TextBlock Classes="h1">DropDown</TextBlock>
<TextBlock Classes="h2">A drop-down list.</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"> <DropDown SelectedIndex="0">
<DropDownItem>Inline Items</DropDownItem> <DropDownItem>Inline Items</DropDownItem>
<DropDownItem>Inline Item 2</DropDownItem> <DropDownItem>Inline Item 2</DropDownItem>
@ -28,4 +28,4 @@
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

6
samples/ControlCatalog/Pages/ExpanderPage.xaml

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

4
samples/ControlCatalog/Pages/ImagePage.xaml

@ -1,12 +1,12 @@
<UserControl xmlns="https://github.com/avaloniaui"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Image</TextBlock> <TextBlock Classes="h1">Image</TextBlock>
<TextBlock Classes="h2">Displays an image</TextBlock> <TextBlock Classes="h2">Displays an image</TextBlock>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Gap="16"> Spacing="16">
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock>No Stretch</TextBlock> <TextBlock>No Stretch</TextBlock>
<Image Source="resm:ControlCatalog.Assets.delicate-arch-896885_640.jpg" <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"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">Menu</TextBlock> <TextBlock Classes="h1">Menu</TextBlock>
<TextBlock Classes="h2">A window menu</TextBlock> <TextBlock Classes="h2">A window menu</TextBlock>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Gap="16"> Spacing="16">
<Menu> <Menu>
<MenuItem Header="_First"> <MenuItem Header="_First">
<MenuItem Header="Standard _Menu Item"/> <MenuItem Header="Standard _Menu Item"/>

6
samples/ControlCatalog/Pages/NumericUpDownPage.xaml

@ -1,6 +1,6 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 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="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> <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"> VerticalAlignment="Center" Margin="2">
<DropDown.ItemTemplate> <DropDown.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Orientation="Horizontal" Gap="2"> <StackPanel Orientation="Horizontal" Spacing="2">
<TextBlock Text="{Binding Name}"/> <TextBlock Text="{Binding Name}"/>
<TextBlock Text="-"/> <TextBlock Text="-"/>
<TextBlock Text="{Binding Value}"/> <TextBlock Text="{Binding Value}"/>
@ -69,7 +69,7 @@
</Grid> </Grid>
</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> <TextBlock FontSize="14" FontWeight="Bold" VerticalAlignment="Center">Usage of NumericUpDown:</TextBlock>
<NumericUpDown Name="upDown" Minimum="0" Maximum="10" Increment="0.5" <NumericUpDown Name="upDown" Minimum="0" Maximum="10" Increment="0.5"
CultureInfo="en-US" VerticalAlignment="Center" Height="25" Width="100" 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"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">ProgressBar</TextBlock> <TextBlock Classes="h1">ProgressBar</TextBlock>
<TextBlock Classes="h2">A progress bar control</TextBlock> <TextBlock Classes="h2">A progress bar control</TextBlock>
@ -7,8 +7,8 @@
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Gap="16"> Spacing="16">
<StackPanel Gap="16"> <StackPanel Spacing="16">
<ProgressBar Value="{Binding #hprogress.Value}" /> <ProgressBar Value="{Binding #hprogress.Value}" />
<ProgressBar IsIndeterminate="True"/> <ProgressBar IsIndeterminate="True"/>
</StackPanel> </StackPanel>

8
samples/ControlCatalog/Pages/RadioButtonPage.xaml

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

11
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -1,14 +1,15 @@
<UserControl xmlns="https://github.com/avaloniaui"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">TextBox</TextBlock> <TextBlock Classes="h1">TextBox</TextBlock>
<TextBlock Classes="h2">A control into which the user can input text</TextBlock> <TextBlock Classes="h2">A control into which the user can input text</TextBlock>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Gap="16"> Spacing="16">
<StackPanel Orientation="Vertical" Gap="8"> <StackPanel Orientation="Vertical" Spacing="8">
<TextBox Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit." Width="200" /> <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="Watermark" />
<TextBox Width="200" <TextBox Width="200"
Watermark="Floating Watermark" Watermark="Floating Watermark"
@ -25,13 +26,13 @@
<TextBox Width="200" Text="Right aligned text" TextAlignment="Right" /> <TextBox Width="200" Text="Right aligned text" TextAlignment="Right" />
</StackPanel> </StackPanel>
<StackPanel Orientation="Vertical" Gap="8"> <StackPanel Orientation="Vertical" Spacing="8">
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Width="200" Height="125" <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." /> 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" <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." /> 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>
<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 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 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"/> <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"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" <StackPanel Orientation="Vertical"
Gap="4"> Spacing="4">
<TextBlock Classes="h1">ToolTip</TextBlock> <TextBlock Classes="h1">ToolTip</TextBlock>
<TextBlock Classes="h2">A control which pops up a hint when a control is hovered</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"> <UserControl xmlns="https://github.com/avaloniaui">
<StackPanel Orientation="Vertical" Gap="4"> <StackPanel Orientation="Vertical" Spacing="4">
<TextBlock Classes="h1">TreeView</TextBlock> <TextBlock Classes="h1">TreeView</TextBlock>
<TextBlock Classes="h2">Displays a hierachical tree of data.</TextBlock> <TextBlock Classes="h2">Displays a hierachical tree of data.</TextBlock>
<StackPanel Orientation="Horizontal" <StackPanel Orientation="Horizontal"
Margin="0,16,0,0" Margin="0,16,0,0"
HorizontalAlignment="Center" HorizontalAlignment="Center"
Gap="16"> Spacing="16">
<TreeView Items="{Binding}" Width="250" Height="350"> <TreeView Items="{Binding}" Width="250" Height="350">
<TreeView.ItemTemplate> <TreeView.ItemTemplate>
<TreeDataTemplate ItemsSource="{Binding Children}"> <TreeDataTemplate ItemsSource="{Binding Children}">

4
samples/ControlCatalog/SideBar.xaml

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

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

@ -9,7 +9,7 @@ using Avalonia.Remote.Protocol;
using Avalonia.Threading; using Avalonia.Threading;
using ControlCatalog; using ControlCatalog;
namespace RemoteTest namespace RemoteDemo
{ {
class Program 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> <Application.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> <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: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.Styles>
</Application> </Application>

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

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

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

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

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

@ -5,10 +5,10 @@ using System;
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using RenderTest.ViewModels; using RenderDemo.ViewModels;
using ReactiveUI; using ReactiveUI;
namespace RenderTest namespace RenderDemo
{ {
public class MainWindow : Window 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.Input;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
using RenderTest.ViewModels; using RenderDemo.ViewModels;
namespace RenderTest.Pages namespace RenderDemo.Pages
{ {
public class AnimationsPage : UserControl 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.Markup.Xaml;
using Avalonia.Media; using Avalonia.Media;
namespace RenderTest.Pages namespace RenderDemo.Pages
{ {
public class ClippingPage : UserControl 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.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace RenderTest.Pages namespace RenderDemo.Pages
{ {
public class DrawingPage : UserControl 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" <TabStrip Name="PART_TabStrip"
MemberSelector="{x:Static TabControl.HeaderSelector}" MemberSelector="{x:Static TabControl.HeaderSelector}"
Items="{TemplateBinding Items}" Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex, Mode=TwoWay}"> SelectedIndex="{TemplateBinding SelectedIndex, Mode=TwoWay}">
<TabStrip.ItemsPanel> <TabStrip.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<StackPanel Orientation="Vertical"/> <StackPanel Orientation="Vertical"/>
@ -21,7 +21,7 @@
Margin="8 0 0 0" Margin="8 0 0 0"
MemberSelector="{x:Static TabControl.ContentSelector}" MemberSelector="{x:Static TabControl.ContentSelector}"
Items="{TemplateBinding Items}" Items="{TemplateBinding Items}"
SelectedIndex="{TemplateBinding Path=SelectedIndex}" SelectedIndex="{TemplateBinding SelectedIndex}"
PageTransition="{TemplateBinding PageTransition}" PageTransition="{TemplateBinding PageTransition}"
Grid.Row="1"/> Grid.Row="1"/>
</DockPanel> </DockPanel>

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

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

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

@ -1,7 +1,7 @@
using System; using System;
using ReactiveUI; using ReactiveUI;
namespace RenderTest.ViewModels namespace RenderDemo.ViewModels
{ {
public class MainWindowViewModel : ReactiveObject 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;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
namespace VirtualizationTest namespace VirtualizationDemo
{ {
public class App : Application public class App : Application
{ {

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

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

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

@ -4,9 +4,9 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using VirtualizationTest.ViewModels; using VirtualizationDemo.ViewModels;
namespace VirtualizationTest namespace VirtualizationDemo
{ {
public class MainWindow : Window 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 Avalonia.Logging.Serilog;
using Serilog; using Serilog;
namespace VirtualizationTest namespace VirtualizationDemo
{ {
class Program class Program
{ {

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

@ -4,7 +4,7 @@
using System; using System;
using ReactiveUI; using ReactiveUI;
namespace VirtualizationTest.ViewModels namespace VirtualizationDemo.ViewModels
{ {
internal class ItemViewModel : ReactiveObject 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 Avalonia.Controls.Primitives;
using ReactiveUI; using ReactiveUI;
namespace VirtualizationTest.ViewModels namespace VirtualizationDemo.ViewModels
{ {
internal class MainWindowViewModel : ReactiveObject 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> </ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\..\..\build\Serilog.props" /> <Import Project="..\..\..\build\Serilog.props" />
<Import Project="..\..\..\build\Sprache.props" />
<Import Project="..\..\..\build\Rx.props" /> <Import Project="..\..\..\build\Rx.props" />
<Import Project="..\..\..\build\System.Memory.props" />
</Project> </Project>

126
src/Avalonia.Animation/Animation.cs

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

66
src/Avalonia.Animation/AnimatorKeyFrame.cs

@ -4,6 +4,8 @@ using System.Text;
using System.ComponentModel; using System.ComponentModel;
using Avalonia.Metadata; using Avalonia.Metadata;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Data;
using Avalonia.Reactive;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
@ -11,13 +13,63 @@ namespace Avalonia.Animation
/// Defines a KeyFrame that is used for /// Defines a KeyFrame that is used for
/// <see cref="Animator{T}"/> objects. /// <see cref="Animator{T}"/> objects.
/// </summary> /// </summary>
public class AnimatorKeyFrame public class AnimatorKeyFrame : AvaloniaObject
{ {
public Type Handler; public static readonly DirectProperty<AnimatorKeyFrame, object> ValueProperty =
public Cue Cue; AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object>(nameof(Value), k => k.Value, (k, v) => k.Value = v);
public TimeSpan KeyTime;
internal bool timeSpanSet, cueSet; public AnimatorKeyFrame()
public AvaloniaProperty Property; {
public object Value;
}
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; private T _neutralValue;
internal bool _unsubscribe = false; internal bool _unsubscribe = false;
private IObserver<object> _targetObserver; private IObserver<object> _targetObserver;
private readonly Action _onComplete;
[Flags] [Flags]
private enum KeyFramesStates private enum KeyFramesStates
@ -51,9 +52,9 @@ namespace Avalonia.Animation
Disposed 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; _targetAnimation = animation;
_targetControl = control; _targetControl = control;
_neutralValue = (T)_targetControl.GetValue(_parent.Property); _neutralValue = (T)_targetControl.GetValue(_parent.Property);
@ -82,6 +83,7 @@ namespace Avalonia.Animation
_currentState = KeyFramesStates.DoDelay; _currentState = KeyFramesStates.DoDelay;
else else
_currentState = KeyFramesStates.DoRun; _currentState = KeyFramesStates.DoRun;
_onComplete = onComplete;
} }
public void Step(PlayState _playState, Func<double, T, T> Interpolator) public void Step(PlayState _playState, Func<double, T, T> Interpolator)
@ -123,121 +125,136 @@ namespace Avalonia.Animation
double _tempDuration = 0d, _easedTime; double _tempDuration = 0d, _easedTime;
checkstate: bool handled = false;
switch (_currentState)
while (!handled)
{ {
case KeyFramesStates.DoDelay: switch (_currentState)
{
case KeyFramesStates.DoDelay:
if (_fillMode == FillMode.Backward if (_fillMode == FillMode.Backward
|| _fillMode == FillMode.Both) || _fillMode == FillMode.Both)
{
if (_currentIteration == 0)
{ {
_targetObserver.OnNext(_firstKFValue); if (_currentIteration == 0)
{
_targetObserver.OnNext(_firstKFValue);
}
else
{
_targetObserver.OnNext(_lastInterpValue);
}
}
if (_delayFrameCount > _delayTotalFrameCount)
{
_currentState = KeyFramesStates.DoRun;
} }
else else
{ {
_targetObserver.OnNext(_lastInterpValue); handled = true;
_delayFrameCount++;
} }
} break;
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;
}
_tempDuration = (double)_durationFrameCount / _durationTotalFrameCount; case KeyFramesStates.DoRun:
_currentState = KeyFramesStates.RunApplyValue;
goto checkstate; if (_isReversed)
_currentState = KeyFramesStates.RunBackwards;
else
_currentState = KeyFramesStates.RunForwards;
case KeyFramesStates.RunBackwards: break;
if (_durationFrameCount > _durationTotalFrameCount) case KeyFramesStates.RunForwards:
{
_currentState = KeyFramesStates.RunComplete;
goto checkstate;
}
_tempDuration = (double)(_durationTotalFrameCount - _durationFrameCount) / _durationTotalFrameCount; if (_durationFrameCount > _durationTotalFrameCount)
_currentState = KeyFramesStates.RunApplyValue; {
_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++; case KeyFramesStates.RunApplyValue:
_lastInterpValue = Interpolator(_easedTime, _neutralValue);
_targetObserver.OnNext(_lastInterpValue);
_currentState = KeyFramesStates.DoRun;
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) case KeyFramesStates.RunComplete:
{
_delayFrameCount = 0;
_durationFrameCount = 0;
if (_isLooping) if (_checkLoopAndRepeat)
{
_currentState = KeyFramesStates.DoRun;
}
else if (_isRepeating)
{ {
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 if (_animationDirection == PlaybackDirection.Alternate
|| _animationDirection == PlaybackDirection.AlternateReverse) || _animationDirection == PlaybackDirection.AlternateReverse)
_isReversed = !_isReversed; _isReversed = !_isReversed;
break;
}
_currentState = KeyFramesStates.Stop;
break; break;
}
_currentState = KeyFramesStates.Stop; case KeyFramesStates.Stop:
goto checkstate;
case KeyFramesStates.Stop: if (_fillMode == FillMode.Forward
|| _fillMode == FillMode.Both)
{
_targetControl.SetValue(_parent.Property, _lastInterpValue, BindingPriority.LocalValue);
}
if (_fillMode == FillMode.Forward _targetObserver.OnCompleted();
|| _fillMode == FillMode.Both) _onComplete?.Invoke();
{ Dispose();
_targetControl.SetValue(_parent.Property, _lastInterpValue, BindingPriority.LocalValue); handled = true;
} break;
_targetObserver.OnCompleted(); default:
break; handled = true;
break;
}
} }
} }
@ -253,4 +270,4 @@ namespace Avalonia.Animation
_currentState = KeyFramesStates.Disposed; _currentState = KeyFramesStates.Disposed;
} }
} }
} }

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

@ -19,7 +19,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// List of type-converted keyframes. /// List of type-converted keyframes.
/// </summary> /// </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; private bool _isVerfifiedAndConverted;
@ -35,18 +35,17 @@ namespace Avalonia.Animation
} }
/// <inheritdoc/> /// <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) if (!_isVerfifiedAndConverted)
VerifyConvertKeyFrames(animation, typeof(T)); VerifyConvertKeyFrames();
return obsMatch return obsMatch
.Where(p => p == true)
// Ignore triggers when global timers are paused. // Ignore triggers when global timers are paused.
.Where(p => Timing.GetGlobalPlayState() != PlayState.Pause) .Where(p => p && Timing.GetGlobalPlayState() != PlayState.Pause)
.Subscribe(_ => .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> /// <param name="t">The time parameter, relative to the total animation time</param>
protected (double IntraKFTime, KeyFramePair<T> KFPair) GetKFPairAndIntraKFTime(double t) protected (double IntraKFTime, KeyFramePair<T> KFPair) GetKFPairAndIntraKFTime(double t)
{ {
KeyValuePair<double, (T, bool)> firstCue, lastCue; KeyValuePair<double, (AnimatorKeyFrame frame, bool isNeutral)> firstCue, lastCue;
int kvCount = _convertedKeyframes.Count(); int kvCount = _convertedKeyframes.Count;
if (kvCount > 2) if (kvCount > 2)
{ {
if (DoubleUtils.AboutEqual(t, 0.0) || t < 0.0) if (DoubleUtils.AboutEqual(t, 0.0) || t < 0.0)
@ -76,8 +75,8 @@ namespace Avalonia.Animation
} }
else else
{ {
firstCue = _convertedKeyframes.Where(j => j.Key <= t).Last(); firstCue = _convertedKeyframes.Last(j => j.Key <= t);
lastCue = _convertedKeyframes.Where(j => j.Key >= t).First(); lastCue = _convertedKeyframes.First(j => j.Key >= t);
} }
} }
else else
@ -89,26 +88,24 @@ namespace Avalonia.Animation
double t0 = firstCue.Key; double t0 = firstCue.Key;
double t1 = lastCue.Key; double t1 = lastCue.Key;
var intraframeTime = (t - t0) / (t1 - t0); 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> /// <summary>
/// Runs the KeyFrames Animation. /// Runs the KeyFrames Animation.
/// </summary> /// </summary>
private IDisposable RunKeyFrames(Animation animation, Animatable control) private IDisposable RunKeyFrames(Animation animation, Animatable control, Action onComplete)
{ {
var _kfStateMach = new AnimatorStateMachine<T>(); var stateMachine = new AnimatorStateMachine<T>(animation, control, this, onComplete);
_kfStateMach.Initialize(animation, control, this);
Timing.AnimationStateTimer Timing.AnimationStateTimer
.TakeWhile(_ => !_kfStateMach._unsubscribe) .TakeWhile(_ => !stateMachine._unsubscribe)
.Subscribe(p => .Subscribe(p => stateMachine.Step(p, DoInterpolation));
{
_kfStateMach.Step(p, DoInterpolation);
});
return control.Bind(Property, _kfStateMach, BindingPriority.Animation); return control.Bind(Property, stateMachine, BindingPriority.Animation);
} }
/// <summary> /// <summary>
@ -119,39 +116,19 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Verifies and converts keyframe values according to this class's target type. /// Verifies and converts keyframe values according to this class's target type.
/// </summary> /// </summary>
private void VerifyConvertKeyFrames(Animation animation, Type type) private void VerifyConvertKeyFrames()
{ {
var typeConv = TypeDescriptor.GetConverter(type); foreach (AnimatorKeyFrame keyframe in this)
foreach (AnimatorKeyFrame k in this)
{ {
if (k.Value == null) _convertedKeyframes.Add(keyframe.Cue.CueValue, (keyframe, false));
{
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));
} }
SortKeyFrameCues(_convertedKeyframes); AddNeutralKeyFramesIfNeeded();
_isVerfifiedAndConverted = true; _isVerfifiedAndConverted = true;
} }
private void SortKeyFrameCues(Dictionary<double, (T, bool)> convertedValues) private void AddNeutralKeyFramesIfNeeded()
{ {
bool hasStartKey, hasEndKey; bool hasStartKey, hasEndKey;
hasStartKey = hasEndKey = false; hasStartKey = hasEndKey = false;
@ -170,23 +147,20 @@ namespace Avalonia.Animation
} }
if (!hasStartKey || !hasEndKey) if (!hasStartKey || !hasEndKey)
AddNeutralKeyFrames(hasStartKey, hasEndKey, _convertedKeyframes); AddNeutralKeyFrames(hasStartKey, hasEndKey);
_convertedKeyframes = _convertedKeyframes.OrderBy(p => p.Key)
.ToDictionary((k) => k.Key, (v) => v.Value);
} }
private void AddNeutralKeyFrames(bool hasStartKey, bool hasEndKey, Dictionary<double, (T, bool)> convertedKeyframes) private void AddNeutralKeyFrames(bool hasStartKey, bool hasEndKey)
{ {
if (!hasStartKey) if (!hasStartKey)
{ {
convertedKeyframes.Add(0.0d, (default(T), true)); _convertedKeyframes.Add(0.0d, (new AnimatorKeyFrame { Value = default(T) }, true));
} }
if (!hasEndKey) 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"/>. /// A Cue object for <see cref="KeyFrame"/>.
/// </summary> /// </summary>
[TypeConverter(typeof(CueTypeConverter))] [TypeConverter(typeof(CueTypeConverter))]
public struct Cue : IEquatable<Cue>, IEquatable<double> public readonly struct Cue : IEquatable<Cue>, IEquatable<double>
{ {
/// <summary> /// <summary>
/// The normalized percent value, ranging from 0.0 to 1.0 /// 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 firstKF = pair.KFPair.FirstKeyFrame;
var secondKF = pair.KFPair.SecondKeyFrame; var secondKF = pair.KFPair.SecondKeyFrame;
if (firstKF.Value.isNeutral) if (firstKF.isNeutral)
y0 = neutralValue; y0 = neutralValue;
else else
y0 = firstKF.Value.TargetValue; y0 = firstKF.TargetValue;
if (secondKF.Value.isNeutral) if (secondKF.isNeutral)
y1 = neutralValue; y1 = neutralValue;
else else
y1 = secondKF.Value.TargetValue; y1 = secondKF.TargetValue;
// Do linear parametric interpolation // Do linear parametric interpolation
return y0 + (pair.IntraKFTime) * (y1 - y0); 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.Collections.Generic;
using System.Text; using System.Text;
using System.Threading.Tasks;
namespace Avalonia.Animation namespace Avalonia.Animation
{ {
@ -12,6 +13,11 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Apply the animation to the specified control /// Apply the animation to the specified control
/// </summary> /// </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; } AvaloniaProperty Property { get; set; }
object Value { get; set; } object Value { get; set; }
} }
} }

2
src/Avalonia.Animation/IAnimator.cs

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

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

@ -22,7 +22,7 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <param name="FirstKeyFrame"></param> /// <param name="FirstKeyFrame"></param>
/// <param name="LastKeyFrame"></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.FirstKeyFrame = FirstKeyFrame;
this.SecondKeyFrame = LastKeyFrame; this.SecondKeyFrame = LastKeyFrame;
@ -31,11 +31,11 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// First <see cref="KeyFrame"/> object. /// First <see cref="KeyFrame"/> object.
/// </summary> /// </summary>
public KeyValuePair<double, (T TargetValue, bool isNeutral)> FirstKeyFrame { get; private set; } public (T TargetValue, bool isNeutral) FirstKeyFrame { get; }
/// <summary> /// <summary>
/// Second <see cref="KeyFrame"/> object. /// Second <see cref="KeyFrame"/> object.
/// </summary> /// </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\Binding.props" />
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.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.Data;
using Avalonia.Diagnostics; using Avalonia.Diagnostics;
using Avalonia.Logging; using Avalonia.Logging;
using Avalonia.Reactive;
using Avalonia.Threading; using Avalonia.Threading;
using Avalonia.Utilities; using Avalonia.Utilities;
@ -21,24 +22,18 @@ namespace Avalonia
/// <remarks> /// <remarks>
/// This class is analogous to DependencyObject in WPF. /// This class is analogous to DependencyObject in WPF.
/// </remarks> /// </remarks>
public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged, IPriorityValueOwner public class AvaloniaObject : IAvaloniaObject, IAvaloniaObjectDebug, INotifyPropertyChanged
{ {
/// <summary> /// <summary>
/// The parent object that inherited values are inherited from. /// The parent object that inherited values are inherited from.
/// </summary> /// </summary>
private IAvaloniaObject _inheritanceParent; private IAvaloniaObject _inheritanceParent;
/// <summary>
/// The set values/bindings on this object.
/// </summary>
private readonly Dictionary<AvaloniaProperty, PriorityValue> _values =
new Dictionary<AvaloniaProperty, PriorityValue>();
/// <summary> /// <summary>
/// Maintains a list of direct property binding subscriptions so that the binding source /// Maintains a list of direct property binding subscriptions so that the binding source
/// doesn't get collected. /// doesn't get collected.
/// </summary> /// </summary>
private List<IDisposable> _directBindings; private List<DirectBindingSubscription> _directBindings;
/// <summary> /// <summary>
/// Event handler for <see cref="INotifyPropertyChanged"/> implementation. /// Event handler for <see cref="INotifyPropertyChanged"/> implementation.
@ -50,20 +45,8 @@ namespace Avalonia
/// </summary> /// </summary>
private EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChanged; private EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChanged;
private DeferredSetter<AvaloniaProperty, object> _directDeferredSetter; private ValueStore _values;
private ValueStore Values => _values ?? (_values = new ValueStore(this));
/// <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>());
}
}
/// <summary> /// <summary>
/// Initializes a new instance of the <see cref="AvaloniaObject"/> class. /// Initializes a new instance of the <see cref="AvaloniaObject"/> class.
@ -227,9 +210,20 @@ namespace Avalonia
{ {
return ((IDirectPropertyAccessor)GetRegistered(property)).GetValue(this); 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 else
{ {
return GetValueInternal(property); return GetDefaultValue(property);
} }
} }
@ -256,7 +250,7 @@ namespace Avalonia
Contract.Requires<ArgumentNullException>(property != null); Contract.Requires<ArgumentNullException>(property != null);
VerifyAccess(); VerifyAccess();
return _values.TryGetValue(property, out PriorityValue value) ? value.IsAnimating : false; return _values?.IsAnimating(property) ?? false;
} }
/// <summary> /// <summary>
@ -273,14 +267,7 @@ namespace Avalonia
Contract.Requires<ArgumentNullException>(property != null); Contract.Requires<ArgumentNullException>(property != null);
VerifyAccess(); VerifyAccess();
PriorityValue value; return _values?.IsSet(property) ?? false;
if (_values.TryGetValue(property, out value))
{
return value.Value != AvaloniaProperty.UnsetValue;
}
return false;
} }
/// <summary> /// <summary>
@ -359,36 +346,15 @@ namespace Avalonia
property, property,
description); description);
IDisposable subscription = null;
if (_directBindings == null) if (_directBindings == null)
{ {
_directBindings = new List<IDisposable>(); _directBindings = new List<DirectBindingSubscription>();
} }
subscription = source return new DirectBindingSubscription(this, property, 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);
});
} }
else else
{ {
PriorityValue v;
if (!_values.TryGetValue(property, out v))
{
v = CreatePriorityValue(property);
_values.Add(property, v);
}
Logger.Verbose( Logger.Verbose(
LogArea.Property, LogArea.Property,
this, this,
@ -397,7 +363,7 @@ namespace Avalonia
description, description,
priority); priority);
return v.Add(source, (int)priority); return Values.AddBinding(property, source, priority);
} }
} }
@ -428,20 +394,11 @@ namespace Avalonia
public void Revalidate(AvaloniaProperty property) public void Revalidate(AvaloniaProperty property)
{ {
VerifyAccess(); VerifyAccess();
PriorityValue value; _values?.Revalidate(property);
if (_values.TryGetValue(property, out value))
{
value.Revalidate();
}
} }
/// <inheritdoc/> internal void PriorityValueChanged(AvaloniaProperty property, int priority, object oldValue, object newValue)
void IPriorityValueOwner.Changed(PriorityValue sender, object oldValue, object newValue)
{ {
var property = sender.Property;
var priority = (BindingPriority)sender.ValuePriority;
oldValue = (oldValue == AvaloniaProperty.UnsetValue) ? oldValue = (oldValue == AvaloniaProperty.UnsetValue) ?
GetDefaultValue(property) : GetDefaultValue(property) :
oldValue; oldValue;
@ -451,7 +408,7 @@ namespace Avalonia
if (!Equals(oldValue, newValue)) if (!Equals(oldValue, newValue))
{ {
RaisePropertyChanged(property, oldValue, newValue, priority); RaisePropertyChanged(property, oldValue, newValue, (BindingPriority)priority);
Logger.Verbose( Logger.Verbose(
LogArea.Property, LogArea.Property,
@ -460,14 +417,13 @@ namespace Avalonia
property, property,
oldValue, oldValue,
newValue, newValue,
priority); (BindingPriority)priority);
} }
} }
/// <inheritdoc/> internal void BindingNotificationReceived(AvaloniaProperty property, BindingNotification notification)
void IPriorityValueOwner.BindingNotificationReceived(PriorityValue sender, BindingNotification notification)
{ {
UpdateDataValidation(sender.Property, notification); UpdateDataValidation(property, notification);
} }
/// <inheritdoc/> /// <inheritdoc/>
@ -480,10 +436,7 @@ namespace Avalonia
/// Gets all priority values set on the object. /// Gets all priority values set on the object.
/// </summary> /// </summary>
/// <returns>A collection of property/value tuples.</returns> /// <returns>A collection of property/value tuples.</returns>
internal IDictionary<AvaloniaProperty, PriorityValue> GetSetValues() internal IDictionary<AvaloniaProperty, object> GetSetValues() => Values?.GetSetValues();
{
return _values;
}
/// <summary> /// <summary>
/// Forces revalidation of properties when a property value changes. /// Forces revalidation of properties when a property value changes.
@ -593,12 +546,12 @@ namespace Avalonia
T value) T value)
{ {
Contract.Requires<ArgumentNullException>(setterCallback != null); Contract.Requires<ArgumentNullException>(setterCallback != null);
return DirectPropertyDeferredSetter.SetAndNotify( return Values.Setter.SetAndNotify(
property, property,
ref field, 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; return true;
}, },
value); 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> /// <summary>
/// Gets the default value for a property. /// Gets the default value for a property.
/// </summary> /// </summary>
/// <param name="property">The property.</param> /// <param name="property">The property.</param>
/// <returns>The default value.</returns> /// <returns>The default value.</returns>
private object GetDefaultValue(AvaloniaProperty property) internal object GetDefaultValue(AvaloniaProperty property)
{ {
if (property.Inherits && InheritanceParent is AvaloniaObject aobj) if (property.Inherits && InheritanceParent is AvaloniaObject aobj)
return aobj.GetValueInternal(property); return aobj.GetValue(property);
return ((IStyledPropertyAccessor) property).GetDefaultValue(GetType()); 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> /// <summary>
/// Sets the value of a direct property. /// Sets the value of a direct property.
/// </summary> /// </summary>
@ -814,21 +717,8 @@ namespace Avalonia
originalValue?.GetType().FullName ?? "(null)")); 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); LogPropertySet(property, value, priority);
v.SetValue(value, (int)priority); Values.AddValue(property, value, (int)priority);
} }
/// <summary> /// <summary>
@ -908,5 +798,38 @@ namespace Avalonia
value, value,
priority); 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