diff --git a/Avalonia.sln b/Avalonia.sln
index ccaa41f552..ffd7b4d4f4 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -150,6 +150,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\System.Memory.props = build\System.Memory.props
build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
build\XUnit.props = build\XUnit.props
+ build\ApiDiff.props = build\ApiDiff.props
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"
diff --git a/NuGet.Config b/NuGet.Config
index 2a1e0af74d..3abd236d42 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -1,7 +1,9 @@
+
+
diff --git a/build/ApiDiff.props b/build/ApiDiff.props
new file mode 100644
index 0000000000..da82fbcc51
--- /dev/null
+++ b/build/ApiDiff.props
@@ -0,0 +1,12 @@
+
+
+ 0.10.0-preview3
+ $(PackageId)
+ Avalonia
+
+
+
+
+
+
+
diff --git a/build/ReactiveUI.props b/build/ReactiveUI.props
index f827cb9a32..d8e86e917e 100644
--- a/build/ReactiveUI.props
+++ b/build/ReactiveUI.props
@@ -1,5 +1,5 @@
-
+
diff --git a/build/SharedVersion.props b/build/SharedVersion.props
index bd183faab3..d3cebef418 100644
--- a/build/SharedVersion.props
+++ b/build/SharedVersion.props
@@ -2,7 +2,7 @@
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
Avalonia
- 0.9.999
+ 0.10.999
Copyright 2020 © The AvaloniaUI Project
https://avaloniaui.net
https://github.com/AvaloniaUI/Avalonia/
diff --git a/build/SkiaSharp.props b/build/SkiaSharp.props
index a8d9332c57..bbef48050e 100644
--- a/build/SkiaSharp.props
+++ b/build/SkiaSharp.props
@@ -1,6 +1,6 @@
-
+
diff --git a/native/Avalonia.Native/src/OSX/window.mm b/native/Avalonia.Native/src/OSX/window.mm
index 2d0ffbe4f0..dd241409c7 100644
--- a/native/Avalonia.Native/src/OSX/window.mm
+++ b/native/Avalonia.Native/src/OSX/window.mm
@@ -27,6 +27,7 @@ public:
AvnPoint lastPositionSet;
NSString* _lastTitle;
IAvnMenu* _mainMenu;
+
bool _shown;
WindowBaseImpl(IAvnWindowBaseEvents* events, IAvnGlContext* gl)
@@ -230,6 +231,29 @@ public:
{
@autoreleasepool
{
+ auto maxSize = [Window maxSize];
+ auto minSize = [Window minSize];
+
+ if (x < minSize.width)
+ {
+ x = minSize.width;
+ }
+
+ if (y < minSize.height)
+ {
+ y = minSize.height;
+ }
+
+ if (x > maxSize.width)
+ {
+ x = maxSize.width;
+ }
+
+ if (y > maxSize.height)
+ {
+ y = maxSize.height;
+ }
+
[Window setContentSize:NSSize{x, y}];
return S_OK;
diff --git a/nukebuild/Build.cs b/nukebuild/Build.cs
index fe877dc49c..fbfbf47e1b 100644
--- a/nukebuild/Build.cs
+++ b/nukebuild/Build.cs
@@ -128,7 +128,9 @@ partial class Build : NukeBuild
{
var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp";
- NpmTasks.NpmInstall(c => c.SetWorkingDirectory(webappDir));
+ NpmTasks.NpmInstall(c => c
+ .SetWorkingDirectory(webappDir)
+ .SetArgumentConfigurator(a => a.Add("--silent")));
NpmTasks.NpmRun(c => c
.SetWorkingDirectory(webappDir)
.SetCommand("dist"));
diff --git a/readme.md b/readme.md
index 19a9a8420d..c1bf5bbfde 100644
--- a/readme.md
+++ b/readme.md
@@ -1,4 +1,4 @@
-[](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [](#backers) [](#sponsors) 
+[](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) []( https://aka.ms/dotnet-discord) [](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [](#backers) [](#sponsors) 
[](https://www.nuget.org/packages/Avalonia) [](https://www.nuget.org/packages/Avalonia) [](https://www.myget.org/gallery/avalonia-ci) 
diff --git a/samples/ControlCatalog/App.xaml b/samples/ControlCatalog/App.xaml
index c7a75f5a70..bab57f3544 100644
--- a/samples/ControlCatalog/App.xaml
+++ b/samples/ControlCatalog/App.xaml
@@ -4,14 +4,14 @@
diff --git a/samples/ControlCatalog/App.xaml.cs b/samples/ControlCatalog/App.xaml.cs
index 3f1ec289d1..b0fbcc76d2 100644
--- a/samples/ControlCatalog/App.xaml.cs
+++ b/samples/ControlCatalog/App.xaml.cs
@@ -67,9 +67,9 @@ namespace ControlCatalog
public override void Initialize()
{
- AvaloniaXamlLoader.Load(this);
-
Styles.Insert(0, FluentDark);
+
+ AvaloniaXamlLoader.Load(this);
}
public override void OnFrameworkInitializationCompleted()
diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml
index af95e3c356..efc90357ed 100644
--- a/samples/ControlCatalog/MainView.xaml
+++ b/samples/ControlCatalog/MainView.xaml
@@ -1,9 +1,7 @@
+ x:Class="ControlCatalog.MainView">
diff --git a/samples/ControlCatalog/Pages/ContextMenuPage.xaml b/samples/ControlCatalog/Pages/ContextMenuPage.xaml
index 8ccd8e97f7..260162ddb9 100644
--- a/samples/ControlCatalog/Pages/ContextMenuPage.xaml
+++ b/samples/ControlCatalog/Pages/ContextMenuPage.xaml
@@ -14,13 +14,14 @@
Padding="48,48,48,48">
-
+
+
-
+
diff --git a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
index 304782dbf9..392ccb57c3 100644
--- a/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
+++ b/samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
@@ -43,7 +43,7 @@
-
+
diff --git a/samples/ControlCatalog/Pages/ListBoxPage.xaml b/samples/ControlCatalog/Pages/ListBoxPage.xaml
index f4d81418ac..edf3d41bf5 100644
--- a/samples/ControlCatalog/Pages/ListBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/ListBoxPage.xaml
@@ -11,8 +11,7 @@
Spacing="16">
(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
- SelectedItems = new ObservableCollection();
-
- AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));
-
- RemoveItemCommand = ReactiveCommand.Create(() =>
- {
- while (SelectedItems.Count > 0)
- {
- Items.Remove(SelectedItems[0]);
- }
- });
-
- SelectRandomItemCommand = ReactiveCommand.Create(() =>
- {
- var random = new Random();
-
- SelectedItem = Items[random.Next(Items.Count - 1)];
- });
- }
-
- public ObservableCollection Items { get; }
-
- private string _selectedItem;
-
- public string SelectedItem
- {
- get { return _selectedItem; }
- set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
- }
-
-
- public ObservableCollection SelectedItems { get; }
-
- public ReactiveCommand AddItemCommand { get; }
-
- public ReactiveCommand RemoveItemCommand { get; }
-
- public ReactiveCommand SelectRandomItemCommand { get; }
-
- public SelectionMode SelectionMode
- {
- get => _selectionMode;
- set
- {
- SelectedItems.Clear();
- this.RaiseAndSetIfChanged(ref _selectionMode, value);
- }
- }
-
- private string GenerateItem() => $"Item {_counter++.ToString()}";
- }
}
}
diff --git a/samples/ControlCatalog/Pages/MenuPage.xaml b/samples/ControlCatalog/Pages/MenuPage.xaml
index de9ea34e80..2c09cb9b4d 100644
--- a/samples/ControlCatalog/Pages/MenuPage.xaml
+++ b/samples/ControlCatalog/Pages/MenuPage.xaml
@@ -16,11 +16,17 @@
Defined in XAML
+
+
+
+ Mixed
+
+
diff --git a/samples/ControlCatalog/Pages/ScreenPage.cs b/samples/ControlCatalog/Pages/ScreenPage.cs
index d775eb9635..c39f414b44 100644
--- a/samples/ControlCatalog/Pages/ScreenPage.cs
+++ b/samples/ControlCatalog/Pages/ScreenPage.cs
@@ -29,7 +29,8 @@ namespace ControlCatalog.Pages
var screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling;
- Pen p = new Pen(Brushes.Black);
+ var drawBrush = Brushes.Green;
+ Pen p = new Pen(drawBrush);
if (screens != null)
foreach (Screen screen in screens)
{
@@ -53,19 +54,19 @@ namespace ControlCatalog.Pages
};
text.Text = $"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}";
- context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height), text);
+ context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height), text);
text.Text = $"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
- context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
+ context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
text.Text = $"Scaling: {screen.PixelDensity * 100}%";
- context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
+ context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
text.Text = $"Primary: {screen.Primary}";
- context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
+ context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
- context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
+ context.DrawText(drawBrush, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
}
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10));
diff --git a/samples/ControlCatalog/Pages/TextBlockPage.xaml b/samples/ControlCatalog/Pages/TextBlockPage.xaml
index 4b8edcf98c..4a1c196917 100644
--- a/samples/ControlCatalog/Pages/TextBlockPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBlockPage.xaml
@@ -12,7 +12,7 @@
@@ -49,7 +49,7 @@
diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index 64118a00b4..481a459159 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -20,6 +20,7 @@
@@ -37,6 +38,8 @@
Text="Multiline TextBox with TextWrapping.
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." />
+
+
resm fonts
diff --git a/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
new file mode 100644
index 0000000000..6bdb5c0103
--- /dev/null
+++ b/samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Reactive;
+using Avalonia.Controls;
+using ReactiveUI;
+
+namespace ControlCatalog.ViewModels
+{
+ public class ListBoxPageViewModel : ReactiveObject
+ {
+ private int _counter;
+ private SelectionMode _selectionMode;
+
+ public ListBoxPageViewModel()
+ {
+ Items = new ObservableCollection(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
+ Selection = new SelectionModel();
+ Selection.Select(1);
+
+ AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));
+
+ RemoveItemCommand = ReactiveCommand.Create(() =>
+ {
+ while (Selection.SelectedItems.Count > 0)
+ {
+ Items.Remove((string)Selection.SelectedItems.First());
+ }
+ });
+
+ SelectRandomItemCommand = ReactiveCommand.Create(() =>
+ {
+ var random = new Random();
+
+ using (Selection.Update())
+ {
+ Selection.ClearSelection();
+ Selection.Select(random.Next(Items.Count - 1));
+ }
+ });
+ }
+
+ public ObservableCollection Items { get; }
+
+ public SelectionModel Selection { get; }
+
+ public ReactiveCommand AddItemCommand { get; }
+
+ public ReactiveCommand RemoveItemCommand { get; }
+
+ public ReactiveCommand SelectRandomItemCommand { get; }
+
+ public SelectionMode SelectionMode
+ {
+ get => _selectionMode;
+ set
+ {
+ Selection.ClearSelection();
+ this.RaiseAndSetIfChanged(ref _selectionMode, value);
+ }
+ }
+
+ private string GenerateItem() => $"Item {_counter++.ToString()}";
+ }
+}
diff --git a/samples/ControlCatalog/ViewModels/MenuPageViewModel.cs b/samples/ControlCatalog/ViewModels/MenuPageViewModel.cs
index dc9c4a8f49..9e7ae8b716 100644
--- a/samples/ControlCatalog/ViewModels/MenuPageViewModel.cs
+++ b/samples/ControlCatalog/ViewModels/MenuPageViewModel.cs
@@ -17,6 +17,23 @@ namespace ControlCatalog.ViewModels
SaveCommand = ReactiveCommand.Create(Save, Observable.Return(false));
OpenRecentCommand = ReactiveCommand.Create(OpenRecent);
+ var recentItems = new[]
+ {
+ new MenuItemViewModel
+ {
+ Header = "File1.txt",
+ Command = OpenRecentCommand,
+ CommandParameter = @"c:\foo\File1.txt"
+ },
+ new MenuItemViewModel
+ {
+ Header = "File2.txt",
+ Command = OpenRecentCommand,
+ CommandParameter = @"c:\foo\File2.txt"
+ },
+ };
+
+ RecentItems = recentItems;
MenuItems = new[]
{
new MenuItemViewModel
@@ -24,27 +41,13 @@ namespace ControlCatalog.ViewModels
Header = "_File",
Items = new[]
{
- new MenuItemViewModel { Header = "_Open...", Command = OpenCommand },
+ new MenuItemViewModel { Header = "O_pen...", Command = OpenCommand },
new MenuItemViewModel { Header = "Save", Command = SaveCommand },
new MenuItemViewModel { Header = "-" },
new MenuItemViewModel
{
Header = "Recent",
- Items = new[]
- {
- new MenuItemViewModel
- {
- Header = "File1.txt",
- Command = OpenRecentCommand,
- CommandParameter = @"c:\foo\File1.txt"
- },
- new MenuItemViewModel
- {
- Header = "File2.txt",
- Command = OpenRecentCommand,
- CommandParameter = @"c:\foo\File2.txt"
- },
- }
+ Items = recentItems
},
}
},
@@ -61,6 +64,7 @@ namespace ControlCatalog.ViewModels
}
public IReadOnlyList MenuItems { get; set; }
+ public IReadOnlyList RecentItems { get; set; }
public ReactiveCommand OpenCommand { get; }
public ReactiveCommand SaveCommand { get; }
public ReactiveCommand OpenRecentCommand { get; }
diff --git a/samples/RenderDemo/MainWindow.xaml b/samples/RenderDemo/MainWindow.xaml
index 14ccc82043..770960d7c4 100644
--- a/samples/RenderDemo/MainWindow.xaml
+++ b/samples/RenderDemo/MainWindow.xaml
@@ -44,6 +44,9 @@
+
+
+
diff --git a/samples/RenderDemo/Pages/WriteableBitmapPage.cs b/samples/RenderDemo/Pages/WriteableBitmapPage.cs
new file mode 100644
index 0000000000..850e398a93
--- /dev/null
+++ b/samples/RenderDemo/Pages/WriteableBitmapPage.cs
@@ -0,0 +1,92 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.LogicalTree;
+using Avalonia.Media;
+using Avalonia.Media.Imaging;
+using Avalonia.Media.Immutable;
+using Avalonia.Platform;
+using Avalonia.Threading;
+
+namespace RenderDemo.Pages
+{
+ public class WriteableBitmapPage : Control
+ {
+ private WriteableBitmap _unpremulBitmap;
+ private WriteableBitmap _premulBitmap;
+ private readonly Stopwatch _st = Stopwatch.StartNew();
+
+ protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
+ {
+ _unpremulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Unpremul);
+ _premulBitmap = new WriteableBitmap(new PixelSize(256, 256), new Vector(96, 96), PixelFormat.Bgra8888, AlphaFormat.Premul);
+
+ base.OnAttachedToLogicalTree(e);
+ }
+
+ protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromLogicalTree(e);
+
+ _unpremulBitmap?.Dispose();
+ _unpremulBitmap = null;
+
+ _premulBitmap?.Dispose();
+ _unpremulBitmap = null;
+ }
+
+ public override void Render(DrawingContext context)
+ {
+ void FillPixels(WriteableBitmap bitmap, byte fillAlpha, bool premul)
+ {
+ using (var fb = bitmap.Lock())
+ {
+ var data = new int[fb.Size.Width * fb.Size.Height];
+
+ for (int y = 0; y < fb.Size.Height; y++)
+ {
+ for (int x = 0; x < fb.Size.Width; x++)
+ {
+ var color = new Color(fillAlpha, 0, 255, 0);
+
+ if (premul)
+ {
+ byte r = (byte) (color.R * color.A / 255);
+ byte g = (byte) (color.G * color.A / 255);
+ byte b = (byte) (color.B * color.A / 255);
+
+ color = new Color(fillAlpha, r, g, b);
+ }
+
+ data[y * fb.Size.Width + x] = (int) color.ToUint32();
+ }
+ }
+
+ Marshal.Copy(data, 0, fb.Address, fb.Size.Width * fb.Size.Height);
+ }
+ }
+
+ base.Render(context);
+
+ byte alpha = (byte)((_st.ElapsedMilliseconds / 10) % 256);
+
+ FillPixels(_unpremulBitmap, alpha, false);
+ FillPixels(_premulBitmap, alpha, true);
+
+ context.FillRectangle(Brushes.Red, new Rect(0, 0, 256 * 3, 256));
+
+ context.DrawImage(_unpremulBitmap,
+ new Rect(0, 0, 256, 256),
+ new Rect(0, 0, 256, 256));
+
+ context.DrawImage(_premulBitmap,
+ new Rect(0, 0, 256, 256),
+ new Rect(256, 0, 256, 256));
+
+ context.FillRectangle(new ImmutableSolidColorBrush(Colors.Lime, alpha / 255d), new Rect(512, 0, 256, 256));
+
+ Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Background);
+ }
+ }
+}
diff --git a/src/Avalonia.Animation/Avalonia.Animation.csproj b/src/Avalonia.Animation/Avalonia.Animation.csproj
index 73c619942e..ee91acf45e 100644
--- a/src/Avalonia.Animation/Avalonia.Animation.csproj
+++ b/src/Avalonia.Animation/Avalonia.Animation.csproj
@@ -1,9 +1,10 @@
- netstandard2.0
+ netstandard2.0
+
diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj
index cbcf7a7386..9bfd387ca9 100644
--- a/src/Avalonia.Base/Avalonia.Base.csproj
+++ b/src/Avalonia.Base/Avalonia.Base.csproj
@@ -3,7 +3,7 @@
netstandard2.0
Avalonia.Base
Avalonia
- True
+ True
@@ -13,4 +13,5 @@
+
diff --git a/src/Avalonia.Base/AvaloniaObject.cs b/src/Avalonia.Base/AvaloniaObject.cs
index d18f0b3f94..65233f9230 100644
--- a/src/Avalonia.Base/AvaloniaObject.cs
+++ b/src/Avalonia.Base/AvaloniaObject.cs
@@ -806,7 +806,9 @@ namespace Avalonia
break;
}
- if (p.IsDataValidationEnabled)
+ var metadata = p.GetMetadata(GetType());
+
+ if (metadata.EnableDataValidation == true)
{
UpdateDataValidation(property, value);
}
diff --git a/src/Avalonia.Base/AvaloniaProperty.cs b/src/Avalonia.Base/AvaloniaProperty.cs
index a873d5fd42..39391490b0 100644
--- a/src/Avalonia.Base/AvaloniaProperty.cs
+++ b/src/Avalonia.Base/AvaloniaProperty.cs
@@ -369,14 +369,14 @@ namespace Avalonia
var metadata = new DirectPropertyMetadata(
unsetValue: unsetValue,
- defaultBindingMode: defaultBindingMode);
+ defaultBindingMode: defaultBindingMode,
+ enableDataValidation: enableDataValidation);
var result = new DirectProperty(
name,
getter,
setter,
- metadata,
- enableDataValidation);
+ metadata);
AvaloniaPropertyRegistry.Instance.Register(typeof(TOwner), result);
return result;
}
diff --git a/src/Avalonia.Base/DirectProperty.cs b/src/Avalonia.Base/DirectProperty.cs
index d21969502a..a8120fbd4f 100644
--- a/src/Avalonia.Base/DirectProperty.cs
+++ b/src/Avalonia.Base/DirectProperty.cs
@@ -23,16 +23,12 @@ namespace Avalonia
/// Gets the current value of the property.
/// Sets the value of the property. May be null.
/// The property metadata.
- ///
- /// Whether the property is interested in data validation.
- ///
public DirectProperty(
string name,
Func getter,
Action setter,
- DirectPropertyMetadata metadata,
- bool enableDataValidation)
- : base(name, typeof(TOwner), metadata, enableDataValidation)
+ DirectPropertyMetadata metadata)
+ : base(name, typeof(TOwner), metadata)
{
Contract.Requires(getter != null);
@@ -47,16 +43,12 @@ namespace Avalonia
/// Gets the current value of the property.
/// Sets the value of the property. May be null.
/// Optional overridden metadata.
- ///
- /// Whether the property is interested in data validation.
- ///
private DirectProperty(
DirectPropertyBase source,
Func getter,
Action setter,
- DirectPropertyMetadata metadata,
- bool enableDataValidation)
- : base(source, typeof(TOwner), metadata, enableDataValidation)
+ DirectPropertyMetadata metadata)
+ : base(source, typeof(TOwner), metadata)
{
Contract.Requires(getter != null);
@@ -107,7 +99,8 @@ namespace Avalonia
{
var metadata = new DirectPropertyMetadata(
unsetValue: unsetValue,
- defaultBindingMode: defaultBindingMode);
+ defaultBindingMode: defaultBindingMode,
+ enableDataValidation: enableDataValidation);
metadata.Merge(GetMetadata(), this);
@@ -115,8 +108,7 @@ namespace Avalonia
(DirectPropertyBase)this,
getter,
setter,
- metadata,
- enableDataValidation);
+ metadata);
AvaloniaPropertyRegistry.Instance.Register(typeof(TNewOwner), result);
return result;
@@ -155,8 +147,7 @@ namespace Avalonia
this,
getter,
setter,
- metadata,
- enableDataValidation);
+ metadata);
AvaloniaPropertyRegistry.Instance.Register(typeof(TNewOwner), result);
return result;
diff --git a/src/Avalonia.Base/DirectPropertyBase.cs b/src/Avalonia.Base/DirectPropertyBase.cs
index d42c030245..dbc2625b86 100644
--- a/src/Avalonia.Base/DirectPropertyBase.cs
+++ b/src/Avalonia.Base/DirectPropertyBase.cs
@@ -23,17 +23,12 @@ namespace Avalonia
/// The name of the property.
/// The type of the class that registers the property.
/// The property metadata.
- ///
- /// Whether the property is interested in data validation.
- ///
protected DirectPropertyBase(
string name,
Type ownerType,
- PropertyMetadata metadata,
- bool enableDataValidation)
+ PropertyMetadata metadata)
: base(name, ownerType, metadata)
{
- IsDataValidationEnabled = enableDataValidation;
}
///
@@ -42,17 +37,12 @@ namespace Avalonia
/// The property to copy.
/// The new owner type.
/// Optional overridden metadata.
- ///
- /// Whether the property is interested in data validation.
- ///
protected DirectPropertyBase(
AvaloniaProperty source,
Type ownerType,
- PropertyMetadata metadata,
- bool enableDataValidation)
+ PropertyMetadata metadata)
: base(source, ownerType, metadata)
{
- IsDataValidationEnabled = enableDataValidation;
}
///
@@ -60,11 +50,6 @@ namespace Avalonia
///
public abstract Type Owner { get; }
- ///
- /// Gets a value that indicates whether data validation is enabled for the property.
- ///
- public bool IsDataValidationEnabled { get; }
-
///
/// Gets the value of the property on the instance.
///
@@ -102,6 +87,26 @@ namespace Avalonia
return (DirectPropertyMetadata)base.GetMetadata(type);
}
+ ///
+ /// Overrides the metadata for the property on the specified type.
+ ///
+ /// The type.
+ /// The metadata.
+ public void OverrideMetadata(DirectPropertyMetadata metadata) where T : IAvaloniaObject
+ {
+ base.OverrideMetadata(typeof(T), metadata);
+ }
+
+ ///
+ /// Overrides the metadata for the property on the specified type.
+ ///
+ /// The type.
+ /// The metadata.
+ public void OverrideMetadata(Type type, DirectPropertyMetadata metadata)
+ {
+ base.OverrideMetadata(type, metadata);
+ }
+
///
public override void Accept(IAvaloniaPropertyVisitor vistor, ref TData data)
{
diff --git a/src/Avalonia.Base/Threading/AvaloniaScheduler.cs b/src/Avalonia.Base/Threading/AvaloniaScheduler.cs
index 0bfc713ba0..397826df53 100644
--- a/src/Avalonia.Base/Threading/AvaloniaScheduler.cs
+++ b/src/Avalonia.Base/Threading/AvaloniaScheduler.cs
@@ -9,6 +9,16 @@ namespace Avalonia.Threading
///
public class AvaloniaScheduler : LocalScheduler
{
+ ///
+ /// Users can schedule actions on the dispatcher thread while being on the correct thread already.
+ /// We are optimizing this case by invoking user callback immediately which can lead to stack overflows in certain cases.
+ /// To prevent this we are limiting amount of reentrant calls to before we will
+ /// schedule on a dispatcher anyway.
+ ///
+ private const int MaxReentrantSchedules = 32;
+
+ private int _reentrancyGuard;
+
///
/// The instance of the .
///
@@ -24,31 +34,58 @@ namespace Avalonia.Threading
///
public override IDisposable Schedule(TState state, TimeSpan dueTime, Func action)
{
- var composite = new CompositeDisposable(2);
+ IDisposable PostOnDispatcher()
+ {
+ var composite = new CompositeDisposable(2);
+
+ var cancellation = new CancellationDisposable();
+
+ Dispatcher.UIThread.Post(() =>
+ {
+ if (!cancellation.Token.IsCancellationRequested)
+ {
+ composite.Add(action(this, state));
+ }
+ }, DispatcherPriority.DataBind);
+
+ composite.Add(cancellation);
+
+ return composite;
+ }
+
if (dueTime == TimeSpan.Zero)
{
if (!Dispatcher.UIThread.CheckAccess())
{
- var cancellation = new CancellationDisposable();
- Dispatcher.UIThread.Post(() =>
- {
- if (!cancellation.Token.IsCancellationRequested)
- {
- composite.Add(action(this, state));
- }
- }, DispatcherPriority.DataBind);
- composite.Add(cancellation);
+ return PostOnDispatcher();
}
else
{
- return action(this, state);
+ if (_reentrancyGuard >= MaxReentrantSchedules)
+ {
+ return PostOnDispatcher();
+ }
+
+ try
+ {
+ _reentrancyGuard++;
+
+ return action(this, state);
+ }
+ finally
+ {
+ _reentrancyGuard--;
+ }
}
}
else
{
+ var composite = new CompositeDisposable(2);
+
composite.Add(DispatcherTimer.RunOnce(() => composite.Add(action(this, state)), dueTime));
+
+ return composite;
}
- return composite;
}
}
}
diff --git a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
index c1cc0e7bf0..c9c9c562bd 100644
--- a/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
+++ b/src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
@@ -128,7 +128,7 @@ namespace Avalonia.Build.Tasks
asm.MainModule.Types.Add(typeDef);
var builder = typeSystem.CreateTypeBuilder(typeDef);
- foreach (var res in group.Resources.Where(CheckXamlName))
+ foreach (var res in group.Resources.Where(CheckXamlName).OrderBy(x=>x.FilePath.ToLowerInvariant()))
{
try
{
diff --git a/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj b/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
index 27853a1540..6975642db2 100644
--- a/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
+++ b/src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
@@ -22,4 +22,5 @@
+
diff --git a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
index 738732f671..1d4d88825f 100644
--- a/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
+++ b/src/Avalonia.Controls.DataGrid/Themes/Default.xaml
@@ -28,7 +28,7 @@
-
+
@@ -188,7 +188,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Default/DefaultTheme.xaml b/src/Avalonia.Themes.Default/DefaultTheme.xaml
index 97cff5d94b..e5b654b490 100644
--- a/src/Avalonia.Themes.Default/DefaultTheme.xaml
+++ b/src/Avalonia.Themes.Default/DefaultTheme.xaml
@@ -37,6 +37,7 @@
+
@@ -54,4 +55,7 @@
+
+
+
diff --git a/src/Avalonia.Themes.Default/GridSplitter.xaml b/src/Avalonia.Themes.Default/GridSplitter.xaml
index dc5cd002dc..6d9cb4f31f 100644
--- a/src/Avalonia.Themes.Default/GridSplitter.xaml
+++ b/src/Avalonia.Themes.Default/GridSplitter.xaml
@@ -2,8 +2,8 @@
-
-
diff --git a/src/Avalonia.Themes.Default/SplitView.xaml b/src/Avalonia.Themes.Default/SplitView.xaml
new file mode 100644
index 0000000000..2fb59cdbc4
--- /dev/null
+++ b/src/Avalonia.Themes.Default/SplitView.xaml
@@ -0,0 +1,219 @@
+
+
+
+ 320
+ 48
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Default/TabItem.xaml b/src/Avalonia.Themes.Default/TabItem.xaml
index 92482a564c..6e344ce58e 100644
--- a/src/Avalonia.Themes.Default/TabItem.xaml
+++ b/src/Avalonia.Themes.Default/TabItem.xaml
@@ -2,7 +2,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Avalonia.Themes.Default/TitleBar.xaml b/src/Avalonia.Themes.Default/TitleBar.xaml
index 45798d3fa1..7f8ed24076 100644
--- a/src/Avalonia.Themes.Default/TitleBar.xaml
+++ b/src/Avalonia.Themes.Default/TitleBar.xaml
@@ -5,7 +5,7 @@
-
-
@@ -264,10 +289,6 @@
-
-
diff --git a/src/Avalonia.Themes.Default/Window.xaml b/src/Avalonia.Themes.Default/Window.xaml
index 1856eec206..3b378dbcbe 100644
--- a/src/Avalonia.Themes.Default/Window.xaml
+++ b/src/Avalonia.Themes.Default/Window.xaml
@@ -1,9 +1,8 @@
-
-
-
-
-
-
-
diff --git a/src/Avalonia.Themes.Fluent/CalendarButton.xaml b/src/Avalonia.Themes.Fluent/CalendarButton.xaml
index 87082ef21e..ca538e4b0a 100644
--- a/src/Avalonia.Themes.Fluent/CalendarButton.xaml
+++ b/src/Avalonia.Themes.Fluent/CalendarButton.xaml
@@ -67,7 +67,7 @@
-
+
diff --git a/src/Avalonia.Themes.Fluent/DatePicker.xaml b/src/Avalonia.Themes.Fluent/DatePicker.xaml
index 8b669a30ed..6fbfa1bbf7 100644
--- a/src/Avalonia.Themes.Fluent/DatePicker.xaml
+++ b/src/Avalonia.Themes.Fluent/DatePicker.xaml
@@ -190,7 +190,7 @@
diff --git a/src/Avalonia.Themes.Fluent/Menu.xaml b/src/Avalonia.Themes.Fluent/Menu.xaml
index 5f22f77d18..e62b76d293 100644
--- a/src/Avalonia.Themes.Fluent/Menu.xaml
+++ b/src/Avalonia.Themes.Fluent/Menu.xaml
@@ -11,10 +11,12 @@
- 32
+ 32
+ 12,0,12,0
+
-
+
diff --git a/src/Avalonia.Themes.Fluent/ToggleButton.xaml b/src/Avalonia.Themes.Fluent/ToggleButton.xaml
index f2f07d3e2a..49e2280a6d 100644
--- a/src/Avalonia.Themes.Fluent/ToggleButton.xaml
+++ b/src/Avalonia.Themes.Fluent/ToggleButton.xaml
@@ -39,67 +39,67 @@
-
-
-
-
-
-
-
-
-
-
-