diff --git a/Avalonia.sln b/Avalonia.sln
index 4954260e12..ffd7b4d4f4 100644
--- a/Avalonia.sln
+++ b/Avalonia.sln
@@ -123,10 +123,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject
+ build\AndroidWorkarounds.props = build\AndroidWorkarounds.props
build\Base.props = build\Base.props
build\Binding.props = build\Binding.props
- build\BuildTargets.targets = build\BuildTargets.targets
+ build\CoreLibraries.props = build\CoreLibraries.props
+ build\EmbedXaml.props = build\EmbedXaml.props
build\HarfBuzzSharp.props = build\HarfBuzzSharp.props
+ build\iOSWorkarounds.props = build\iOSWorkarounds.props
build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.props
@@ -136,17 +139,25 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1
build\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props
build\ReactiveUI.props = build\ReactiveUI.props
+ build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.props
build\Rx.props = build\Rx.props
build\SampleApp.props = build\SampleApp.props
+ build\SharedVersion.props = build\SharedVersion.props
build\SharpDX.props = build\SharpDX.props
build\SkiaSharp.props = build\SkiaSharp.props
+ build\SourceLink.props = build\SourceLink.props
+ build\System.Drawing.Common.props = build\System.Drawing.Common.props
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}"
ProjectSection(SolutionItems) = preProject
build\UnitTests.NetCore.targets = build\UnitTests.NetCore.targets
+ build\BuildTargets.targets = build\BuildTargets.targets
+ build\LegacyProject.targets = build\LegacyProject.targets
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}"
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..1573dc2dd6
--- /dev/null
+++ b/build/ApiDiff.props
@@ -0,0 +1,12 @@
+
+
+ 0.10.0-preview2
+ $(PackageId)
+ 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/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..1c8c38d3e5 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/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..e9d2301e89 100644
--- a/samples/ControlCatalog/Pages/MenuPage.xaml
+++ b/samples/ControlCatalog/Pages/MenuPage.xaml
@@ -20,7 +20,9 @@
@@ -52,6 +54,33 @@
+
+
+
+ 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/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/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/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/Avalonia.Controls.csproj b/src/Avalonia.Controls/Avalonia.Controls.csproj
index 32331d29ab..480dcfcb85 100644
--- a/src/Avalonia.Controls/Avalonia.Controls.csproj
+++ b/src/Avalonia.Controls/Avalonia.Controls.csproj
@@ -1,6 +1,6 @@
- netstandard2.0
+ netstandard2.0
@@ -14,4 +14,5 @@
+
diff --git a/src/Avalonia.Controls/Chrome/CaptionButtons.cs b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
index 75d6c366b8..a86cbc271b 100644
--- a/src/Avalonia.Controls/Chrome/CaptionButtons.cs
+++ b/src/Avalonia.Controls/Chrome/CaptionButtons.cs
@@ -38,12 +38,10 @@ namespace Avalonia.Controls.Chrome
{
if (_disposables != null)
{
- var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
-
- layer?.Children.Remove(this);
-
_disposables.Dispose();
_disposables = null;
+
+ _hostWindow = null;
}
}
diff --git a/src/Avalonia.Controls/Chrome/TitleBar.cs b/src/Avalonia.Controls/Chrome/TitleBar.cs
index 78b49d2a03..c0c8076dd8 100644
--- a/src/Avalonia.Controls/Chrome/TitleBar.cs
+++ b/src/Avalonia.Controls/Chrome/TitleBar.cs
@@ -12,106 +12,86 @@ namespace Avalonia.Controls.Chrome
public class TitleBar : TemplatedControl
{
private CompositeDisposable? _disposables;
- private readonly Window? _hostWindow;
private CaptionButtons? _captionButtons;
- public TitleBar(Window hostWindow)
+ private void UpdateSize(Window window)
{
- _hostWindow = hostWindow;
- }
-
- public TitleBar()
- {
-
- }
-
- public void Attach()
- {
- if (_disposables == null)
- {
- var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
-
- layer?.Children.Add(this);
-
- if (_hostWindow != null)
- {
- _disposables = new CompositeDisposable
- {
- _hostWindow.GetObservable(Window.WindowDecorationMarginProperty)
- .Subscribe(x => UpdateSize()),
-
- _hostWindow.GetObservable(Window.ExtendClientAreaTitleBarHeightHintProperty)
- .Subscribe(x => UpdateSize()),
-
- _hostWindow.GetObservable(Window.OffScreenMarginProperty)
- .Subscribe(x => UpdateSize()),
-
- _hostWindow.GetObservable(Window.WindowStateProperty)
- .Subscribe(x =>
- {
- PseudoClasses.Set(":minimized", x == WindowState.Minimized);
- PseudoClasses.Set(":normal", x == WindowState.Normal);
- PseudoClasses.Set(":maximized", x == WindowState.Maximized);
- PseudoClasses.Set(":fullscreen", x == WindowState.FullScreen);
- })
- };
-
- _captionButtons?.Attach(_hostWindow);
- }
-
- UpdateSize();
- }
- }
-
- private void UpdateSize()
- {
- if (_hostWindow != null)
+ if (window != null)
{
Margin = new Thickness(
- _hostWindow.OffScreenMargin.Left,
- _hostWindow.OffScreenMargin.Top,
- _hostWindow.OffScreenMargin.Right,
- _hostWindow.OffScreenMargin.Bottom);
+ window.OffScreenMargin.Left,
+ window.OffScreenMargin.Top,
+ window.OffScreenMargin.Right,
+ window.OffScreenMargin.Bottom);
- if (_hostWindow.WindowState != WindowState.FullScreen)
+ if (window.WindowState != WindowState.FullScreen)
{
- Height = _hostWindow.WindowDecorationMargin.Top;
+ Height = window.WindowDecorationMargin.Top;
if (_captionButtons != null)
{
_captionButtons.Height = Height;
}
}
+
+ IsVisible = window.PlatformImpl.NeedsManagedDecorations;
}
}
- public void Detach()
+ protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
- if (_disposables != null)
- {
- var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
-
- layer?.Children.Remove(this);
+ base.OnApplyTemplate(e);
- _disposables.Dispose();
- _disposables = null;
+ _captionButtons?.Detach();
+
+ _captionButtons = e.NameScope.Get("PART_CaptionButtons");
- _captionButtons?.Detach();
+ if (VisualRoot is Window window)
+ {
+ _captionButtons?.Attach(window);
+
+ UpdateSize(window);
}
}
- protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
+ protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
{
- base.OnApplyTemplate(e);
-
- _captionButtons = e.NameScope.Get("PART_CaptionButtons");
+ base.OnAttachedToVisualTree(e);
- if (_hostWindow != null)
+ if (VisualRoot is Window window)
{
- _captionButtons.Attach(_hostWindow);
+ _disposables = new CompositeDisposable
+ {
+ window.GetObservable(Window.WindowDecorationMarginProperty)
+ .Subscribe(x => UpdateSize(window)),
+ window.GetObservable(Window.ExtendClientAreaTitleBarHeightHintProperty)
+ .Subscribe(x => UpdateSize(window)),
+ window.GetObservable(Window.OffScreenMarginProperty)
+ .Subscribe(x => UpdateSize(window)),
+ window.GetObservable(Window.ExtendClientAreaChromeHintsProperty)
+ .Subscribe(x => UpdateSize(window)),
+ window.GetObservable(Window.WindowStateProperty)
+ .Subscribe(x =>
+ {
+ PseudoClasses.Set(":minimized", x == WindowState.Minimized);
+ PseudoClasses.Set(":normal", x == WindowState.Normal);
+ PseudoClasses.Set(":maximized", x == WindowState.Maximized);
+ PseudoClasses.Set(":fullscreen", x == WindowState.FullScreen);
+ }),
+ window.GetObservable(Window.IsExtendedIntoWindowDecorationsProperty)
+ .Subscribe(x => UpdateSize(window))
+ };
}
+ }
+
+ protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+ {
+ base.OnDetachedFromVisualTree(e);
- UpdateSize();
+ _disposables?.Dispose();
+
+ _captionButtons?.Detach();
+ _captionButtons = null;
}
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
index 31527ccb16..eec4615736 100644
--- a/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
@@ -356,10 +356,17 @@ namespace Avalonia.Controls
}
if (MonthVisible)
+ {
_monthSelector.SelectedValue = dt.Month;
-
+ _monthSelector.FormatDate = dt.Date;
+ }
+
if (YearVisible)
+ {
_yearSelector.SelectedValue = dt.Year;
+ _yearSelector.FormatDate = dt.Date;
+ }
+
_suppressUpdateSelection = false;
SetInitialFocus();
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
index 3fa426b1d3..e54da1fb3a 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePicker.cs
@@ -15,7 +15,7 @@ namespace Avalonia.Controls
/// Defines the property
///
public static readonly DirectProperty MinuteIncrementProperty =
- AvaloniaProperty.RegisterDirect(nameof(MinuteIncrement),
+ AvaloniaProperty.RegisterDirect(nameof(MinuteIncrement),
x => x.MinuteIncrement, (x, v) => x.MinuteIncrement = v);
///
@@ -34,17 +34,17 @@ namespace Avalonia.Controls
/// Defines the property
///
public static readonly DirectProperty ClockIdentifierProperty =
- AvaloniaProperty.RegisterDirect(nameof(ClockIdentifier),
+ AvaloniaProperty.RegisterDirect(nameof(ClockIdentifier),
x => x.ClockIdentifier, (x, v) => x.ClockIdentifier = v);
///
/// Defines the property
///
public static readonly DirectProperty SelectedTimeProperty =
- AvaloniaProperty.RegisterDirect(nameof(SelectedTime),
+ AvaloniaProperty.RegisterDirect(nameof(SelectedTime),
x => x.SelectedTime, (x, v) => x.SelectedTime = v);
- //Template Items
+ // Template Items
private TimePickerPresenter _presenter;
private Button _flyoutButton;
private Border _firstPickerHost;
@@ -52,7 +52,7 @@ namespace Avalonia.Controls
private Border _thirdPickerHost;
private TextBlock _hourText;
private TextBlock _minuteText;
- public TextBlock _periodText;
+ private TextBlock _periodText;
private Rectangle _firstSplitter;
private Rectangle _secondSplitter;
private Grid _contentGrid;
@@ -145,7 +145,7 @@ namespace Avalonia.Controls
if (_flyoutButton != null)
_flyoutButton.Click -= OnFlyoutButtonClicked;
- if(_presenter != null)
+ if (_presenter != null)
{
_presenter.Confirmed -= OnConfirmed;
_presenter.Dismissed -= OnDismissPicker;
@@ -170,7 +170,6 @@ namespace Avalonia.Controls
_popup = e.NameScope.Find("Popup");
_presenter = e.NameScope.Find("PickerPresenter");
-
if (_flyoutButton != null)
_flyoutButton.Click += OnFlyoutButtonClicked;
@@ -185,7 +184,6 @@ namespace Avalonia.Controls
_presenter[!TimePickerPresenter.MinuteIncrementProperty] = this[!MinuteIncrementProperty];
_presenter[!TimePickerPresenter.ClockIdentifierProperty] = this[!ClockIdentifierProperty];
}
-
}
private void SetGrid()
@@ -195,30 +193,19 @@ namespace Avalonia.Controls
bool use24HourClock = ClockIdentifier == "24HourClock";
- if (!use24HourClock)
- {
- _contentGrid.ColumnDefinitions = new ColumnDefinitions("*,Auto,*,Auto,*");
- _thirdPickerHost.IsVisible = true;
- _secondSplitter.IsVisible = true;
+ var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
+ _contentGrid.ColumnDefinitions = new ColumnDefinitions(columnsD);
- Grid.SetColumn(_firstPickerHost, 0);
- Grid.SetColumn(_secondPickerHost, 2);
- Grid.SetColumn(_thirdPickerHost, 4);
+ _thirdPickerHost.IsVisible = !use24HourClock;
+ _secondSplitter.IsVisible = !use24HourClock;
- Grid.SetColumn(_firstSplitter, 1);
- Grid.SetColumn(_secondSplitter, 3);
- }
- else
- {
- _contentGrid.ColumnDefinitions = new ColumnDefinitions("*,Auto,*");
- _thirdPickerHost.IsVisible = false;
- _secondSplitter.IsVisible = false;
+ Grid.SetColumn(_firstPickerHost, 0);
+ Grid.SetColumn(_secondPickerHost, 2);
- Grid.SetColumn(_firstPickerHost, 0);
- Grid.SetColumn(_secondPickerHost, 2);
+ Grid.SetColumn(_thirdPickerHost, use24HourClock ? 0 : 4);
- Grid.SetColumn(_firstSplitter, 1);
- }
+ Grid.SetColumn(_firstSplitter, 1);
+ Grid.SetColumn(_secondSplitter, use24HourClock ? 0 : 3);
}
private void SetSelectedTimeText()
@@ -237,14 +224,13 @@ namespace Avalonia.Controls
hr = hr > 12 ? hr - 12 : hr == 0 ? 12 : hr;
newTime = new TimeSpan(hr, newTime.Minutes, 0);
}
- _hourText.Text = newTime.ToString("%h");
+ _hourText.Text = newTime.ToString("%h");
_minuteText.Text = newTime.ToString("mm");
PseudoClasses.Set(":hasnotime", false);
_periodText.Text = time.Value.Hours >= 12 ? CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator :
CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator;
-
}
else
{
@@ -262,7 +248,7 @@ namespace Avalonia.Controls
SelectedTimeChanged?.Invoke(this, new TimePickerSelectedValueChangedEventArgs(oldTime, newTime));
}
- private void OnFlyoutButtonClicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
+ private void OnFlyoutButtonClicked(object sender, Interactivity.RoutedEventArgs e)
{
_presenter.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
@@ -270,7 +256,7 @@ namespace Avalonia.Controls
var deltaY = _presenter.GetOffsetForPopup();
- //The extra 5 px I think is related to default popup placement behavior
+ // The extra 5 px I think is related to default popup placement behavior
_popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
@@ -287,6 +273,5 @@ namespace Avalonia.Controls
_popup.Close();
SelectedTime = _presenter.Time;
}
-
}
}
diff --git a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
index 5ab5b92e16..920eeeb406 100644
--- a/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
+++ b/src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
@@ -39,7 +39,7 @@ namespace Avalonia.Controls
KeyboardNavigation.SetTabNavigation(this, KeyboardNavigationMode.Cycle);
}
- //TemplateItems
+ // TemplateItems
private Grid _pickerContainer;
private Button _acceptButton;
private Button _dismissButton;
@@ -55,8 +55,8 @@ namespace Avalonia.Controls
private Button _minuteDownButton;
private Button _periodDownButton;
- //Backing Fields
- private TimeSpan _Time;
+ // Backing Fields
+ private TimeSpan _time;
private int _minuteIncrement = 1;
private string _clockIdentifier = "12HourClock";
@@ -83,7 +83,7 @@ namespace Avalonia.Controls
get => _clockIdentifier;
set
{
- if (string.IsNullOrEmpty(value) || value == "" || !(value == "12HourClock" || value == "24HourClock"))
+ if (string.IsNullOrEmpty(value) || !(value == "12HourClock" || value == "24HourClock"))
throw new ArgumentException("Invalid ClockIdentifier");
SetAndRaise(ClockIdentifierProperty, ref _clockIdentifier, value);
InitPicker();
@@ -95,10 +95,10 @@ namespace Avalonia.Controls
///
public TimeSpan Time
{
- get => _Time;
+ get => _time;
set
{
- SetAndRaise(TimeProperty, ref _Time, value);
+ SetAndRaise(TimeProperty, ref _time, value);
InitPicker();
}
}
@@ -213,26 +213,24 @@ namespace Avalonia.Controls
private void SetGrid()
{
- if (ClockIdentifier == "12HourClock")
- {
- _pickerContainer.ColumnDefinitions = new ColumnDefinitions("*,Auto,*,Auto,*");
- _spacer2.IsVisible = true;
- _periodHost.IsVisible = true;
- }
- else
- {
- _pickerContainer.ColumnDefinitions = new ColumnDefinitions("*,Auto,*");
- _spacer2.IsVisible = false;
- _periodHost.IsVisible = false;
- }
+ bool use24HourClock = ClockIdentifier == "24HourClock";
+
+ var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
+ _pickerContainer.ColumnDefinitions = new ColumnDefinitions(columnsD);
+
+ _spacer2.IsVisible = !use24HourClock;
+ _periodHost.IsVisible = !use24HourClock;
+
+ Grid.SetColumn(_spacer2, use24HourClock ? 0 : 3);
+ Grid.SetColumn(_periodHost, use24HourClock ? 0 : 4);
}
- private void OnDismissButtonClicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
+ private void OnDismissButtonClicked(object sender, RoutedEventArgs e)
{
OnDismiss();
}
- private void OnAcceptButtonClicked(object sender, Avalonia.Interactivity.RoutedEventArgs e)
+ private void OnAcceptButtonClicked(object sender, RoutedEventArgs e)
{
OnConfirmed();
}
diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs
index 912abc6de3..789e4f8926 100644
--- a/src/Avalonia.Controls/MenuItem.cs
+++ b/src/Avalonia.Controls/MenuItem.cs
@@ -97,7 +97,6 @@ namespace Avalonia.Controls
private ICommand _command;
private bool _commandCanExecute = true;
private Popup _popup;
- private IDisposable _gridHack;
///
/// Initializes static members of the class.
@@ -323,9 +322,6 @@ namespace Avalonia.Controls
{
Command.CanExecuteChanged -= CanExecuteChanged;
}
-
- _gridHack?.Dispose();
- _gridHack = null;
}
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
@@ -345,9 +341,7 @@ namespace Avalonia.Controls
// the WPF codebase:
//
// https://github.com/dotnet/wpf/blob/89537909bdf36bc918e88b37751add46a8980bb0/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L2126-L2141
- _gridHack = Bind(
- DefinitionBase.PrivateSharedSizeScopeProperty,
- parent.GetBindingObservable(DefinitionBase.PrivateSharedSizeScopeProperty));
+ SetValue(DefinitionBase.PrivateSharedSizeScopeProperty, parent.GetValue(DefinitionBase.PrivateSharedSizeScopeProperty));
}
}
diff --git a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
index ba0fdfd535..7171ecc302 100644
--- a/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
+++ b/src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
@@ -8,7 +8,7 @@ namespace Avalonia.Controls.Primitives
{
public class ChromeOverlayLayer : Panel, ICustomSimpleHitTest
{
- public static ChromeOverlayLayer? GetOverlayLayer(IVisual visual)
+ public static Panel? GetOverlayLayer(IVisual visual)
{
foreach (var v in visual.GetVisualAncestors())
if (v is VisualLayerManager vlm)
@@ -24,6 +24,11 @@ namespace Avalonia.Controls.Primitives
return null;
}
+ public void Add(Control c)
+ {
+ base.Children.Add(c);
+ }
+
public bool HitTest(Point point) => Children.HitTestCustom(point);
}
}
diff --git a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
index 3084d7fa72..ff83351190 100644
--- a/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
+++ b/src/Avalonia.Controls/Primitives/VisualLayerManager.cs
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using Avalonia.LogicalTree;
+using Avalonia.Metadata;
namespace Avalonia.Controls.Primitives
{
@@ -11,10 +12,12 @@ namespace Avalonia.Controls.Primitives
private ILogicalRoot _logicalRoot;
private readonly List _layers = new List();
-
+
+ public static readonly StyledProperty ChromeOverlayLayerProperty =
+ AvaloniaProperty.Register(nameof(ChromeOverlayLayer));
public bool IsPopup { get; set; }
-
+
public AdornerLayer AdornerLayer
{
get
@@ -30,10 +33,19 @@ namespace Avalonia.Controls.Primitives
{
get
{
- var rv = FindLayer();
- if (rv == null)
- AddLayer(rv = new ChromeOverlayLayer(), ChromeZIndex);
- return rv;
+ var current = GetValue(ChromeOverlayLayerProperty);
+
+ if (current is null)
+ {
+ var chromeOverlayLayer = new ChromeOverlayLayer();
+ AddLayer(chromeOverlayLayer, ChromeZIndex);
+
+ SetValue(ChromeOverlayLayerProperty, chromeOverlayLayer);
+
+ current = chromeOverlayLayer;
+ }
+
+ return current;
}
}
@@ -44,7 +56,7 @@ namespace Avalonia.Controls.Primitives
if (IsPopup)
return null;
var rv = FindLayer();
- if(rv == null)
+ if (rv == null)
AddLayer(rv = new OverlayLayer(), OverlayZIndex);
return rv;
}
@@ -65,7 +77,8 @@ namespace Avalonia.Controls.Primitives
layer.ZIndex = zindex;
VisualChildren.Add(layer);
if (((ILogical)this).IsAttachedToLogicalTree)
- ((ILogical)layer).NotifyAttachedToLogicalTree(new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this));
+ ((ILogical)layer).NotifyAttachedToLogicalTree(
+ new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this));
InvalidateArrange();
}
diff --git a/src/Avalonia.Controls/ProgressBar.cs b/src/Avalonia.Controls/ProgressBar.cs
index e904957429..a92f24a050 100644
--- a/src/Avalonia.Controls/ProgressBar.cs
+++ b/src/Avalonia.Controls/ProgressBar.cs
@@ -215,7 +215,7 @@ namespace Avalonia.Controls
TemplateProperties.Container2AnimationEndPosition = barIndicatorWidth2 * 1.66; // Position at 166%
// Remove these properties when we switch to fluent as default and removed the old one.
- IndeterminateStartingOffset = -(dim / 5d);
+ IndeterminateStartingOffset = -dim;
IndeterminateEndingOffset = dim;
var padding = Padding;
diff --git a/src/Avalonia.Controls/Repeater/ItemsSourceView.cs b/src/Avalonia.Controls/Repeater/ItemsSourceView.cs
index ecf8abc13f..def9301e2d 100644
--- a/src/Avalonia.Controls/Repeater/ItemsSourceView.cs
+++ b/src/Avalonia.Controls/Repeater/ItemsSourceView.cs
@@ -25,7 +25,6 @@ namespace Avalonia.Controls
{
private readonly IList _inner;
private INotifyCollectionChanged _notifyCollectionChanged;
- private int _cachedSize = -1;
///
/// Initializes a new instance of the ItemsSourceView class for the specified data source.
@@ -54,18 +53,7 @@ namespace Avalonia.Controls
///
/// Gets the number of items in the collection.
///
- public int Count
- {
- get
- {
- if (_cachedSize == -1)
- {
- _cachedSize = _inner.Count;
- }
-
- return _cachedSize;
- }
- }
+ public int Count => _inner.Count;
///
/// Gets a value that indicates whether the items source can provide a unique key for each item.
@@ -126,7 +114,6 @@ namespace Avalonia.Controls
protected void OnItemsSourceChanged(NotifyCollectionChangedEventArgs args)
{
- _cachedSize = _inner.Count;
CollectionChanged?.Invoke(this, args);
}
diff --git a/src/Avalonia.Controls/ToolTip.cs b/src/Avalonia.Controls/ToolTip.cs
index b458b15c64..cf0652247f 100644
--- a/src/Avalonia.Controls/ToolTip.cs
+++ b/src/Avalonia.Controls/ToolTip.cs
@@ -66,6 +66,7 @@ namespace Avalonia.Controls
static ToolTip()
{
TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
+ IsOpenProperty.Changed.Subscribe(ToolTipService.Instance.TipOpenChanged);
IsOpenProperty.Changed.Subscribe(IsOpenChanged);
}
diff --git a/src/Avalonia.Controls/ToolTipService.cs b/src/Avalonia.Controls/ToolTipService.cs
index 569697304f..e2a0f9e50c 100644
--- a/src/Avalonia.Controls/ToolTipService.cs
+++ b/src/Avalonia.Controls/ToolTipService.cs
@@ -28,20 +28,33 @@ namespace Avalonia.Controls
{
control.PointerEnter -= ControlPointerEnter;
control.PointerLeave -= ControlPointerLeave;
- control.DetachedFromVisualTree -= ControlDetaching;
}
if (e.NewValue != null)
{
control.PointerEnter += ControlPointerEnter;
control.PointerLeave += ControlPointerLeave;
+ }
+ }
+
+ internal void TipOpenChanged(AvaloniaPropertyChangedEventArgs e)
+ {
+ var control = (Control)e.Sender;
+
+ if (e.OldValue is false && e.NewValue is true)
+ {
control.DetachedFromVisualTree += ControlDetaching;
}
+ else if(e.OldValue is true && e.NewValue is false)
+ {
+ control.DetachedFromVisualTree -= ControlDetaching;
+ }
}
private void ControlDetaching(object sender, VisualTreeAttachmentEventArgs e)
{
var control = (Control)sender;
+ control.DetachedFromVisualTree -= ControlDetaching;
Close(control);
}
diff --git a/src/Avalonia.Controls/Utils/SelectedItemsSync.cs b/src/Avalonia.Controls/Utils/SelectedItemsSync.cs
index c127771990..91cef9fe64 100644
--- a/src/Avalonia.Controls/Utils/SelectedItemsSync.cs
+++ b/src/Avalonia.Controls/Utils/SelectedItemsSync.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Specialized;
+using System.ComponentModel;
using System.Linq;
using Avalonia.Collections;
@@ -16,6 +17,7 @@ namespace Avalonia.Controls.Utils
private IList? _items;
private bool _updatingItems;
private bool _updatingModel;
+ private bool _initializeOnSourceAssignment;
public SelectedItemsSync(ISelectionModel model)
{
@@ -63,10 +65,18 @@ namespace Avalonia.Controls.Utils
_updatingModel = true;
_items = items;
- using (Model.Update())
+ if (Model.Source is object)
{
- Model.ClearSelection();
- Add(items);
+ using (Model.Update())
+ {
+ Model.ClearSelection();
+ Add(items);
+ }
+ }
+ else if (!_initializeOnSourceAssignment)
+ {
+ Model.PropertyChanged += SelectionModelPropertyChanged;
+ _initializeOnSourceAssignment = true;
}
if (_items is INotifyCollectionChanged incc2)
@@ -86,9 +96,11 @@ namespace Avalonia.Controls.Utils
if (_items != null)
{
+ Model.PropertyChanged -= SelectionModelPropertyChanged;
Model.SelectionChanged -= SelectionModelSelectionChanged;
Model = model;
Model.SelectionChanged += SelectionModelSelectionChanged;
+ _initializeOnSourceAssignment = false;
try
{
@@ -175,6 +187,25 @@ namespace Avalonia.Controls.Utils
}
}
+ private void SelectionModelPropertyChanged(object sender, PropertyChangedEventArgs e)
+ {
+ if (_initializeOnSourceAssignment &&
+ _items != null &&
+ e.PropertyName == nameof(SelectionModel.Source))
+ {
+ try
+ {
+ _updatingModel = true;
+ Add(_items);
+ _initializeOnSourceAssignment = false;
+ }
+ finally
+ {
+ _updatingModel = false;
+ }
+ }
+ }
+
private void SelectionModelSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
{
if (_updatingModel)
diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs
index 90e5c22c45..d8e7f3a387 100644
--- a/src/Avalonia.Controls/Window.cs
+++ b/src/Avalonia.Controls/Window.cs
@@ -6,6 +6,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks;
using Avalonia.Controls.Chrome;
using Avalonia.Controls.Platform;
+using Avalonia.Controls.Primitives;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Interactivity;
@@ -70,8 +71,7 @@ namespace Avalonia.Controls
///
public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot
{
- private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>();
- private TitleBar _managedTitleBar;
+ private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>();
private bool _isExtendedIntoWindowDecorations;
private Thickness _windowDecorationMargin;
private Thickness _offScreenMargin;
@@ -552,20 +552,6 @@ namespace Avalonia.Controls
IsExtendedIntoWindowDecorations = isExtended;
WindowDecorationMargin = PlatformImpl.ExtendedMargins;
OffScreenMargin = PlatformImpl.OffScreenMargin;
-
- if (PlatformImpl.NeedsManagedDecorations)
- {
- if (_managedTitleBar == null)
- {
- _managedTitleBar = new TitleBar(this);
- _managedTitleBar.Attach();
- }
- }
- else
- {
- _managedTitleBar?.Detach();
- _managedTitleBar = null;
- }
}
///
diff --git a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
index 76ea8a3445..35bd0f97e1 100644
--- a/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
+++ b/src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
@@ -9,6 +9,7 @@
0.7.0
CS1591
true
+ Avalonia
@@ -26,4 +27,5 @@
+
diff --git a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js
index 3057f269a5..3750351165 100644
--- a/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js
+++ b/src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js
@@ -93,7 +93,7 @@ const config = {
plugins:
[
new Printer(),
- new CleanWebpackPlugin([path.resolve(__dirname, 'build')]),
+ new CleanWebpackPlugin([path.resolve(__dirname, 'build')], { verbose: false }),
new MiniCssExtractPlugin({
filename: "[name].[chunkhash]h" +
".css",
diff --git a/src/Avalonia.Desktop/Avalonia.Desktop.csproj b/src/Avalonia.Desktop/Avalonia.Desktop.csproj
index 72b7b5c1e7..a9589b7f2b 100644
--- a/src/Avalonia.Desktop/Avalonia.Desktop.csproj
+++ b/src/Avalonia.Desktop/Avalonia.Desktop.csproj
@@ -11,4 +11,6 @@
+
+
diff --git a/src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj b/src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
index c0e46416c1..805aae2d1a 100644
--- a/src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
+++ b/src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
@@ -17,4 +17,5 @@
+
diff --git a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
index 5f49a46839..db8684747d 100644
--- a/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
+++ b/src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
@@ -2,6 +2,7 @@
netstandard2.0
Avalonia
+ Avalonia.Diagnostics
@@ -28,4 +29,5 @@
+
diff --git a/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj b/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
index f54ddf32be..dd476e2559 100644
--- a/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
+++ b/src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
@@ -15,4 +15,6 @@
+
+
diff --git a/src/Avalonia.Dialogs/ManagedFileChooser.xaml b/src/Avalonia.Dialogs/ManagedFileChooser.xaml
index 8a0451f982..227cc1afc0 100644
--- a/src/Avalonia.Dialogs/ManagedFileChooser.xaml
+++ b/src/Avalonia.Dialogs/ManagedFileChooser.xaml
@@ -66,7 +66,7 @@
-
+ DockPanel.Dock="Left" Focusable="False">
diff --git a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
index d9fd3b78a2..260d7350d2 100644
--- a/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
+++ b/src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
@@ -1,7 +1,7 @@
- netstandard2.0
+ netstandard2.0
@@ -10,6 +10,5 @@
-
-
+
diff --git a/src/Avalonia.Headless/Avalonia.Headless.csproj b/src/Avalonia.Headless/Avalonia.Headless.csproj
index b871316a2c..ac591b68a8 100644
--- a/src/Avalonia.Headless/Avalonia.Headless.csproj
+++ b/src/Avalonia.Headless/Avalonia.Headless.csproj
@@ -1,8 +1,9 @@
netstandard2.0
+
-
+
diff --git a/src/Avalonia.Input/Avalonia.Input.csproj b/src/Avalonia.Input/Avalonia.Input.csproj
index ea560ce2ea..2204778afe 100644
--- a/src/Avalonia.Input/Avalonia.Input.csproj
+++ b/src/Avalonia.Input/Avalonia.Input.csproj
@@ -10,4 +10,5 @@
+
diff --git a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
index 730ca2bd6e..2da23410d6 100644
--- a/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
+++ b/src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
@@ -11,4 +11,5 @@
+
\ No newline at end of file
diff --git a/src/Avalonia.Layout/Avalonia.Layout.csproj b/src/Avalonia.Layout/Avalonia.Layout.csproj
index 410a0791b1..076ec56cd6 100644
--- a/src/Avalonia.Layout/Avalonia.Layout.csproj
+++ b/src/Avalonia.Layout/Avalonia.Layout.csproj
@@ -8,4 +8,5 @@
+
diff --git a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
index 0f2551ffeb..6d1b95b997 100644
--- a/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
+++ b/src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
@@ -11,7 +11,7 @@ namespace Avalonia.Native
class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter
{
private IAvaloniaNativeFactory _factory;
- private bool _resetQueued;
+ private bool _resetQueued = true;
private bool _exported = false;
private IAvnWindow _nativeWindow;
private NativeMenu _menu;
@@ -39,8 +39,7 @@ namespace Avalonia.Native
public void SetNativeMenu(NativeMenu menu)
{
_menu = menu == null ? new NativeMenu() : menu;
-
- DoLayoutReset();
+ DoLayoutReset(true);
}
internal void UpdateIfNeeded()
@@ -74,31 +73,34 @@ namespace Avalonia.Native
return result;
}
- void DoLayoutReset()
+ private void DoLayoutReset(bool forceUpdate = false)
{
- _resetQueued = false;
-
- if (_nativeWindow is null)
+ if (_resetQueued || forceUpdate)
{
- var appMenu = NativeMenu.GetMenu(Application.Current);
+ _resetQueued = false;
- if (appMenu == null)
+ if (_nativeWindow is null)
{
- appMenu = CreateDefaultAppMenu();
- NativeMenu.SetMenu(Application.Current, appMenu);
- }
+ var appMenu = NativeMenu.GetMenu(Application.Current);
- SetMenu(appMenu);
- }
- else
- {
- if (_menu != null)
+ if (appMenu == null)
+ {
+ appMenu = CreateDefaultAppMenu();
+ NativeMenu.SetMenu(Application.Current, appMenu);
+ }
+
+ SetMenu(appMenu);
+ }
+ else
{
- SetMenu(_nativeWindow, _menu);
+ if (_menu != null)
+ {
+ SetMenu(_nativeWindow, _menu);
+ }
}
- }
- _exported = true;
+ _exported = true;
+ }
}
internal void QueueReset()
@@ -106,7 +108,7 @@ namespace Avalonia.Native
if (_resetQueued)
return;
_resetQueued = true;
- Dispatcher.UIThread.Post(DoLayoutReset, DispatcherPriority.Background);
+ Dispatcher.UIThread.Post(() => DoLayoutReset(), DispatcherPriority.Background);
}
private void SetMenu(NativeMenu menu)
diff --git a/src/Avalonia.Native/OsxUnicodeKeys.cs b/src/Avalonia.Native/OsxUnicodeKeys.cs
index b4056c8cd8..fd9acfa714 100644
--- a/src/Avalonia.Native/OsxUnicodeKeys.cs
+++ b/src/Avalonia.Native/OsxUnicodeKeys.cs
@@ -140,6 +140,11 @@ namespace Avalonia.Native.Interop
}
else
{
+ if (key >= Key.D0 && key <= Key.D9)
+ {
+ return key.ToString().Replace("D", "");
+ }
+
return key.ToString().ToLower();
}
}
diff --git a/src/Avalonia.Native/WindowImplBase.cs b/src/Avalonia.Native/WindowImplBase.cs
index 42eecc36ea..4b13666edd 100644
--- a/src/Avalonia.Native/WindowImplBase.cs
+++ b/src/Avalonia.Native/WindowImplBase.cs
@@ -300,7 +300,15 @@ namespace Avalonia.Native
public IRenderer CreateRenderer(IRenderRoot root)
{
if (_deferredRendering)
- return new DeferredRenderer(root, AvaloniaLocator.Current.GetService());
+ {
+ var loop = AvaloniaLocator.Current.GetService();
+ var customRendererFactory = AvaloniaLocator.Current.GetService();
+
+ if (customRendererFactory != null)
+ return customRendererFactory.Create(root, loop);
+ return new DeferredRenderer(root, loop);
+ }
+
return new ImmediateRenderer(root);
}
diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
index 72132eed93..d761e60c07 100644
--- a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
+++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
@@ -9,6 +9,5 @@
-
-
+
diff --git a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
index 64145b9c3c..d01a495108 100644
--- a/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
+++ b/src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
@@ -8,4 +8,5 @@
+
diff --git a/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj b/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
index 6684772bfe..6c241bbc75 100644
--- a/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
+++ b/src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
@@ -4,8 +4,10 @@
AVALONIA_REMOTE_PROTOCOL;$(DefineConstants)
true
Key.snk
+ Avalonia.Remote.Protocol
+
\ No newline at end of file
diff --git a/src/Avalonia.Styling/Avalonia.Styling.csproj b/src/Avalonia.Styling/Avalonia.Styling.csproj
index b4f6c2c942..d9f0cef3da 100644
--- a/src/Avalonia.Styling/Avalonia.Styling.csproj
+++ b/src/Avalonia.Styling/Avalonia.Styling.csproj
@@ -8,4 +8,5 @@
+
diff --git a/src/Avalonia.Themes.Default/Accents/BaseDark.xaml b/src/Avalonia.Themes.Default/Accents/BaseDark.xaml
index ffe3e92202..44dfb9ea48 100644
--- a/src/Avalonia.Themes.Default/Accents/BaseDark.xaml
+++ b/src/Avalonia.Themes.Default/Accents/BaseDark.xaml
@@ -58,6 +58,11 @@
+
+
+
+
+
1,1,1,1
0.5
diff --git a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml
index c0e5f47eed..9ed3207235 100644
--- a/src/Avalonia.Themes.Default/Accents/BaseLight.xaml
+++ b/src/Avalonia.Themes.Default/Accents/BaseLight.xaml
@@ -61,6 +61,11 @@
+
+
+
+
+
1
0.5
diff --git a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
index c44cc358e8..153e21761e 100644
--- a/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
+++ b/src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
@@ -19,4 +19,5 @@
+
diff --git a/src/Avalonia.Themes.Default/ComboBox.xaml b/src/Avalonia.Themes.Default/ComboBox.xaml
index ae5b902ae8..0fd6b144a4 100644
--- a/src/Avalonia.Themes.Default/ComboBox.xaml
+++ b/src/Avalonia.Themes.Default/ComboBox.xaml
@@ -1,4 +1,5 @@
-
+
@@ -24,6 +25,7 @@
+
+
+
+
+
+ 0,0,0,4
+ 40
+ 40
+ 41
+ 296
+ 456
+ 0,3,0,6
+ 9,3,0,6
+ 0,3,0,6
+ 9,3,0,6
+ 1
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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/ProgressBar.xaml b/src/Avalonia.Themes.Default/ProgressBar.xaml
index 43a0752bc8..d9c407245b 100644
--- a/src/Avalonia.Themes.Default/ProgressBar.xaml
+++ b/src/Avalonia.Themes.Default/ProgressBar.xaml
@@ -13,19 +13,14 @@
-
-
+
+
+
+
+
-
-
+
+
@@ -54,36 +49,31 @@
-
-
diff --git a/src/Avalonia.Themes.Default/SplitView.xaml b/src/Avalonia.Themes.Default/SplitView.xaml
new file mode 100644
index 0000000000..4a9a7be164
--- /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 739887fb35..7d74a7e6a0 100644
--- a/src/Avalonia.Themes.Default/Window.xaml
+++ b/src/Avalonia.Themes.Default/Window.xaml
@@ -1,23 +1,24 @@
-
-
-
-
-
-
-
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/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
+
-
+
-
+
-
+
@@ -40,97 +41,98 @@
+ -4
0,4,0,4
0,0,12,0
- 24,0,0,0
+ 24,0,0,0
M 1,0 10,10 l -9,10 -1,-1 L 8,10 -0,1 Z
@@ -145,6 +147,8 @@
@@ -155,8 +159,7 @@
-
+
+
+
@@ -203,7 +211,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-