Browse Source

Merge branch 'master' into issues/4306

pull/4307/head
Steven Kirk 6 years ago
committed by GitHub
parent
commit
1a7cc18533
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 13
      Avalonia.sln
  2. 2
      NuGet.Config
  3. 12
      build/ApiDiff.props
  4. 2
      build/SkiaSharp.props
  5. 4
      nukebuild/Build.cs
  6. 2
      readme.md
  7. 8
      samples/ControlCatalog/App.xaml
  8. 4
      samples/ControlCatalog/App.xaml.cs
  9. 4
      samples/ControlCatalog/MainView.xaml
  10. 14
      samples/ControlCatalog/MainWindow.xaml.cs
  11. 4
      samples/ControlCatalog/Pages/ButtonPage.xaml
  12. 2
      samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml
  13. 3
      samples/ControlCatalog/Pages/ListBoxPage.xaml
  14. 68
      samples/ControlCatalog/Pages/ListBoxPage.xaml.cs
  15. 31
      samples/ControlCatalog/Pages/MenuPage.xaml
  16. 13
      samples/ControlCatalog/Pages/ScreenPage.cs
  17. 4
      samples/ControlCatalog/Pages/TextBlockPage.xaml
  18. 65
      samples/ControlCatalog/ViewModels/ListBoxPageViewModel.cs
  19. 36
      samples/ControlCatalog/ViewModels/MenuPageViewModel.cs
  20. 3
      src/Avalonia.Animation/Avalonia.Animation.csproj
  21. 3
      src/Avalonia.Base/Avalonia.Base.csproj
  22. 61
      src/Avalonia.Base/Threading/AvaloniaScheduler.cs
  23. 2
      src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs
  24. 1
      src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj
  25. 3
      src/Avalonia.Controls/Avalonia.Controls.csproj
  26. 6
      src/Avalonia.Controls/Chrome/CaptionButtons.cs
  27. 126
      src/Avalonia.Controls/Chrome/TitleBar.cs
  28. 9
      src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs
  29. 51
      src/Avalonia.Controls/DateTimePickers/TimePicker.cs
  30. 38
      src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs
  31. 8
      src/Avalonia.Controls/MenuItem.cs
  32. 7
      src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs
  33. 29
      src/Avalonia.Controls/Primitives/VisualLayerManager.cs
  34. 2
      src/Avalonia.Controls/ProgressBar.cs
  35. 15
      src/Avalonia.Controls/Repeater/ItemsSourceView.cs
  36. 1
      src/Avalonia.Controls/ToolTip.cs
  37. 15
      src/Avalonia.Controls/ToolTipService.cs
  38. 37
      src/Avalonia.Controls/Utils/SelectedItemsSync.cs
  39. 18
      src/Avalonia.Controls/Window.cs
  40. 2
      src/Avalonia.DesignerSupport/Avalonia.DesignerSupport.csproj
  41. 2
      src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js
  42. 2
      src/Avalonia.Desktop/Avalonia.Desktop.csproj
  43. 1
      src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj
  44. 2
      src/Avalonia.Diagnostics/Avalonia.Diagnostics.csproj
  45. 2
      src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
  46. 4
      src/Avalonia.Dialogs/ManagedFileChooser.xaml
  47. 5
      src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj
  48. 3
      src/Avalonia.Headless/Avalonia.Headless.csproj
  49. 1
      src/Avalonia.Input/Avalonia.Input.csproj
  50. 1
      src/Avalonia.Interactivity/Avalonia.Interactivity.csproj
  51. 1
      src/Avalonia.Layout/Avalonia.Layout.csproj
  52. 44
      src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
  53. 5
      src/Avalonia.Native/OsxUnicodeKeys.cs
  54. 10
      src/Avalonia.Native/WindowImplBase.cs
  55. 3
      src/Avalonia.OpenGL/Avalonia.OpenGL.csproj
  56. 1
      src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj
  57. 2
      src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj
  58. 1
      src/Avalonia.Styling/Avalonia.Styling.csproj
  59. 5
      src/Avalonia.Themes.Default/Accents/BaseDark.xaml
  60. 5
      src/Avalonia.Themes.Default/Accents/BaseLight.xaml
  61. 1
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  62. 12
      src/Avalonia.Themes.Default/ComboBox.xaml
  63. 334
      src/Avalonia.Themes.Default/DatePicker.xaml
  64. 4
      src/Avalonia.Themes.Default/DefaultTheme.xaml
  65. 46
      src/Avalonia.Themes.Default/ProgressBar.xaml
  66. 219
      src/Avalonia.Themes.Default/SplitView.xaml
  67. 2
      src/Avalonia.Themes.Default/TabItem.xaml
  68. 283
      src/Avalonia.Themes.Default/TimePicker.xaml
  69. 6
      src/Avalonia.Themes.Default/TitleBar.xaml
  70. 47
      src/Avalonia.Themes.Default/ToggleSwitch.xaml
  71. 31
      src/Avalonia.Themes.Default/Window.xaml
  72. 12
      src/Avalonia.Themes.Fluent/Accents/Base.xaml
  73. 9
      src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml
  74. 3
      src/Avalonia.Themes.Fluent/AutoCompleteBox.xaml
  75. 1
      src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj
  76. 14
      src/Avalonia.Themes.Fluent/Button.xaml
  77. 8
      src/Avalonia.Themes.Fluent/ButtonSpinner.xaml
  78. 2
      src/Avalonia.Themes.Fluent/CalendarButton.xaml
  79. 6
      src/Avalonia.Themes.Fluent/CalendarDatePicker.xaml
  80. 1
      src/Avalonia.Themes.Fluent/ComboBox.xaml
  81. 18
      src/Avalonia.Themes.Fluent/DataValidationErrors.xaml
  82. 6
      src/Avalonia.Themes.Fluent/Menu.xaml
  83. 188
      src/Avalonia.Themes.Fluent/MenuItem.xaml
  84. 2
      src/Avalonia.Themes.Fluent/NumericUpDown.xaml
  85. 8
      src/Avalonia.Themes.Fluent/RepeatButton.xaml
  86. 21
      src/Avalonia.Themes.Fluent/TextBox.xaml
  87. 2
      src/Avalonia.Themes.Fluent/TitleBar.xaml
  88. 22
      src/Avalonia.Themes.Fluent/ToggleButton.xaml
  89. 4
      src/Avalonia.Themes.Fluent/ToggleSwitch.xaml
  90. 22
      src/Avalonia.Themes.Fluent/Window.xaml
  91. 4
      src/Avalonia.Visuals/ApiCompatBaseline.txt
  92. 1
      src/Avalonia.Visuals/Avalonia.Visuals.csproj
  93. 2
      src/Avalonia.Visuals/Media/CharacterHit.cs
  94. 8
      src/Avalonia.Visuals/Media/FontStyle.cs
  95. 5
      src/Avalonia.Visuals/Media/RadialGradientBrush.cs
  96. 79
      src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs
  97. 5
      src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs
  98. 22
      src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs
  99. 38
      src/Avalonia.Visuals/Rendering/RenderLoop.cs
  100. 72
      src/Avalonia.Visuals/Rendering/SleepLoopRenderTimer.cs

13
Avalonia.sln

@ -123,10 +123,13 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ControlCatalog.NetCore", "s
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Props", "Props", "{F3AC8BC1-27F5-4255-9AFC-04ABFD11683A}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
build\AndroidWorkarounds.props = build\AndroidWorkarounds.props
build\Base.props = build\Base.props build\Base.props = build\Base.props
build\Binding.props = build\Binding.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\HarfBuzzSharp.props = build\HarfBuzzSharp.props
build\iOSWorkarounds.props = build\iOSWorkarounds.props
build\JetBrains.Annotations.props = build\JetBrains.Annotations.props build\JetBrains.Annotations.props = build\JetBrains.Annotations.props
build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props build\JetBrains.dotMemoryUnit.props = build\JetBrains.dotMemoryUnit.props
build\Magick.NET-Q16-AnyCPU.props = build\Magick.NET-Q16-AnyCPU.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\NetCore.props = build\NetCore.props
build\NetFX.props = build\NetFX.props build\NetFX.props = build\NetFX.props
build\ReactiveUI.props = build\ReactiveUI.props build\ReactiveUI.props = build\ReactiveUI.props
build\ReferenceCoreLibraries.props = build\ReferenceCoreLibraries.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
build\SharedVersion.props = build\SharedVersion.props
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\SourceLink.props = build\SourceLink.props
build\System.Drawing.Common.props = build\System.Drawing.Common.props
build\System.Memory.props = build\System.Memory.props build\System.Memory.props = build\System.Memory.props
build\UnitTests.NetFX.props = build\UnitTests.NetFX.props
build\XUnit.props = build\XUnit.props build\XUnit.props = build\XUnit.props
build\ApiDiff.props = build\ApiDiff.props
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Targets", "Targets", "{4D6FAF79-58B4-482F-9122-0668C346364C}"
ProjectSection(SolutionItems) = preProject ProjectSection(SolutionItems) = preProject
build\UnitTests.NetCore.targets = build\UnitTests.NetCore.targets build\UnitTests.NetCore.targets = build\UnitTests.NetCore.targets
build\BuildTargets.targets = build\BuildTargets.targets
build\LegacyProject.targets = build\LegacyProject.targets
EndProjectSection EndProjectSection
EndProject EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}" Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux", "Linux", "{86C53C40-57AA-45B8-AD42-FAE0EFDF0F2B}"

2
NuGet.Config

@ -1,7 +1,9 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<packageSources> <packageSources>
<clear /> <clear />
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" /> <add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
</packageSources> </packageSources>
</configuration> </configuration>

12
build/ApiDiff.props

@ -0,0 +1,12 @@
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ApiContractPackageVersion>0.10.0-preview2</ApiContractPackageVersion>
<NugetPackageName Condition="'$(PackageId)' != ''">$(PackageId)</NugetPackageName>
<NugetPackageName Condition="'$(PackageId)' == ''">Avalonia</NugetPackageName>
</PropertyGroup>
<ItemGroup>
<PackageDownload Include="$(NugetPackageName)" Version="[$(ApiContractPackageVersion)]" />
<PackageReference Include="Microsoft.DotNet.ApiCompat" Version="5.0.0-beta.20372.2" PrivateAssets="All" />
<ResolvedMatchingContract Include="$(NuGetPackageRoot)\$(NugetPackageName.ToLower())\$(ApiContractPackageVersion)\lib\$(TargetFramework)\$(AssemblyName).dll" />
</ItemGroup>
</Project>

2
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="2.80.0" /> <PackageReference Include="SkiaSharp" Version="2.80.1" />
<PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.80.0" /> <PackageReference Condition="'$(IncludeLinuxSkia)' == 'true'" Include="SkiaSharp.NativeAssets.Linux" Version="2.80.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

4
nukebuild/Build.cs

@ -128,7 +128,9 @@ partial class Build : NukeBuild
{ {
var webappDir = RootDirectory / "src" / "Avalonia.DesignerSupport" / "Remote" / "HtmlTransport" / "webapp"; 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 NpmTasks.NpmRun(c => c
.SetWorkingDirectory(webappDir) .SetWorkingDirectory(webappDir)
.SetCommand("dist")); .SetCommand("dist"));

2
readme.md

@ -1,4 +1,4 @@
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) ![License](https://img.shields.io/github/license/avaloniaui/avalonia.svg) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/AvaloniaUI/Avalonia?utm_campaign=pr-badge&utm_content=badge&utm_medium=badge&utm_source=badge) [![Discord](https://img.shields.io/badge/discord-join%20chat-46BC99)]( https://aka.ms/dotnet-discord) [![Build Status](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_apis/build/status/AvaloniaUI.Avalonia)](https://dev.azure.com/AvaloniaUI/AvaloniaUI/_build/latest?definitionId=4) [![Backers on Open Collective](https://opencollective.com/Avalonia/backers/badge.svg)](#backers) [![Sponsors on Open Collective](https://opencollective.com/Avalonia/sponsors/badge.svg)](#sponsors) ![License](https://img.shields.io/github/license/avaloniaui/avalonia.svg)
<br /> <br />
[![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) [![downloads](https://img.shields.io/nuget/dt/avalonia)](https://www.nuget.org/packages/Avalonia) [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) ![Size](https://img.shields.io/github/repo-size/avaloniaui/avalonia.svg) [![NuGet](https://img.shields.io/nuget/v/Avalonia.svg)](https://www.nuget.org/packages/Avalonia) [![downloads](https://img.shields.io/nuget/dt/avalonia)](https://www.nuget.org/packages/Avalonia) [![MyGet](https://img.shields.io/myget/avalonia-ci/vpre/Avalonia.svg?label=myget)](https://www.myget.org/gallery/avalonia-ci) ![Size](https://img.shields.io/github/repo-size/avaloniaui/avalonia.svg)

8
samples/ControlCatalog/App.xaml

@ -4,14 +4,14 @@
<Application.Styles> <Application.Styles>
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/> <StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
<Style Selector="TextBlock.h1"> <Style Selector="TextBlock.h1">
<Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/> <Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Medium"/> <Setter Property="FontWeight" Value="Medium" />
</Style> </Style>
<Style Selector="TextBlock.h2"> <Style Selector="TextBlock.h2">
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}"/> <Setter Property="FontSize" Value="14" />
</Style> </Style>
<Style Selector="TextBlock.h3"> <Style Selector="TextBlock.h3">
<Setter Property="FontSize" Value="{DynamicResource FontSizeSmall}"/> <Setter Property="FontSize" Value="10" />
</Style> </Style>
<StyleInclude Source="/SideBar.xaml"/> <StyleInclude Source="/SideBar.xaml"/>
</Application.Styles> </Application.Styles>

4
samples/ControlCatalog/App.xaml.cs

@ -67,9 +67,9 @@ namespace ControlCatalog
public override void Initialize() public override void Initialize()
{ {
AvaloniaXamlLoader.Load(this);
Styles.Insert(0, FluentDark); Styles.Insert(0, FluentDark);
AvaloniaXamlLoader.Load(this);
} }
public override void OnFrameworkInitializationCompleted() public override void OnFrameworkInitializationCompleted()

4
samples/ControlCatalog/MainView.xaml

@ -1,9 +1,7 @@
<UserControl xmlns="https://github.com/avaloniaui" <UserControl xmlns="https://github.com/avaloniaui"
xmlns:pages="clr-namespace:ControlCatalog.Pages" xmlns:pages="clr-namespace:ControlCatalog.Pages"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="ControlCatalog.MainView" x:Class="ControlCatalog.MainView">
Foreground="{DynamicResource ThemeForegroundBrush}"
FontSize="{DynamicResource FontSizeNormal}">
<Grid> <Grid>
<Grid.Styles> <Grid.Styles>
<Style Selector="TextBlock.h2"> <Style Selector="TextBlock.h2">

14
samples/ControlCatalog/MainWindow.xaml.cs

@ -63,8 +63,18 @@ namespace ControlCatalog
// TODO: iOS does not support dynamically loading assemblies // TODO: iOS does not support dynamically loading assemblies
// so we must refer to this resource DLL statically. For // so we must refer to this resource DLL statically. For
// now I am doing that here. But we need a better solution!! // now I am doing that here. But we need a better solution!!
var theme = new Avalonia.Themes.Default.DefaultTheme(); // Note, theme swiching probably will not work in runtime for iOS.
theme.TryGetResource("Button", out _); if (Application.Current.Styles.Contains(App.FluentDark)
|| Application.Current.Styles.Contains(App.FluentLight))
{
var theme = new Avalonia.Themes.Fluent.FluentTheme();
theme.TryGetResource("Button", out _);
}
else
{
var theme = new Avalonia.Themes.Default.DefaultTheme();
theme.TryGetResource("Button", out _);
}
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
} }

4
samples/ControlCatalog/Pages/ButtonPage.xaml

@ -20,6 +20,10 @@
<Style.Resources> <Style.Resources>
<SolidColorBrush x:Key="ThemeBorderMidBrush">Red</SolidColorBrush> <SolidColorBrush x:Key="ThemeBorderMidBrush">Red</SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighBrush">DarkRed</SolidColorBrush> <SolidColorBrush x:Key="ThemeControlHighBrush">DarkRed</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBorderBrush">Red</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBackground">DarkRed</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBackgroundPointerOver">Red</SolidColorBrush>
<SolidColorBrush x:Key="ButtonBackgroundPressed">OrangeRed</SolidColorBrush>
</Style.Resources> </Style.Resources>
</Style> </Style>
</Button.Styles> </Button.Styles>

2
samples/ControlCatalog/Pages/ItemsRepeaterPage.xaml

@ -43,7 +43,7 @@
<Button x:Name="scrollToLast">Scroll to Last</Button> <Button x:Name="scrollToLast">Scroll to Last</Button>
<Button x:Name="scrollToRandom">Scroll to Random</Button> <Button x:Name="scrollToRandom">Scroll to Random</Button>
</StackPanel> </StackPanel>
<Border BorderThickness="1" BorderBrush="{DynamicResource ThemeBorderMidBrush}" Margin="0 0 0 16"> <Border BorderThickness="1" BorderBrush="{DynamicResource SystemControlHighlightBaseMediumLowBrush}" Margin="0 0 0 16">
<ScrollViewer Name="scroller" <ScrollViewer Name="scroller"
HorizontalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto"> VerticalScrollBarVisibility="Auto">

3
samples/ControlCatalog/Pages/ListBoxPage.xaml

@ -11,8 +11,7 @@
Spacing="16"> Spacing="16">
<StackPanel Orientation="Vertical" Spacing="8"> <StackPanel Orientation="Vertical" Spacing="8">
<ListBox Items="{Binding Items}" <ListBox Items="{Binding Items}"
SelectedItem="{Binding SelectedItem}" Selection="{Binding Selection}"
SelectedItems="{Binding SelectedItems}"
AutoScrollToSelectedItem="True" AutoScrollToSelectedItem="True"
SelectionMode="{Binding SelectionMode}" SelectionMode="{Binding SelectionMode}"
Width="250" Width="250"

68
samples/ControlCatalog/Pages/ListBoxPage.xaml.cs

@ -1,10 +1,6 @@
using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Reactive;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using ReactiveUI; using ControlCatalog.ViewModels;
namespace ControlCatalog.Pages namespace ControlCatalog.Pages
{ {
@ -13,72 +9,12 @@ namespace ControlCatalog.Pages
public ListBoxPage() public ListBoxPage()
{ {
InitializeComponent(); InitializeComponent();
DataContext = new PageViewModel(); DataContext = new ListBoxPageViewModel();
} }
private void InitializeComponent() private void InitializeComponent()
{ {
AvaloniaXamlLoader.Load(this); AvaloniaXamlLoader.Load(this);
} }
private class PageViewModel : ReactiveObject
{
private int _counter;
private SelectionMode _selectionMode;
public PageViewModel()
{
Items = new ObservableCollection<string>(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
SelectedItems = new ObservableCollection<string>();
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<string> Items { get; }
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
}
public ObservableCollection<string> SelectedItems { get; }
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }
public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
SelectedItems.Clear();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}
private string GenerateItem() => $"Item {_counter++.ToString()}";
}
} }
} }

31
samples/ControlCatalog/Pages/MenuPage.xaml

@ -20,7 +20,9 @@
<Separator/> <Separator/>
<MenuItem Header="Menu with _Submenu"> <MenuItem Header="Menu with _Submenu">
<MenuItem Header="Submenu _1"/> <MenuItem Header="Submenu _1"/>
<MenuItem Header="Submenu _2"/> <MenuItem Header="Submenu _2 with Submenu">
<MenuItem Header="Submenu Level 2" />
</MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="Menu Item with _Icon" InputGesture="Ctrl+Shift+B"> <MenuItem Header="Menu Item with _Icon" InputGesture="Ctrl+Shift+B">
<MenuItem.Icon> <MenuItem.Icon>
@ -52,6 +54,33 @@
</Menu.Styles> </Menu.Styles>
</Menu> </Menu>
</StackPanel> </StackPanel>
<StackPanel>
<TextBlock Classes="h3" Margin="4 8">Mixed</TextBlock>
<Menu>
<MenuItem Header="_File">
<MenuItem Header="_New" CommandParameter="{Binding}" InputGesture="Ctrl+N"/>
<Separator/>
<MenuItem Header="_Open..." InputGesture="Ctrl+O"/>
<Separator/>
<MenuItem Header="Execu_te Script..." />
<Separator/>
<MenuItem Header="_Recent" Items="{Binding RecentItems}">
<MenuItem.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Header}"/>
</Style>
</MenuItem.Styles>
</MenuItem>
<Separator/>
<MenuItem Header="E_xit" InputGesture="Alt+F4"/>
</MenuItem>
<MenuItem Header="_Help">
<MenuItem Header="_About"/>
</MenuItem>
</Menu>
</StackPanel>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

13
samples/ControlCatalog/Pages/ScreenPage.cs

@ -29,7 +29,8 @@ namespace ControlCatalog.Pages
var screens = w.Screens.All; var screens = w.Screens.All;
var scaling = ((IRenderRoot)w).RenderScaling; var scaling = ((IRenderRoot)w).RenderScaling;
Pen p = new Pen(Brushes.Black); var drawBrush = Brushes.Green;
Pen p = new Pen(drawBrush);
if (screens != null) if (screens != null)
foreach (Screen screen in screens) foreach (Screen screen in screens)
{ {
@ -53,19 +54,19 @@ namespace ControlCatalog.Pages
}; };
text.Text = $"Bounds: {screen.Bounds.Width}:{screen.Bounds.Height}"; 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}"; 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}%"; 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}"; 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))))}"; 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)); context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10));

4
samples/ControlCatalog/Pages/TextBlockPage.xaml

@ -12,7 +12,7 @@
<StackPanel.Styles> <StackPanel.Styles>
<Style Selector="Border"> <Style Selector="Border">
<Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/> <Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightBaseMediumLowBrush}"/>
<Setter Property="Padding" Value="2"/> <Setter Property="Padding" Value="2"/>
</Style> </Style>
</StackPanel.Styles> </StackPanel.Styles>
@ -49,7 +49,7 @@
<StackPanel.Styles> <StackPanel.Styles>
<Style Selector="Border"> <Style Selector="Border">
<Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderThickness" Value="1"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}"/> <Setter Property="BorderBrush" Value="{DynamicResource SystemControlHighlightBaseMediumLowBrush}"/>
<Setter Property="Padding" Value="2"/> <Setter Property="Padding" Value="2"/>
</Style> </Style>
</StackPanel.Styles> </StackPanel.Styles>

65
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<string>(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<string> Items { get; }
public SelectionModel Selection { get; }
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }
public SelectionMode SelectionMode
{
get => _selectionMode;
set
{
Selection.ClearSelection();
this.RaiseAndSetIfChanged(ref _selectionMode, value);
}
}
private string GenerateItem() => $"Item {_counter++.ToString()}";
}
}

36
samples/ControlCatalog/ViewModels/MenuPageViewModel.cs

@ -17,6 +17,23 @@ namespace ControlCatalog.ViewModels
SaveCommand = ReactiveCommand.Create(Save, Observable.Return(false)); SaveCommand = ReactiveCommand.Create(Save, Observable.Return(false));
OpenRecentCommand = ReactiveCommand.Create<string>(OpenRecent); OpenRecentCommand = ReactiveCommand.Create<string>(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[] MenuItems = new[]
{ {
new MenuItemViewModel new MenuItemViewModel
@ -24,27 +41,13 @@ namespace ControlCatalog.ViewModels
Header = "_File", Header = "_File",
Items = new[] Items = new[]
{ {
new MenuItemViewModel { Header = "_Open...", Command = OpenCommand }, new MenuItemViewModel { Header = "O_pen...", Command = OpenCommand },
new MenuItemViewModel { Header = "Save", Command = SaveCommand }, new MenuItemViewModel { Header = "Save", Command = SaveCommand },
new MenuItemViewModel { Header = "-" }, new MenuItemViewModel { Header = "-" },
new MenuItemViewModel new MenuItemViewModel
{ {
Header = "Recent", Header = "Recent",
Items = new[] Items = recentItems
{
new MenuItemViewModel
{
Header = "File1.txt",
Command = OpenRecentCommand,
CommandParameter = @"c:\foo\File1.txt"
},
new MenuItemViewModel
{
Header = "File2.txt",
Command = OpenRecentCommand,
CommandParameter = @"c:\foo\File2.txt"
},
}
}, },
} }
}, },
@ -61,6 +64,7 @@ namespace ControlCatalog.ViewModels
} }
public IReadOnlyList<MenuItemViewModel> MenuItems { get; set; } public IReadOnlyList<MenuItemViewModel> MenuItems { get; set; }
public IReadOnlyList<MenuItemViewModel> RecentItems { get; set; }
public ReactiveCommand<Unit, Unit> OpenCommand { get; } public ReactiveCommand<Unit, Unit> OpenCommand { get; }
public ReactiveCommand<Unit, Unit> SaveCommand { get; } public ReactiveCommand<Unit, Unit> SaveCommand { get; }
public ReactiveCommand<string, Unit> OpenRecentCommand { get; } public ReactiveCommand<string, Unit> OpenRecentCommand { get; }

3
src/Avalonia.Animation/Avalonia.Animation.csproj

@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" /> <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

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

@ -3,7 +3,7 @@
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>Avalonia.Base</AssemblyName> <AssemblyName>Avalonia.Base</AssemblyName>
<RootNamespace>Avalonia</RootNamespace> <RootNamespace>Avalonia</RootNamespace>
<AllowUnsafeBlocks>True</AllowUnsafeBlocks> <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj"/> <ProjectReference Include="..\Avalonia.Build.Tasks\Avalonia.Build.Tasks.csproj"/>
@ -13,4 +13,5 @@
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" /> <Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\System.Memory.props" /> <Import Project="..\..\build\System.Memory.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

61
src/Avalonia.Base/Threading/AvaloniaScheduler.cs

@ -9,6 +9,16 @@ namespace Avalonia.Threading
/// </summary> /// </summary>
public class AvaloniaScheduler : LocalScheduler public class AvaloniaScheduler : LocalScheduler
{ {
/// <summary>
/// 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 <see cref="Schedule{TState}"/> before we will
/// schedule on a dispatcher anyway.
/// </summary>
private const int MaxReentrantSchedules = 32;
private int _reentrancyGuard;
/// <summary> /// <summary>
/// The instance of the <see cref="AvaloniaScheduler"/>. /// The instance of the <see cref="AvaloniaScheduler"/>.
/// </summary> /// </summary>
@ -24,31 +34,58 @@ namespace Avalonia.Threading
/// <inheritdoc/> /// <inheritdoc/>
public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> action) public override IDisposable Schedule<TState>(TState state, TimeSpan dueTime, Func<IScheduler, TState, IDisposable> 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 (dueTime == TimeSpan.Zero)
{ {
if (!Dispatcher.UIThread.CheckAccess()) if (!Dispatcher.UIThread.CheckAccess())
{ {
var cancellation = new CancellationDisposable(); return PostOnDispatcher();
Dispatcher.UIThread.Post(() =>
{
if (!cancellation.Token.IsCancellationRequested)
{
composite.Add(action(this, state));
}
}, DispatcherPriority.DataBind);
composite.Add(cancellation);
} }
else else
{ {
return action(this, state); if (_reentrancyGuard >= MaxReentrantSchedules)
{
return PostOnDispatcher();
}
try
{
_reentrancyGuard++;
return action(this, state);
}
finally
{
_reentrancyGuard--;
}
} }
} }
else else
{ {
var composite = new CompositeDisposable(2);
composite.Add(DispatcherTimer.RunOnce(() => composite.Add(action(this, state)), dueTime)); composite.Add(DispatcherTimer.RunOnce(() => composite.Add(action(this, state)), dueTime));
return composite;
} }
return composite;
} }
} }
} }

2
src/Avalonia.Build.Tasks/XamlCompilerTaskExecutor.cs

@ -128,7 +128,7 @@ namespace Avalonia.Build.Tasks
asm.MainModule.Types.Add(typeDef); asm.MainModule.Types.Add(typeDef);
var builder = typeSystem.CreateTypeBuilder(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 try
{ {

1
src/Avalonia.Controls.DataGrid/Avalonia.Controls.DataGrid.csproj

@ -22,4 +22,5 @@
<Import Project="..\..\build\EmbedXaml.props" /> <Import Project="..\..\build\EmbedXaml.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" /> <Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

3
src/Avalonia.Controls/Avalonia.Controls.csproj

@ -1,6 +1,6 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" /> <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
@ -14,4 +14,5 @@
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\JetBrains.Annotations.props" /> <Import Project="..\..\build\JetBrains.Annotations.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

6
src/Avalonia.Controls/Chrome/CaptionButtons.cs

@ -38,12 +38,10 @@ namespace Avalonia.Controls.Chrome
{ {
if (_disposables != null) if (_disposables != null)
{ {
var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
layer?.Children.Remove(this);
_disposables.Dispose(); _disposables.Dispose();
_disposables = null; _disposables = null;
_hostWindow = null;
} }
} }

126
src/Avalonia.Controls/Chrome/TitleBar.cs

@ -12,106 +12,86 @@ namespace Avalonia.Controls.Chrome
public class TitleBar : TemplatedControl public class TitleBar : TemplatedControl
{ {
private CompositeDisposable? _disposables; private CompositeDisposable? _disposables;
private readonly Window? _hostWindow;
private CaptionButtons? _captionButtons; private CaptionButtons? _captionButtons;
public TitleBar(Window hostWindow) private void UpdateSize(Window window)
{ {
_hostWindow = hostWindow; if (window != null)
}
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)
{ {
Margin = new Thickness( Margin = new Thickness(
_hostWindow.OffScreenMargin.Left, window.OffScreenMargin.Left,
_hostWindow.OffScreenMargin.Top, window.OffScreenMargin.Top,
_hostWindow.OffScreenMargin.Right, window.OffScreenMargin.Right,
_hostWindow.OffScreenMargin.Bottom); window.OffScreenMargin.Bottom);
if (_hostWindow.WindowState != WindowState.FullScreen) if (window.WindowState != WindowState.FullScreen)
{ {
Height = _hostWindow.WindowDecorationMargin.Top; Height = window.WindowDecorationMargin.Top;
if (_captionButtons != null) if (_captionButtons != null)
{ {
_captionButtons.Height = Height; _captionButtons.Height = Height;
} }
} }
IsVisible = window.PlatformImpl.NeedsManagedDecorations;
} }
} }
public void Detach() protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
if (_disposables != null) base.OnApplyTemplate(e);
{
var layer = ChromeOverlayLayer.GetOverlayLayer(_hostWindow);
layer?.Children.Remove(this);
_disposables.Dispose(); _captionButtons?.Detach();
_disposables = null;
_captionButtons = e.NameScope.Get<CaptionButtons>("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); base.OnAttachedToVisualTree(e);
_captionButtons = e.NameScope.Get<CaptionButtons>("PART_CaptionButtons");
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;
} }
} }
} }

9
src/Avalonia.Controls/DateTimePickers/DatePickerPresenter.cs

@ -356,10 +356,17 @@ namespace Avalonia.Controls
} }
if (MonthVisible) if (MonthVisible)
{
_monthSelector.SelectedValue = dt.Month; _monthSelector.SelectedValue = dt.Month;
_monthSelector.FormatDate = dt.Date;
}
if (YearVisible) if (YearVisible)
{
_yearSelector.SelectedValue = dt.Year; _yearSelector.SelectedValue = dt.Year;
_yearSelector.FormatDate = dt.Date;
}
_suppressUpdateSelection = false; _suppressUpdateSelection = false;
SetInitialFocus(); SetInitialFocus();

51
src/Avalonia.Controls/DateTimePickers/TimePicker.cs

@ -15,7 +15,7 @@ namespace Avalonia.Controls
/// Defines the <see cref="MinuteIncrement"/> property /// Defines the <see cref="MinuteIncrement"/> property
/// </summary> /// </summary>
public static readonly DirectProperty<TimePicker, int> MinuteIncrementProperty = public static readonly DirectProperty<TimePicker, int> MinuteIncrementProperty =
AvaloniaProperty.RegisterDirect<TimePicker, int>(nameof(MinuteIncrement), AvaloniaProperty.RegisterDirect<TimePicker, int>(nameof(MinuteIncrement),
x => x.MinuteIncrement, (x, v) => x.MinuteIncrement = v); x => x.MinuteIncrement, (x, v) => x.MinuteIncrement = v);
/// <summary> /// <summary>
@ -34,17 +34,17 @@ namespace Avalonia.Controls
/// Defines the <see cref="ClockIdentifier"/> property /// Defines the <see cref="ClockIdentifier"/> property
/// </summary> /// </summary>
public static readonly DirectProperty<TimePicker, string> ClockIdentifierProperty = public static readonly DirectProperty<TimePicker, string> ClockIdentifierProperty =
AvaloniaProperty.RegisterDirect<TimePicker, string>(nameof(ClockIdentifier), AvaloniaProperty.RegisterDirect<TimePicker, string>(nameof(ClockIdentifier),
x => x.ClockIdentifier, (x, v) => x.ClockIdentifier = v); x => x.ClockIdentifier, (x, v) => x.ClockIdentifier = v);
/// <summary> /// <summary>
/// Defines the <see cref="SelectedTime"/> property /// Defines the <see cref="SelectedTime"/> property
/// </summary> /// </summary>
public static readonly DirectProperty<TimePicker, TimeSpan?> SelectedTimeProperty = public static readonly DirectProperty<TimePicker, TimeSpan?> SelectedTimeProperty =
AvaloniaProperty.RegisterDirect<TimePicker, TimeSpan?>(nameof(SelectedTime), AvaloniaProperty.RegisterDirect<TimePicker, TimeSpan?>(nameof(SelectedTime),
x => x.SelectedTime, (x, v) => x.SelectedTime = v); x => x.SelectedTime, (x, v) => x.SelectedTime = v);
//Template Items // Template Items
private TimePickerPresenter _presenter; private TimePickerPresenter _presenter;
private Button _flyoutButton; private Button _flyoutButton;
private Border _firstPickerHost; private Border _firstPickerHost;
@ -52,7 +52,7 @@ namespace Avalonia.Controls
private Border _thirdPickerHost; private Border _thirdPickerHost;
private TextBlock _hourText; private TextBlock _hourText;
private TextBlock _minuteText; private TextBlock _minuteText;
public TextBlock _periodText; private TextBlock _periodText;
private Rectangle _firstSplitter; private Rectangle _firstSplitter;
private Rectangle _secondSplitter; private Rectangle _secondSplitter;
private Grid _contentGrid; private Grid _contentGrid;
@ -145,7 +145,7 @@ namespace Avalonia.Controls
if (_flyoutButton != null) if (_flyoutButton != null)
_flyoutButton.Click -= OnFlyoutButtonClicked; _flyoutButton.Click -= OnFlyoutButtonClicked;
if(_presenter != null) if (_presenter != null)
{ {
_presenter.Confirmed -= OnConfirmed; _presenter.Confirmed -= OnConfirmed;
_presenter.Dismissed -= OnDismissPicker; _presenter.Dismissed -= OnDismissPicker;
@ -170,7 +170,6 @@ namespace Avalonia.Controls
_popup = e.NameScope.Find<Popup>("Popup"); _popup = e.NameScope.Find<Popup>("Popup");
_presenter = e.NameScope.Find<TimePickerPresenter>("PickerPresenter"); _presenter = e.NameScope.Find<TimePickerPresenter>("PickerPresenter");
if (_flyoutButton != null) if (_flyoutButton != null)
_flyoutButton.Click += OnFlyoutButtonClicked; _flyoutButton.Click += OnFlyoutButtonClicked;
@ -185,7 +184,6 @@ namespace Avalonia.Controls
_presenter[!TimePickerPresenter.MinuteIncrementProperty] = this[!MinuteIncrementProperty]; _presenter[!TimePickerPresenter.MinuteIncrementProperty] = this[!MinuteIncrementProperty];
_presenter[!TimePickerPresenter.ClockIdentifierProperty] = this[!ClockIdentifierProperty]; _presenter[!TimePickerPresenter.ClockIdentifierProperty] = this[!ClockIdentifierProperty];
} }
} }
private void SetGrid() private void SetGrid()
@ -195,30 +193,19 @@ namespace Avalonia.Controls
bool use24HourClock = ClockIdentifier == "24HourClock"; bool use24HourClock = ClockIdentifier == "24HourClock";
if (!use24HourClock) var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
{ _contentGrid.ColumnDefinitions = new ColumnDefinitions(columnsD);
_contentGrid.ColumnDefinitions = new ColumnDefinitions("*,Auto,*,Auto,*");
_thirdPickerHost.IsVisible = true;
_secondSplitter.IsVisible = true;
Grid.SetColumn(_firstPickerHost, 0); _thirdPickerHost.IsVisible = !use24HourClock;
Grid.SetColumn(_secondPickerHost, 2); _secondSplitter.IsVisible = !use24HourClock;
Grid.SetColumn(_thirdPickerHost, 4);
Grid.SetColumn(_firstSplitter, 1); Grid.SetColumn(_firstPickerHost, 0);
Grid.SetColumn(_secondSplitter, 3); Grid.SetColumn(_secondPickerHost, 2);
}
else
{
_contentGrid.ColumnDefinitions = new ColumnDefinitions("*,Auto,*");
_thirdPickerHost.IsVisible = false;
_secondSplitter.IsVisible = false;
Grid.SetColumn(_firstPickerHost, 0); Grid.SetColumn(_thirdPickerHost, use24HourClock ? 0 : 4);
Grid.SetColumn(_secondPickerHost, 2);
Grid.SetColumn(_firstSplitter, 1); Grid.SetColumn(_firstSplitter, 1);
} Grid.SetColumn(_secondSplitter, use24HourClock ? 0 : 3);
} }
private void SetSelectedTimeText() private void SetSelectedTimeText()
@ -237,14 +224,13 @@ namespace Avalonia.Controls
hr = hr > 12 ? hr - 12 : hr == 0 ? 12 : hr; hr = hr > 12 ? hr - 12 : hr == 0 ? 12 : hr;
newTime = new TimeSpan(hr, newTime.Minutes, 0); newTime = new TimeSpan(hr, newTime.Minutes, 0);
} }
_hourText.Text = newTime.ToString("%h");
_hourText.Text = newTime.ToString("%h");
_minuteText.Text = newTime.ToString("mm"); _minuteText.Text = newTime.ToString("mm");
PseudoClasses.Set(":hasnotime", false); PseudoClasses.Set(":hasnotime", false);
_periodText.Text = time.Value.Hours >= 12 ? CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator : _periodText.Text = time.Value.Hours >= 12 ? CultureInfo.CurrentCulture.DateTimeFormat.PMDesignator :
CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator; CultureInfo.CurrentCulture.DateTimeFormat.AMDesignator;
} }
else else
{ {
@ -262,7 +248,7 @@ namespace Avalonia.Controls
SelectedTimeChanged?.Invoke(this, new TimePickerSelectedValueChangedEventArgs(oldTime, newTime)); 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; _presenter.Time = SelectedTime ?? DateTime.Now.TimeOfDay;
@ -270,7 +256,7 @@ namespace Avalonia.Controls
var deltaY = _presenter.GetOffsetForPopup(); 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), _popup.Host.ConfigurePosition(_popup.PlacementTarget, PlacementMode.AnchorAndGravity, new Point(0, deltaY + 5),
Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom, Primitives.PopupPositioning.PopupAnchor.Bottom, Primitives.PopupPositioning.PopupGravity.Bottom,
Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY); Primitives.PopupPositioning.PopupPositionerConstraintAdjustment.SlideY);
@ -287,6 +273,5 @@ namespace Avalonia.Controls
_popup.Close(); _popup.Close();
SelectedTime = _presenter.Time; SelectedTime = _presenter.Time;
} }
} }
} }

38
src/Avalonia.Controls/DateTimePickers/TimePickerPresenter.cs

@ -39,7 +39,7 @@ namespace Avalonia.Controls
KeyboardNavigation.SetTabNavigation(this, KeyboardNavigationMode.Cycle); KeyboardNavigation.SetTabNavigation(this, KeyboardNavigationMode.Cycle);
} }
//TemplateItems // TemplateItems
private Grid _pickerContainer; private Grid _pickerContainer;
private Button _acceptButton; private Button _acceptButton;
private Button _dismissButton; private Button _dismissButton;
@ -55,8 +55,8 @@ namespace Avalonia.Controls
private Button _minuteDownButton; private Button _minuteDownButton;
private Button _periodDownButton; private Button _periodDownButton;
//Backing Fields // Backing Fields
private TimeSpan _Time; private TimeSpan _time;
private int _minuteIncrement = 1; private int _minuteIncrement = 1;
private string _clockIdentifier = "12HourClock"; private string _clockIdentifier = "12HourClock";
@ -83,7 +83,7 @@ namespace Avalonia.Controls
get => _clockIdentifier; get => _clockIdentifier;
set set
{ {
if (string.IsNullOrEmpty(value) || value == "" || !(value == "12HourClock" || value == "24HourClock")) if (string.IsNullOrEmpty(value) || !(value == "12HourClock" || value == "24HourClock"))
throw new ArgumentException("Invalid ClockIdentifier"); throw new ArgumentException("Invalid ClockIdentifier");
SetAndRaise(ClockIdentifierProperty, ref _clockIdentifier, value); SetAndRaise(ClockIdentifierProperty, ref _clockIdentifier, value);
InitPicker(); InitPicker();
@ -95,10 +95,10 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public TimeSpan Time public TimeSpan Time
{ {
get => _Time; get => _time;
set set
{ {
SetAndRaise(TimeProperty, ref _Time, value); SetAndRaise(TimeProperty, ref _time, value);
InitPicker(); InitPicker();
} }
} }
@ -213,26 +213,24 @@ namespace Avalonia.Controls
private void SetGrid() private void SetGrid()
{ {
if (ClockIdentifier == "12HourClock") bool use24HourClock = ClockIdentifier == "24HourClock";
{
_pickerContainer.ColumnDefinitions = new ColumnDefinitions("*,Auto,*,Auto,*"); var columnsD = use24HourClock ? "*, Auto, *" : "*, Auto, *, Auto, *";
_spacer2.IsVisible = true; _pickerContainer.ColumnDefinitions = new ColumnDefinitions(columnsD);
_periodHost.IsVisible = true;
} _spacer2.IsVisible = !use24HourClock;
else _periodHost.IsVisible = !use24HourClock;
{
_pickerContainer.ColumnDefinitions = new ColumnDefinitions("*,Auto,*"); Grid.SetColumn(_spacer2, use24HourClock ? 0 : 3);
_spacer2.IsVisible = false; Grid.SetColumn(_periodHost, use24HourClock ? 0 : 4);
_periodHost.IsVisible = false;
}
} }
private void OnDismissButtonClicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) private void OnDismissButtonClicked(object sender, RoutedEventArgs e)
{ {
OnDismiss(); OnDismiss();
} }
private void OnAcceptButtonClicked(object sender, Avalonia.Interactivity.RoutedEventArgs e) private void OnAcceptButtonClicked(object sender, RoutedEventArgs e)
{ {
OnConfirmed(); OnConfirmed();
} }

8
src/Avalonia.Controls/MenuItem.cs

@ -97,7 +97,6 @@ namespace Avalonia.Controls
private ICommand _command; private ICommand _command;
private bool _commandCanExecute = true; private bool _commandCanExecute = true;
private Popup _popup; private Popup _popup;
private IDisposable _gridHack;
/// <summary> /// <summary>
/// Initializes static members of the <see cref="MenuItem"/> class. /// Initializes static members of the <see cref="MenuItem"/> class.
@ -323,9 +322,6 @@ namespace Avalonia.Controls
{ {
Command.CanExecuteChanged -= CanExecuteChanged; Command.CanExecuteChanged -= CanExecuteChanged;
} }
_gridHack?.Dispose();
_gridHack = null;
} }
protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e)
@ -345,9 +341,7 @@ namespace Avalonia.Controls
// the WPF codebase: // the WPF codebase:
// //
// https://github.com/dotnet/wpf/blob/89537909bdf36bc918e88b37751add46a8980bb0/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L2126-L2141 // https://github.com/dotnet/wpf/blob/89537909bdf36bc918e88b37751add46a8980bb0/src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/MenuItem.cs#L2126-L2141
_gridHack = Bind( SetValue(DefinitionBase.PrivateSharedSizeScopeProperty, parent.GetValue(DefinitionBase.PrivateSharedSizeScopeProperty));
DefinitionBase.PrivateSharedSizeScopeProperty,
parent.GetBindingObservable(DefinitionBase.PrivateSharedSizeScopeProperty));
} }
} }

7
src/Avalonia.Controls/Primitives/ChromeOverlayLayer.cs

@ -8,7 +8,7 @@ namespace Avalonia.Controls.Primitives
{ {
public class ChromeOverlayLayer : Panel, ICustomSimpleHitTest public class ChromeOverlayLayer : Panel, ICustomSimpleHitTest
{ {
public static ChromeOverlayLayer? GetOverlayLayer(IVisual visual) public static Panel? GetOverlayLayer(IVisual visual)
{ {
foreach (var v in visual.GetVisualAncestors()) foreach (var v in visual.GetVisualAncestors())
if (v is VisualLayerManager vlm) if (v is VisualLayerManager vlm)
@ -24,6 +24,11 @@ namespace Avalonia.Controls.Primitives
return null; return null;
} }
public void Add(Control c)
{
base.Children.Add(c);
}
public bool HitTest(Point point) => Children.HitTestCustom(point); public bool HitTest(Point point) => Children.HitTestCustom(point);
} }
} }

29
src/Avalonia.Controls/Primitives/VisualLayerManager.cs

@ -1,5 +1,6 @@
using System.Collections.Generic; using System.Collections.Generic;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Metadata;
namespace Avalonia.Controls.Primitives namespace Avalonia.Controls.Primitives
{ {
@ -11,10 +12,12 @@ namespace Avalonia.Controls.Primitives
private ILogicalRoot _logicalRoot; private ILogicalRoot _logicalRoot;
private readonly List<Control> _layers = new List<Control>(); private readonly List<Control> _layers = new List<Control>();
public static readonly StyledProperty<ChromeOverlayLayer> ChromeOverlayLayerProperty =
AvaloniaProperty.Register<VisualLayerManager, ChromeOverlayLayer>(nameof(ChromeOverlayLayer));
public bool IsPopup { get; set; } public bool IsPopup { get; set; }
public AdornerLayer AdornerLayer public AdornerLayer AdornerLayer
{ {
get get
@ -30,10 +33,19 @@ namespace Avalonia.Controls.Primitives
{ {
get get
{ {
var rv = FindLayer<ChromeOverlayLayer>(); var current = GetValue(ChromeOverlayLayerProperty);
if (rv == null)
AddLayer(rv = new ChromeOverlayLayer(), ChromeZIndex); if (current is null)
return rv; {
var chromeOverlayLayer = new ChromeOverlayLayer();
AddLayer(chromeOverlayLayer, ChromeZIndex);
SetValue(ChromeOverlayLayerProperty, chromeOverlayLayer);
current = chromeOverlayLayer;
}
return current;
} }
} }
@ -44,7 +56,7 @@ namespace Avalonia.Controls.Primitives
if (IsPopup) if (IsPopup)
return null; return null;
var rv = FindLayer<OverlayLayer>(); var rv = FindLayer<OverlayLayer>();
if(rv == null) if (rv == null)
AddLayer(rv = new OverlayLayer(), OverlayZIndex); AddLayer(rv = new OverlayLayer(), OverlayZIndex);
return rv; return rv;
} }
@ -65,7 +77,8 @@ namespace Avalonia.Controls.Primitives
layer.ZIndex = zindex; layer.ZIndex = zindex;
VisualChildren.Add(layer); VisualChildren.Add(layer);
if (((ILogical)this).IsAttachedToLogicalTree) if (((ILogical)this).IsAttachedToLogicalTree)
((ILogical)layer).NotifyAttachedToLogicalTree(new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this)); ((ILogical)layer).NotifyAttachedToLogicalTree(
new LogicalTreeAttachmentEventArgs(_logicalRoot, layer, this));
InvalidateArrange(); InvalidateArrange();
} }

2
src/Avalonia.Controls/ProgressBar.cs

@ -215,7 +215,7 @@ namespace Avalonia.Controls
TemplateProperties.Container2AnimationEndPosition = barIndicatorWidth2 * 1.66; // Position at 166% TemplateProperties.Container2AnimationEndPosition = barIndicatorWidth2 * 1.66; // Position at 166%
// Remove these properties when we switch to fluent as default and removed the old one. // Remove these properties when we switch to fluent as default and removed the old one.
IndeterminateStartingOffset = -(dim / 5d); IndeterminateStartingOffset = -dim;
IndeterminateEndingOffset = dim; IndeterminateEndingOffset = dim;
var padding = Padding; var padding = Padding;

15
src/Avalonia.Controls/Repeater/ItemsSourceView.cs

@ -25,7 +25,6 @@ namespace Avalonia.Controls
{ {
private readonly IList _inner; private readonly IList _inner;
private INotifyCollectionChanged _notifyCollectionChanged; private INotifyCollectionChanged _notifyCollectionChanged;
private int _cachedSize = -1;
/// <summary> /// <summary>
/// Initializes a new instance of the ItemsSourceView class for the specified data source. /// Initializes a new instance of the ItemsSourceView class for the specified data source.
@ -54,18 +53,7 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Gets the number of items in the collection. /// Gets the number of items in the collection.
/// </summary> /// </summary>
public int Count public int Count => _inner.Count;
{
get
{
if (_cachedSize == -1)
{
_cachedSize = _inner.Count;
}
return _cachedSize;
}
}
/// <summary> /// <summary>
/// Gets a value that indicates whether the items source can provide a unique key for each item. /// 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) protected void OnItemsSourceChanged(NotifyCollectionChangedEventArgs args)
{ {
_cachedSize = _inner.Count;
CollectionChanged?.Invoke(this, args); CollectionChanged?.Invoke(this, args);
} }

1
src/Avalonia.Controls/ToolTip.cs

@ -66,6 +66,7 @@ namespace Avalonia.Controls
static ToolTip() static ToolTip()
{ {
TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged); TipProperty.Changed.Subscribe(ToolTipService.Instance.TipChanged);
IsOpenProperty.Changed.Subscribe(ToolTipService.Instance.TipOpenChanged);
IsOpenProperty.Changed.Subscribe(IsOpenChanged); IsOpenProperty.Changed.Subscribe(IsOpenChanged);
} }

15
src/Avalonia.Controls/ToolTipService.cs

@ -28,20 +28,33 @@ namespace Avalonia.Controls
{ {
control.PointerEnter -= ControlPointerEnter; control.PointerEnter -= ControlPointerEnter;
control.PointerLeave -= ControlPointerLeave; control.PointerLeave -= ControlPointerLeave;
control.DetachedFromVisualTree -= ControlDetaching;
} }
if (e.NewValue != null) if (e.NewValue != null)
{ {
control.PointerEnter += ControlPointerEnter; control.PointerEnter += ControlPointerEnter;
control.PointerLeave += ControlPointerLeave; 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; control.DetachedFromVisualTree += ControlDetaching;
} }
else if(e.OldValue is true && e.NewValue is false)
{
control.DetachedFromVisualTree -= ControlDetaching;
}
} }
private void ControlDetaching(object sender, VisualTreeAttachmentEventArgs e) private void ControlDetaching(object sender, VisualTreeAttachmentEventArgs e)
{ {
var control = (Control)sender; var control = (Control)sender;
control.DetachedFromVisualTree -= ControlDetaching;
Close(control); Close(control);
} }

37
src/Avalonia.Controls/Utils/SelectedItemsSync.cs

@ -1,6 +1,7 @@
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq; using System.Linq;
using Avalonia.Collections; using Avalonia.Collections;
@ -16,6 +17,7 @@ namespace Avalonia.Controls.Utils
private IList? _items; private IList? _items;
private bool _updatingItems; private bool _updatingItems;
private bool _updatingModel; private bool _updatingModel;
private bool _initializeOnSourceAssignment;
public SelectedItemsSync(ISelectionModel model) public SelectedItemsSync(ISelectionModel model)
{ {
@ -63,10 +65,18 @@ namespace Avalonia.Controls.Utils
_updatingModel = true; _updatingModel = true;
_items = items; _items = items;
using (Model.Update()) if (Model.Source is object)
{ {
Model.ClearSelection(); using (Model.Update())
Add(items); {
Model.ClearSelection();
Add(items);
}
}
else if (!_initializeOnSourceAssignment)
{
Model.PropertyChanged += SelectionModelPropertyChanged;
_initializeOnSourceAssignment = true;
} }
if (_items is INotifyCollectionChanged incc2) if (_items is INotifyCollectionChanged incc2)
@ -86,9 +96,11 @@ namespace Avalonia.Controls.Utils
if (_items != null) if (_items != null)
{ {
Model.PropertyChanged -= SelectionModelPropertyChanged;
Model.SelectionChanged -= SelectionModelSelectionChanged; Model.SelectionChanged -= SelectionModelSelectionChanged;
Model = model; Model = model;
Model.SelectionChanged += SelectionModelSelectionChanged; Model.SelectionChanged += SelectionModelSelectionChanged;
_initializeOnSourceAssignment = false;
try 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) private void SelectionModelSelectionChanged(object sender, SelectionModelSelectionChangedEventArgs e)
{ {
if (_updatingModel) if (_updatingModel)

18
src/Avalonia.Controls/Window.cs

@ -6,6 +6,7 @@ using System.Reactive.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Avalonia.Controls.Chrome; using Avalonia.Controls.Chrome;
using Avalonia.Controls.Platform; using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
@ -70,8 +71,7 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot public class Window : WindowBase, IStyleable, IFocusScope, ILayoutRoot
{ {
private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>(); private readonly List<(Window child, bool isDialog)> _children = new List<(Window, bool)>();
private TitleBar _managedTitleBar;
private bool _isExtendedIntoWindowDecorations; private bool _isExtendedIntoWindowDecorations;
private Thickness _windowDecorationMargin; private Thickness _windowDecorationMargin;
private Thickness _offScreenMargin; private Thickness _offScreenMargin;
@ -552,20 +552,6 @@ namespace Avalonia.Controls
IsExtendedIntoWindowDecorations = isExtended; IsExtendedIntoWindowDecorations = isExtended;
WindowDecorationMargin = PlatformImpl.ExtendedMargins; WindowDecorationMargin = PlatformImpl.ExtendedMargins;
OffScreenMargin = PlatformImpl.OffScreenMargin; OffScreenMargin = PlatformImpl.OffScreenMargin;
if (PlatformImpl.NeedsManagedDecorations)
{
if (_managedTitleBar == null)
{
_managedTitleBar = new TitleBar(this);
_managedTitleBar.Attach();
}
}
else
{
_managedTitleBar?.Detach();
_managedTitleBar = null;
}
} }
/// <summary> /// <summary>

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

@ -9,6 +9,7 @@
<Version>0.7.0</Version> <Version>0.7.0</Version>
<NoWarn>CS1591</NoWarn> <NoWarn>CS1591</NoWarn>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<NugetPackageName>Avalonia</NugetPackageName>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<EmbeddedResource Include="Remote\HtmlTransport\webapp\build\**\*.gz" /> <EmbeddedResource Include="Remote\HtmlTransport\webapp\build\**\*.gz" />
@ -26,4 +27,5 @@
<ProjectReference Include="..\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" /> <ProjectReference Include="..\Avalonia.Themes.Default\Avalonia.Themes.Default.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

2
src/Avalonia.DesignerSupport/Remote/HtmlTransport/webapp/webpack.config.js

@ -93,7 +93,7 @@ const config = {
plugins: plugins:
[ [
new Printer(), new Printer(),
new CleanWebpackPlugin([path.resolve(__dirname, 'build')]), new CleanWebpackPlugin([path.resolve(__dirname, 'build')], { verbose: false }),
new MiniCssExtractPlugin({ new MiniCssExtractPlugin({
filename: "[name].[chunkhash]h" + filename: "[name].[chunkhash]h" +
".css", ".css",

2
src/Avalonia.Desktop/Avalonia.Desktop.csproj

@ -11,4 +11,6 @@
<ProjectReference Include="../../packages/Avalonia/Avalonia.csproj" /> <ProjectReference Include="../../packages/Avalonia/Avalonia.csproj" />
<ProjectReference Include="../Avalonia.X11/Avalonia.X11.csproj" /> <ProjectReference Include="../Avalonia.X11/Avalonia.X11.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

1
src/Avalonia.DesktopRuntime/Avalonia.DesktopRuntime.csproj

@ -17,4 +17,5 @@
<Import Project="..\..\build\NetCore.props" /> <Import Project="..\..\build\NetCore.props" />
<Import Project="..\..\build\NetFX.props" /> <Import Project="..\..\build\NetFX.props" />
<Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" /> <Import Project="..\Shared\PlatformSupport\PlatformSupport.projitems" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

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

@ -2,6 +2,7 @@
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
<RootNamespace>Avalonia</RootNamespace> <RootNamespace>Avalonia</RootNamespace>
<PackageId>Avalonia.Diagnostics</PackageId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Update="**\*.xaml.cs"> <Compile Update="**\*.xaml.cs">
@ -28,4 +29,5 @@
<Import Project="..\..\build\EmbedXaml.props" /> <Import Project="..\..\build\EmbedXaml.props" />
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

2
src/Avalonia.Dialogs/Avalonia.Dialogs.csproj

@ -15,4 +15,6 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" /> <ProjectReference Include="..\Markup\Avalonia.Markup.Xaml\Avalonia.Markup.Xaml.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

4
src/Avalonia.Dialogs/ManagedFileChooser.xaml

@ -66,7 +66,7 @@
</StackPanel> </StackPanel>
</DockPanel> </DockPanel>
<DropDown DockPanel.Dock="Bottom" <ComboBox DockPanel.Dock="Bottom"
IsVisible="{Binding ShowFilters}" IsVisible="{Binding ShowFilters}"
Items="{Binding Filters}" Items="{Binding Filters}"
SelectedItem="{Binding SelectedFilter}" SelectedItem="{Binding SelectedFilter}"
@ -76,7 +76,7 @@
<ListBox Margin="0 0 5 5" BorderBrush="Transparent" x:Name="QuickLinks" Items="{Binding QuickLinks}" <ListBox Margin="0 0 5 5" BorderBrush="Transparent" x:Name="QuickLinks" Items="{Binding QuickLinks}"
SelectedIndex="{Binding QuickLinksSelectedIndex}" SelectedIndex="{Binding QuickLinksSelectedIndex}"
DockPanel.Dock="Left" Background="{DynamicResource ThemeControlMidBrush}" Focusable="False"> DockPanel.Dock="Left" Focusable="False">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate>
<StackPanel Spacing="4" Orientation="Horizontal" Background="Transparent"> <StackPanel Spacing="4" Orientation="Horizontal" Background="Transparent">

5
src/Avalonia.FreeDesktop/Avalonia.FreeDesktop.csproj

@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
@ -10,6 +10,5 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Tmds.DBus" Version="0.7.0" /> <PackageReference Include="Tmds.DBus" Version="0.7.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>

3
src/Avalonia.Headless/Avalonia.Headless.csproj

@ -1,8 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework> <TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" /> <ProjectReference Include="..\..\packages\Avalonia\Avalonia.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

1
src/Avalonia.Input/Avalonia.Input.csproj

@ -10,4 +10,5 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

1
src/Avalonia.Interactivity/Avalonia.Interactivity.csproj

@ -11,4 +11,5 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

1
src/Avalonia.Layout/Avalonia.Layout.csproj

@ -8,4 +8,5 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

44
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@ -11,7 +11,7 @@ namespace Avalonia.Native
class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter class AvaloniaNativeMenuExporter : ITopLevelNativeMenuExporter
{ {
private IAvaloniaNativeFactory _factory; private IAvaloniaNativeFactory _factory;
private bool _resetQueued; private bool _resetQueued = true;
private bool _exported = false; private bool _exported = false;
private IAvnWindow _nativeWindow; private IAvnWindow _nativeWindow;
private NativeMenu _menu; private NativeMenu _menu;
@ -39,8 +39,7 @@ namespace Avalonia.Native
public void SetNativeMenu(NativeMenu menu) public void SetNativeMenu(NativeMenu menu)
{ {
_menu = menu == null ? new NativeMenu() : menu; _menu = menu == null ? new NativeMenu() : menu;
DoLayoutReset(true);
DoLayoutReset();
} }
internal void UpdateIfNeeded() internal void UpdateIfNeeded()
@ -74,31 +73,34 @@ namespace Avalonia.Native
return result; return result;
} }
void DoLayoutReset() private void DoLayoutReset(bool forceUpdate = false)
{ {
_resetQueued = false; if (_resetQueued || forceUpdate)
if (_nativeWindow is null)
{ {
var appMenu = NativeMenu.GetMenu(Application.Current); _resetQueued = false;
if (appMenu == null) if (_nativeWindow is null)
{ {
appMenu = CreateDefaultAppMenu(); var appMenu = NativeMenu.GetMenu(Application.Current);
NativeMenu.SetMenu(Application.Current, appMenu);
}
SetMenu(appMenu); if (appMenu == null)
} {
else appMenu = CreateDefaultAppMenu();
{ NativeMenu.SetMenu(Application.Current, appMenu);
if (_menu != null) }
SetMenu(appMenu);
}
else
{ {
SetMenu(_nativeWindow, _menu); if (_menu != null)
{
SetMenu(_nativeWindow, _menu);
}
} }
}
_exported = true; _exported = true;
}
} }
internal void QueueReset() internal void QueueReset()
@ -106,7 +108,7 @@ namespace Avalonia.Native
if (_resetQueued) if (_resetQueued)
return; return;
_resetQueued = true; _resetQueued = true;
Dispatcher.UIThread.Post(DoLayoutReset, DispatcherPriority.Background); Dispatcher.UIThread.Post(() => DoLayoutReset(), DispatcherPriority.Background);
} }
private void SetMenu(NativeMenu menu) private void SetMenu(NativeMenu menu)

5
src/Avalonia.Native/OsxUnicodeKeys.cs

@ -140,6 +140,11 @@ namespace Avalonia.Native.Interop
} }
else else
{ {
if (key >= Key.D0 && key <= Key.D9)
{
return key.ToString().Replace("D", "");
}
return key.ToString().ToLower(); return key.ToString().ToLower();
} }
} }

10
src/Avalonia.Native/WindowImplBase.cs

@ -300,7 +300,15 @@ namespace Avalonia.Native
public IRenderer CreateRenderer(IRenderRoot root) public IRenderer CreateRenderer(IRenderRoot root)
{ {
if (_deferredRendering) if (_deferredRendering)
return new DeferredRenderer(root, AvaloniaLocator.Current.GetService<IRenderLoop>()); {
var loop = AvaloniaLocator.Current.GetService<IRenderLoop>();
var customRendererFactory = AvaloniaLocator.Current.GetService<IRendererFactory>();
if (customRendererFactory != null)
return customRendererFactory.Create(root, loop);
return new DeferredRenderer(root, loop);
}
return new ImmediateRenderer(root); return new ImmediateRenderer(root);
} }

3
src/Avalonia.OpenGL/Avalonia.OpenGL.csproj

@ -9,6 +9,5 @@
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" /> <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
<ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" /> <ProjectReference Include="..\Avalonia.Controls\Avalonia.Controls.csproj" />
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

1
src/Avalonia.ReactiveUI/Avalonia.ReactiveUI.csproj

@ -8,4 +8,5 @@
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ReactiveUI.props" /> <Import Project="..\..\build\ReactiveUI.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

2
src/Avalonia.Remote.Protocol/Avalonia.Remote.Protocol.csproj

@ -4,8 +4,10 @@
<DefineConstants>AVALONIA_REMOTE_PROTOCOL;$(DefineConstants)</DefineConstants> <DefineConstants>AVALONIA_REMOTE_PROTOCOL;$(DefineConstants)</DefineConstants>
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<PackageId>Avalonia.Remote.Protocol</PackageId>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\Avalonia.Input\Key.cs" /> <Compile Include="..\Avalonia.Input\Key.cs" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

1
src/Avalonia.Styling/Avalonia.Styling.csproj

@ -8,4 +8,5 @@
<ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" /> <ProjectReference Include="..\Avalonia.Animation\Avalonia.Animation.csproj" />
<ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" /> <ProjectReference Include="..\Avalonia.Base\Avalonia.Base.csproj" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

5
src/Avalonia.Themes.Default/Accents/BaseDark.xaml

@ -58,6 +58,11 @@
<SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/> <SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/> <SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/>
<SolidColorBrush x:Key="DatePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="TimePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="ThemeControlTransparentBrush" Color="Transparent" />
<Thickness x:Key="ThemeBorderThickness">1,1,1,1</Thickness> <Thickness x:Key="ThemeBorderThickness">1,1,1,1</Thickness>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double> <sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>

5
src/Avalonia.Themes.Default/Accents/BaseLight.xaml

@ -61,6 +61,11 @@
<SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/> <SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/> <SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/>
<SolidColorBrush x:Key="DatePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="TimePickerFlyoutPresenterHighlightFill" Color="{DynamicResource ThemeAccentColor}" Opacity="0.4" />
<SolidColorBrush x:Key="ThemeControlTransparentBrush" Color="Transparent" />
<Thickness x:Key="ThemeBorderThickness">1</Thickness> <Thickness x:Key="ThemeBorderThickness">1</Thickness>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double> <sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>

1
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -19,4 +19,5 @@
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

12
src/Avalonia.Themes.Default/ComboBox.xaml

@ -1,4 +1,5 @@
<Styles xmlns="https://github.com/avaloniaui"> <Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith> <Design.PreviewWith>
<Border Padding="20"> <Border Padding="20">
<StackPanel Spacing="10"> <StackPanel Spacing="10">
@ -24,6 +25,7 @@
<Setter Property="VerticalContentAlignment" Value="Center" /> <Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="4" /> <Setter Property="Padding" Value="4" />
<Setter Property="MinHeight" Value="20" /> <Setter Property="MinHeight" Value="20" />
<Setter Property="PlaceholderForeground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Border Name="border" <Border Name="border"
@ -31,6 +33,14 @@
BorderBrush="{TemplateBinding BorderBrush}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"> BorderThickness="{TemplateBinding BorderThickness}">
<Grid ColumnDefinitions="*,Auto"> <Grid ColumnDefinitions="*,Auto">
<TextBlock Name="PlaceholderTextBlock"
Grid.Column="0"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}"
Text="{TemplateBinding PlaceholderText}"
Foreground="{TemplateBinding PlaceholderForeground}"
IsVisible="{TemplateBinding SelectionBoxItem, Converter={x:Static ObjectConverters.IsNull}}" />
<ContentControl Content="{TemplateBinding SelectionBoxItem}" <ContentControl Content="{TemplateBinding SelectionBoxItem}"
ContentTemplate="{TemplateBinding ItemTemplate}" ContentTemplate="{TemplateBinding ItemTemplate}"
Margin="{TemplateBinding Padding}" Margin="{TemplateBinding Padding}"

334
src/Avalonia.Themes.Default/DatePicker.xaml

@ -0,0 +1,334 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Styles.Resources>
<Thickness x:Key="DatePickerTopHeaderMargin">0,0,0,4</Thickness>
<x:Double x:Key="DatePickerFlyoutPresenterHighlightHeight">40</x:Double>
<x:Double x:Key="DatePickerFlyoutPresenterItemHeight">40</x:Double>
<x:Double x:Key="DatePickerFlyoutPresenterAcceptDismissHostGridHeight">41</x:Double>
<x:Double x:Key="DatePickerThemeMinWidth">296</x:Double>
<x:Double x:Key="DatePickerThemeMaxWidth">456</x:Double>
<Thickness x:Key="DatePickerFlyoutPresenterItemPadding">0,3,0,6</Thickness>
<Thickness x:Key="DatePickerFlyoutPresenterMonthPadding">9,3,0,6</Thickness>
<Thickness x:Key="DatePickerHostPadding">0,3,0,6</Thickness>
<Thickness x:Key="DatePickerHostMonthPadding">9,3,0,6</Thickness>
<x:Double x:Key="DatePickerSpacerThemeWidth">1</x:Double>
</Styles.Resources>
<!-- Styles for the items displayed in the selectors -->
<Style Selector="ListBoxItem.DateTimePickerItem">
<Setter Property="Padding" Value="{DynamicResource DatePickerFlyoutPresenterItemPadding}"/>
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style Selector="ListBoxItem.DateTimePickerItem:selected">
<Setter Property="IsHitTestVisible" Value="False"/>
</Style>
<Style Selector="ListBoxItem.DateTimePickerItem:selected /template/ Rectangle#PressedBackground">
<Setter Property="Fill" Value="Transparent"/>
</Style>
<Style Selector="ListBoxItem.DateTimePickerItem:selected /template/ ContentPresenter">
<Setter Property="Background" Value="Transparent" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="ListBoxItem.DateTimePickerItem.MonthItem">
<Setter Property="Padding" Value="{DynamicResource DatePickerFlyoutPresenterMonthPadding}"/>
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
</Style>
<!-- This is used for both the accept/dismiss & repeatbuttons in the presenter-->
<Style Selector=":is(Button).DateTimeFlyoutButtonStyle">
<Setter Property="Background" Value="{DynamicResource ThemeControlTransparentBrush}" />
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<ControlTemplate>
<Border Background="{TemplateBinding Background}">
<ContentPresenter x:Name="ContentPresenter"
Background="{TemplateBinding Background}"
BorderBrush="{DynamicResource ThemeControlTransparentBrush}"
BorderThickness="{DynamicResource DateTimeFlyoutButtonBorderThickness}"
Content="{TemplateBinding Content}"
TextBlock.Foreground="{DynamicResource ThemeForegroundBrush}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector=":is(Button).DateTimeFlyoutButtonStyle:pointerover /template/ ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightLowBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlTransparentBrush}"/>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector=":is(Button).DateTimeFlyoutButtonStyle:pressed /template/ ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightMidBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlTransparentBrush}"/>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="RepeatButton.UpButton">
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="Height" Value="22" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightLowBrush}" />
<Setter Property="Content">
<Template>
<Viewbox Height="10" Width="10" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Stroke="{Binding $parent[RepeatButton].Foreground}" StrokeThickness="1" Data="M 0,9 L 9,0 L 18,9"/>
</Viewbox>
</Template>
</Setter>
</Style>
<Style Selector="RepeatButton.DownButton">
<Setter Property="VerticalAlignment" Value="Bottom"/>
<Setter Property="Height" Value="22" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Focusable" Value="False" />
<Setter Property="Background" Value="{DynamicResource ThemeControlHighlightLowBrush}" />
<Setter Property="Content">
<Template>
<Viewbox Height="10" Width="10" HorizontalAlignment="Center" VerticalAlignment="Center">
<Path Stroke="{Binding $parent[RepeatButton].Foreground}" StrokeThickness="1" Data="M 0,0 L 9,9 L 18,0"/>
</Viewbox>
</Template>
</Setter>
</Style>
<Style Selector="DatePicker">
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}" />
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlHighlightMidBrush}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<ControlTemplate>
<Grid Name="LayoutRoot" Margin="{TemplateBinding Padding}" RowDefinitions="Auto,*">
<ContentPresenter Name="HeaderContentPresenter" Grid.Row="0"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Margin="{DynamicResource DatePickerTopHeaderMargin}"
MaxWidth="{DynamicResource DatePickerThemeMaxWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"/>
<Button Name="FlyoutButton" Grid.Row="1"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
IsEnabled="{TemplateBinding IsEnabled}"
MinWidth="{DynamicResource DatePickerThemeMinWidth}"
MaxWidth="{DynamicResource DatePickerThemeMaxWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"
TemplatedControl.IsTemplateFocusTarget="True">
<Button.Template>
<ControlTemplate>
<ContentPresenter Name="ContentPresenter"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
TextBlock.Foreground="{TemplateBinding Foreground}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch"/>
</ControlTemplate>
</Button.Template>
<Grid Name="ButtonContentGrid" ColumnDefinitions="78*,Auto,132*,Auto,78*">
<TextBlock Name="DayText" Text="day" HorizontalAlignment="Center"
Padding="{DynamicResource DatePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
<TextBlock Name="MonthText" Text="month" TextAlignment="Left"
Padding="{DynamicResource DatePickerHostMonthPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
<TextBlock Name="YearText" Text="year" HorizontalAlignment="Center"
Padding="{DynamicResource DatePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
<Rectangle x:Name="FirstSpacer"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="1"
Grid.Column="1" />
<Rectangle x:Name="SecondSpacer"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="1"
Grid.Column="3" />
</Grid>
</Button>
<Popup Name="Popup" WindowManagerAddShadowHint="False"
StaysOpen="False" PlacementTarget="{TemplateBinding}"
PlacementMode="Bottom">
<DatePickerPresenter Name="PickerPresenter" />
</Popup>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="DatePicker /template/ ContentPresenter#HeaderContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="DatePicker:disabled /template/ Rectangle">
<!--<Setter Property="Fill" Value="{DynamicResource DatePickerSpacerFillDisabled}"/>-->
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}" />
</Style>
<Style Selector="DatePicker /template/ Button#FlyoutButton:pointerover /template/ ContentPresenter">
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlHighBrush}"/>
<!--<Setter Property="Background" Value="{DynamicResource DatePickerButtonBackgroundPointerOver}"/>-->
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="DatePicker /template/ Button#FlyoutButton:pressed /template/ ContentPresenter">
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlLowBrush}"/>
<Setter Property="Background">
<SolidColorBrush Color="{DynamicResource ThemeControlMidHighColor}" Opacity="0.6" />
</Setter>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="DatePicker /template/ Button#FlyoutButton:disabled /template/ ContentPresenter">
<!--<Setter Property="BorderBrush" Value="{DynamicResource DatePickerButtonBorderBrushDisabled}"/>
<Setter Property="Background" Value="{DynamicResource DatePickerButtonBackgroundDisabled}"/>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource DatePickerButtonForegroundDisabled}"/>-->
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}" />
</Style>
<!-- Changes foreground for watermark text when SelectedDate is null-->
<Style Selector="DatePicker:hasnodate /template/ Button#FlyoutButton TextBlock">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}"/>
</Style>
<!--WinUI: DatePickerFlyoutPresenter-->
<Style Selector="DatePickerPresenter">
<Setter Property="Width" Value="296" />
<Setter Property="MinWidth" Value="296" />
<Setter Property="MaxHeight" Value="398" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}" />
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource DateTimeFlyoutBorderThickness}" />
<Setter Property="Template">
<ControlTemplate>
<Border Name="Background" Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{DynamicResource DateTimeFlyoutBorderPadding}"
MaxHeight="398">
<Grid Name="ContentRoot" RowDefinitions="*,Auto">
<Grid Name="PickerContainer">
<!--Column Definitions set in code, ignore here-->
<Panel Name="MonthHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="MonthSelector"
PanelType="Month"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="MonthUpButton"
Classes="DateTimeFlyoutButtonStyle UpButton"/>
<RepeatButton Name="MonthDownButton"
Classes="DateTimeFlyoutButtonStyle DownButton"/>
</Panel>
<Panel Name="DayHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="DaySelector"
PanelType="Day"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
ShouldLoop="True" />
</ScrollViewer>
<RepeatButton Name="DayUpButton"
Classes="DateTimeFlyoutButtonStyle UpButton"/>
<RepeatButton Name="DayDownButton"
Classes="DateTimeFlyoutButtonStyle DownButton"/>
</Panel>
<Panel Name="YearHost">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="YearSelector"
PanelType="Year"
ItemHeight="{DynamicResource DatePickerFlyoutPresenterItemHeight}"
ShouldLoop="False" />
</ScrollViewer>
<RepeatButton Name="YearUpButton"
Classes="DateTimeFlyoutButtonStyle UpButton"/>
<RepeatButton Name="YearDownButton"
Classes="DateTimeFlyoutButtonStyle DownButton"/>
</Panel>
<Rectangle Name="HighlightRect" IsHitTestVisible="False" ZIndex="-1"
Fill="{DynamicResource DatePickerFlyoutPresenterHighlightFill}"
Grid.Column="0" Grid.ColumnSpan="5" VerticalAlignment="Center"
Height="{DynamicResource DatePickerFlyoutPresenterHighlightHeight}" />
<Rectangle Name="FirstSpacer"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="{DynamicResource DatePickerSpacerThemeWidth}"
Grid.Column="1" />
<Rectangle Name="SecondSpacer"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="{DynamicResource DatePickerSpacerThemeWidth}"
Grid.Column="3" />
</Grid>
<Grid Grid.Row="1" Height="{DynamicResource DatePickerFlyoutPresenterAcceptDismissHostGridHeight}"
Name="AcceptDismissGrid" ColumnDefinitions="*,*">
<Rectangle Height="{DynamicResource DatePickerSpacerThemeWidth}" VerticalAlignment="Top"
Fill="{DynamicResource ThemeControlMidHighBrush}"
Grid.ColumnSpan="2"/>
<Button Name="AcceptButton" Grid.Column="0" Classes="DateTimeFlyoutButtonStyle"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Path Stroke="{Binding $parent[Button].Foreground}" StrokeLineCap="Round"
StrokeThickness="0.75" Data="M0.5,8.5 5,13.5 15.5,3" />
</Button>
<Button Name="DismissButton" Grid.Column="1" Classes="DateTimeFlyoutButtonStyle"
FontSize="16" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Path Stroke="{Binding $parent[Button].Foreground}" StrokeLineCap="Round"
StrokeThickness="0.75" Data="M2,2 14,14 M2,14 14 2" />
</Button>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="DatePickerPresenter /template/ Panel RepeatButton">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="DatePickerPresenter /template/ Panel:pointerover RepeatButton">
<Setter Property="IsVisible" Value="True" />
</Style>
</Styles>

4
src/Avalonia.Themes.Default/DefaultTheme.xaml

@ -37,6 +37,7 @@
<StyleInclude Source="resm:Avalonia.Themes.Default.TextBox.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.TextBox.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ToggleButton.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.ToggleButton.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Expander.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.Expander.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.TitleBar.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.TreeView.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.TreeView.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.TreeViewItem.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.TreeViewItem.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.UserControl.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.UserControl.xaml?assembly=Avalonia.Themes.Default"/>
@ -54,4 +55,7 @@
<StyleInclude Source="resm:Avalonia.Themes.Default.NotificationCard.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.NotificationCard.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.NativeMenuBar.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.NativeMenuBar.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.ToggleSwitch.xaml?assembly=Avalonia.Themes.Default"/> <StyleInclude Source="resm:Avalonia.Themes.Default.ToggleSwitch.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.SplitView.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.DatePicker.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.TimePicker.xaml?assembly=Avalonia.Themes.Default"/>
</Styles> </Styles>

46
src/Avalonia.Themes.Default/ProgressBar.xaml

@ -13,19 +13,14 @@
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Grid> <Grid>
<Border Background="{TemplateBinding Background}" <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
BorderBrush="{TemplateBinding BorderBrush}" <Panel>
BorderThickness="{TemplateBinding BorderThickness}"> <Border Name="PART_Indicator" Background="{TemplateBinding Foreground}" IsVisible="{Binding !IsIndeterminate, RelativeSource={RelativeSource TemplatedParent}}"/>
<Border Name="PART_Indicator" Background="{TemplateBinding Foreground}"/> <Border Name="PART_IndeterminateIndicator" Background="{TemplateBinding Foreground}" IsVisible="{Binding IsIndeterminate, RelativeSource={RelativeSource TemplatedParent}}"/>
</Panel>
</Border> </Border>
<LayoutTransformControl <LayoutTransformControl HorizontalAlignment="Center" VerticalAlignment="Center" IsVisible="{Binding ShowProgressText, RelativeSource={RelativeSource TemplatedParent}}" Name="PART_LayoutTransformControl">
HorizontalAlignment="Center" <TextBlock Foreground="{DynamicResource ThemeForegroundBrush}" Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, StringFormat={}{0:0}%}" />
VerticalAlignment="Center"
IsVisible="{Binding ShowProgressText, RelativeSource={RelativeSource TemplatedParent}}"
Name="PART_LayoutTransformControl">
<TextBlock
Foreground="{DynamicResource ThemeForegroundBrush}"
Text="{Binding Value, RelativeSource={RelativeSource TemplatedParent}, StringFormat={}{0:0}%}" />
</LayoutTransformControl> </LayoutTransformControl>
</Grid> </Grid>
</ControlTemplate> </ControlTemplate>
@ -54,36 +49,31 @@
</Setter.Value> </Setter.Value>
</Setter> </Setter>
</Style> </Style>
<Style Selector="ProgressBar:horizontal:indeterminate /template/ Border#PART_Indicator">
<Style Selector="ProgressBar:horizontal:indeterminate /template/ Border#PART_IndeterminateIndicator">
<Style.Animations> <Style.Animations>
<Animation Duration="0:0:3" <Animation Duration="0:0:3" IterationCount="Infinite" Easing="LinearEasing">
IterationCount="Infinite"
Easing="LinearEasing">
<KeyFrame Cue="0%"> <KeyFrame Cue="0%">
<Setter Property="TranslateTransform.X" <Setter Property="TranslateTransform.X" Value="{Binding IndeterminateStartingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
Value="{Binding IndeterminateStartingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame> </KeyFrame>
<KeyFrame Cue="100%"> <KeyFrame Cue="100%">
<Setter Property="TranslateTransform.X" <Setter Property="TranslateTransform.X" Value="{Binding IndeterminateEndingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
Value="{Binding IndeterminateEndingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame> </KeyFrame>
</Animation> </Animation>
</Style.Animations> </Style.Animations>
<Setter Property="Width" Value="{Binding TemplateProperties.ContainerWidth, RelativeSource={RelativeSource TemplatedParent}}" />
</Style> </Style>
<Style Selector="ProgressBar:vertical:indeterminate /template/ Border#PART_Indicator"> <Style Selector="ProgressBar:vertical:indeterminate /template/ Border#PART_IndeterminateIndicator">
<Style.Animations> <Style.Animations>
<Animation Duration="0:0:3" <Animation Duration="0:0:3" IterationCount="Infinite" Easing="LinearEasing">
IterationCount="Infinite"
Easing="LinearEasing">
<KeyFrame Cue="0%"> <KeyFrame Cue="0%">
<Setter Property="TranslateTransform.Y" <Setter Property="TranslateTransform.Y" Value="{Binding IndeterminateStartingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
Value="{Binding TemplateProperties.IndeterminateStartingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame> </KeyFrame>
<KeyFrame Cue="100%"> <KeyFrame Cue="100%">
<Setter Property="TranslateTransform.Y" <Setter Property="TranslateTransform.Y" Value="{Binding IndeterminateEndingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
Value="{Binding TemplateProperties.IndeterminateEndingOffset, RelativeSource={RelativeSource TemplatedParent}}" />
</KeyFrame> </KeyFrame>
</Animation> </Animation>
</Style.Animations> </Style.Animations>
<Setter Property="Height" Value="{Binding TemplateProperties.ContainerWidth, RelativeSource={RelativeSource TemplatedParent}}" />
</Style> </Style>
</Styles> </Styles>

219
src/Avalonia.Themes.Default/SplitView.xaml

@ -0,0 +1,219 @@
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Styles.Resources>
<x:Double x:Key="SplitViewOpenPaneThemeLength">320</x:Double>
<x:Double x:Key="SplitViewCompactPaneThemeLength">48</x:Double>
<!-- Not used here (directly) since they're strings, but preserving for reference
<x:String x:Key="SplitViewPaneAnimationOpenDuration">00:00:00.2</x:String>
<x:String x:Key="SplitViewPaneAnimationOpenPreDuration">00:00:00.19999</x:String>
<x:String x:Key="SplitViewPaneAnimationCloseDuration">00:00:00.1</x:String>-->
</Styles.Resources>
<Style Selector="SplitView">
<Setter Property="OpenPaneLength" Value="{DynamicResource SplitViewOpenPaneThemeLength}" />
<Setter Property="CompactPaneLength" Value="{DynamicResource SplitViewCompactPaneThemeLength}" />
<Setter Property="PaneBackground" Value="{DynamicResource ThemeControlHighlightLowBrush}" />
</Style>
<!-- Left -->
<Style Selector="SplitView:left">
<Setter Property="Template">
<ControlTemplate>
<Grid Name="Container" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<!-- why is this throwing a binding error? -->
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.PaneColumnGridLength}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Panel Name="PART_PaneRoot" Background="{TemplateBinding PaneBackground}"
ClipToBounds="True"
HorizontalAlignment="Left"
ZIndex="100">
<Border Child="{TemplateBinding Pane}"/>
<Rectangle Name="HCPaneBorder" Fill="{DynamicResource SystemControlForegroundTransparentBrush}" Width="1" HorizontalAlignment="Right" />
</Panel>
<Panel Name="ContentRoot">
<Border Child="{TemplateBinding Content}" />
<Rectangle Name="LightDismissLayer"/>
</Panel>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<!-- Overlay -->
<Style Selector="SplitView:overlay:left /template/ Panel#PART_PaneRoot">
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
<!-- ColumnSpan should be 2 -->
<Setter Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="Grid.Column" Value="0"/>
</Style>
<Style Selector="SplitView:overlay:left /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Grid.ColumnSpan" Value="2"/>
</Style>
<!-- CompactInline -->
<Style Selector="SplitView:compactinline:left /template/ Panel#PART_PaneRoot">
<Setter Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:compactinline:left /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Grid.ColumnSpan" Value="1"/>
</Style>
<!-- CompactOverlay -->
<Style Selector="SplitView:compactoverlay:left /template/ Panel#PART_PaneRoot">
<!-- ColumnSpan should be 2 -->
<Setter Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:compactoverlay:left /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Grid.ColumnSpan" Value="1"/>
</Style>
<!-- Inline -->
<Style Selector="SplitView:inline:left /template/ Panel#PART_PaneRoot">
<Setter Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:inline:left /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Grid.ColumnSpan" Value="1"/>
</Style>
<!-- Right -->
<Style Selector="SplitView:right">
<Setter Property="Template">
<ControlTemplate>
<Grid Name="Container" Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.PaneColumnGridLength}"/>
</Grid.ColumnDefinitions>
<Panel Name="PART_PaneRoot" Background="{TemplateBinding PaneBackground}"
ClipToBounds="True"
HorizontalAlignment="Right"
ZIndex="100">
<Border Child="{TemplateBinding Pane}"/>
<Rectangle Name="HCPaneBorder"
Fill="{DynamicResource SystemControlForegroundTransparentBrush}"
Width="1" HorizontalAlignment="Left" />
</Panel>
<Panel Name="ContentRoot">
<Border Child="{TemplateBinding Content}" />
<Rectangle Name="LightDismissLayer"/>
</Panel>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<!-- Overlay -->
<Style Selector="SplitView:overlay:right /template/ Panel#PART_PaneRoot">
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
<Setter Property="Grid.ColumnSpan" Value="2"/>
<Setter Property="Grid.Column" Value="1"/>
</Style>
<Style Selector="SplitView:overlay:right /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Grid.ColumnSpan" Value="2"/>
</Style>
<!-- CompactInline -->
<Style Selector="SplitView:compactinline:right /template/ Panel#PART_PaneRoot">
<Setter Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:compactinline:right /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Grid.ColumnSpan" Value="1"/>
</Style>
<!-- CompactOverlay -->
<Style Selector="SplitView:compactoverlay:right /template/ Panel#PART_PaneRoot">
<Setter Property="Grid.ColumnSpan" Value="2"/>
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:compactoverlay:right /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Grid.ColumnSpan" Value="1"/>
</Style>
<!-- Inline -->
<Style Selector="SplitView:inline:right /template/ Panel#PART_PaneRoot">
<Setter Property="Grid.ColumnSpan" Value="1"/>
<Setter Property="Grid.Column" Value="1"/>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:inline:right /template/ Panel#ContentRoot">
<Setter Property="Grid.Column" Value="0"/>
<Setter Property="Grid.ColumnSpan" Value="1"/>
</Style>
<!-- Open/Close Pane animation -->
<Style Selector="SplitView:open /template/ Panel#PART_PaneRoot">
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Width" Duration="00:00:00.2" Easing="0.1,0.9,0.2,1.0" />
</Transitions>
</Setter>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=OpenPaneLength}" />
</Style>
<Style Selector="SplitView:open /template/ Rectangle#LightDismissLayer">
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Opacity" Duration="00:00:00.2" Easing="0.1,0.9,0.2,1.0" />
</Transitions>
</Setter>
<Setter Property="Opacity" Value="1.0"/>
</Style>
<Style Selector="SplitView:closed /template/ Panel#PART_PaneRoot">
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Width" Duration="00:00:00.1" Easing="0.1,0.9,0.2,1.0" />
</Transitions>
</Setter>
<Setter Property="Width" Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.ClosedPaneWidth}" />
</Style>
<Style Selector="SplitView:closed /template/ Rectangle#LightDismissLayer">
<Setter Property="Transitions">
<Transitions>
<DoubleTransition Property="Opacity" Duration="00:00:00.2" Easing="0.1,0.9,0.2,1.0" />
</Transitions>
</Setter>
<Setter Property="Opacity" Value="0.0"/>
</Style>
<Style Selector="SplitView /template/ Rectangle#LightDismissLayer">
<Setter Property="IsVisible" Value="False"/>
<Setter Property="Fill" Value="Transparent" />
</Style>
<Style Selector="SplitView:lightdismiss /template/ Rectangle#LightDismissLayer">
<Setter Property="Fill" Value="{DynamicResource SplitViewLightDismissOverlayBackground}" />
</Style>
<Style Selector="SplitView:overlay:open /template/ Rectangle#LightDismissLayer">
<Setter Property="IsVisible" Value="True"/>
</Style>
<Style Selector="SplitView:compactoverlay:open /template/ Rectangle#LightDismissLayer">
<Setter Property="IsVisible" Value="True"/>
</Style>
</Styles>

2
src/Avalonia.Themes.Default/TabItem.xaml

@ -2,7 +2,7 @@
<Style Selector="TabItem"> <Style Selector="TabItem">
<Setter Property="Background" Value="Transparent"/> <Setter Property="Background" Value="Transparent"/>
<Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/> <Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/>
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLightBrush}"/> <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/> <Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="Padding" Value="8"/> <Setter Property="Padding" Value="8"/>
<Setter Property="Template"> <Setter Property="Template">

283
src/Avalonia.Themes.Default/TimePicker.xaml

@ -0,0 +1,283 @@
<!--
// (c) Copyright Microsoft Corporation.
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.
-->
<Styles xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Styles.Resources>
<x:Double x:Key="TimePickerFlyoutPresenterItemHeight">40</x:Double>
<x:Double x:Key="TimePickerSpacerThemeWidth">1</x:Double>
<Thickness x:Key="TimePickerBorderThemeThickness">1</Thickness>
<Thickness x:Key="TimePickerTopHeaderMargin">0,0,0,4</Thickness>
<x:Double x:Key="TimePickerFlyoutPresenterHighlightHeight">40</x:Double>
<x:Double x:Key="TimePickerFlyoutPresenterAcceptDismissHostGridHeight">41</x:Double>
<x:Double x:Key="TimePickerThemeMinWidth">242</x:Double>
<x:Double x:Key="TimePickerThemeMaxWidth">456</x:Double>
<Thickness x:Key="TimePickerFlyoutPresenterItemPadding">0,3,0,6</Thickness>
<Thickness x:Key="TimePickerHostPadding">0,3,0,6</Thickness>
</Styles.Resources>
<Style Selector="ListBoxItem.DateTimePickerItem.HourItem">
<Setter Property="Padding" Value="{DynamicResource TimePickerFlyoutPresenterItemPadding}" />
</Style>
<Style Selector="ListBoxItem.DateTimePickerItem.MinuteItem">
<Setter Property="Padding" Value="{DynamicResource TimePickerFlyoutPresenterItemPadding}" />
</Style>
<Style Selector="ListBoxItem.DateTimePickerItem.TimePeriodItem">
<Setter Property="Padding" Value="{DynamicResource TimePickerFlyoutPresenterItemPadding}" />
</Style>
<Style Selector="TimePicker">
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}" />
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}" />
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlHighlightMidBrush}"/>
<Setter Property="BorderThickness" Value="{DynamicResource TimePickerBorderThemeThickness}"/>
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Template">
<ControlTemplate>
<Grid Name="LayoutRoot" Margin="{TemplateBinding Padding}" RowDefinitions="Auto,*">
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Margin="{DynamicResource TimePickerTopHeaderMargin}"
MaxWidth="{DynamicResource TimePickerThemeMaxWidth}"
TextBlock.Foreground="{DynamicResource TimePickerHeaderForeground}"
HorizontalAlignment="Stretch"
VerticalAlignment="Top" />
<Button x:Name="FlyoutButton"
Grid.Row="1"
Foreground="{TemplateBinding Foreground}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
IsEnabled="{TemplateBinding IsEnabled}"
MinWidth="{DynamicResource TimePickerThemeMinWidth}"
MaxWidth="{DynamicResource TimePickerThemeMaxWidth}"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
VerticalAlignment="Top"
VerticalContentAlignment="Stretch">
<Button.Template>
<ControlTemplate>
<ContentPresenter Name="ContentPresenter"
BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
TextBlock.Foreground="{TemplateBinding Foreground}"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch" />
</ControlTemplate>
</Button.Template>
<Grid Name="FlyoutButtonContentGrid">
<!--Ignore col defs here, set in code-->
<Border x:Name="FirstPickerHost" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="HourTextBlock"
HorizontalAlignment="Center"
Padding="{DynamicResource TimePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}" />
</Border>
<Rectangle Name="FirstColumnDivider"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="1" />
<Border x:Name="SecondPickerHost" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="MinuteTextBlock"
HorizontalAlignment="Center"
Padding="{DynamicResource TimePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}"/>
</Border>
<Rectangle Name="SecondColumnDivider"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="3" />
<Border x:Name="ThirdPickerHost" Grid.Column="4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<TextBlock x:Name="PeriodTextBlock"
HorizontalAlignment="Center"
Padding="{DynamicResource TimePickerHostPadding}"
FontFamily="{TemplateBinding FontFamily}"
FontWeight="{TemplateBinding FontWeight}"
FontSize="{TemplateBinding FontSize}" />
</Border>
</Grid>
</Button>
<Popup Name="Popup" WindowManagerAddShadowHint="False"
StaysOpen="False" PlacementTarget="{TemplateBinding}"
PlacementMode="Bottom">
<TimePickerPresenter Name="PickerPresenter" />
</Popup>
</Grid>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TimePicker:disabled /template/ ContentPresenter#HeaderContentPresenter">
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="TimePicker:disabled /template/ Rectangle">
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}"/>
</Style>
<Style Selector="TimePicker /template/ Button#FlyoutButton:pointerover /template/ ContentPresenter">
<!--<Setter Property="Background" Value="{DynamicResource TimePickerButtonBackgroundPointerOver}"/>-->
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlHighBrush}"/>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="TimePicker /template/ Button:pressed /template/ ContentPresenter">
<Setter Property="Background">
<SolidColorBrush Color="{DynamicResource ThemeControlMidHighColor}" Opacity="0.6" />
</Setter>
<Setter Property="BorderBrush" Value="{DynamicResource ThemeControlLowBrush}"/>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
</Style>
<Style Selector="TimePicker /template/ Button:disabled /template/ ContentPresenter">
<!--<Setter Property="Background" Value="{DynamicResource TimePickerButtonBackgroundDisabled}"/>
<Setter Property="BorderBrush" Value="{DynamicResource TimePickerButtonBorderBrushDisabled}"/>
<Setter Property="TextBlock.Foreground" Value="{DynamicResource TimePickerButtonForegroundDisabled}"/>-->
<Setter Property="Opacity" Value="{DynamicResource ThemeDisabledOpacity}" />
</Style>
<Style Selector="TimePicker:hasnotime /template/ Button#FlyoutButton TextBlock">
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundLowBrush}"/>
</Style>
<Style Selector="TimePickerPresenter">
<Setter Property="Width" Value="242" />
<Setter Property="MinWidth" Value="242" />
<Setter Property="MaxHeight" Value="398" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{DynamicResource ThemeBorderMidBrush}" />
<Setter Property="BorderThickness" Value="{DynamicResource DateTimeFlyoutBorderThickness}" />
<Setter Property="Template">
<ControlTemplate>
<Border Name="Background"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{DynamicResource DateTimeFlyoutBorderPadding}"
MaxHeight="398">
<Grid Name="ContentPanel" RowDefinitions="*,Auto">
<Grid Name="PickerContainer">
<!--Ignore col defs here, set in code-->
<Panel Name="HourHost" Grid.Column="0">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="HourSelector"
PanelType="Hour"
ShouldLoop="True"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"/>
</ScrollViewer>
<RepeatButton Name="HourUpButton"
Classes="DateTimeFlyoutButtonStyle UpButton"/>
<RepeatButton Name="HourDownButton"
Classes="DateTimeFlyoutButtonStyle DownButton"/>
</Panel>
<Panel Name="MinuteHost" Grid.Column="2">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="MinuteSelector"
PanelType="Minute"
ShouldLoop="True"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"/>
</ScrollViewer>
<RepeatButton Name="MinuteUpButton"
Classes="DateTimeFlyoutButtonStyle UpButton"/>
<RepeatButton Name="MinuteDownButton"
Classes="DateTimeFlyoutButtonStyle DownButton"/>
</Panel>
<Panel Name="PeriodHost" Grid.Column="4">
<ScrollViewer HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Hidden">
<DateTimePickerPanel Name="PeriodSelector"
PanelType="TimePeriod"
ShouldLoop="False"
ItemHeight="{DynamicResource TimePickerFlyoutPresenterItemHeight}"/>
</ScrollViewer>
<RepeatButton Name="PeriodUpButton"
Classes="DateTimeFlyoutButtonStyle UpButton"/>
<RepeatButton Name="PeriodDownButton"
Classes="DateTimeFlyoutButtonStyle DownButton"/>
</Panel>
<Rectangle x:Name="HighlightRect" ZIndex="-1"
Fill="{DynamicResource TimePickerFlyoutPresenterHighlightFill}"
Grid.Column="0"
Grid.ColumnSpan="5"
VerticalAlignment="Center"
Height="{DynamicResource TimePickerFlyoutPresenterHighlightHeight}" />
<Rectangle Name="FirstSpacer"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="1" />
<Rectangle Name="SecondSpacer"
Fill="{DynamicResource ThemeControlMidHighBrush}"
HorizontalAlignment="Center"
Width="{DynamicResource TimePickerSpacerThemeWidth}"
Grid.Column="3" />
</Grid>
<Grid Grid.Row="1" Height="{DynamicResource TimePickerFlyoutPresenterAcceptDismissHostGridHeight}"
Name="AcceptDismissHostGrid" ColumnDefinitions="*,*">
<Rectangle Height="{DynamicResource TimePickerSpacerThemeWidth}"
VerticalAlignment="Top"
Fill="{DynamicResource ThemeControlMidHighBrush}"
Grid.ColumnSpan="2" />
<Button Name="AcceptButton" Grid.Column="0" Classes="DateTimeFlyoutButtonStyle"
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Path Stroke="{Binding $parent[Button].Foreground}" StrokeLineCap="Round"
StrokeThickness="0.75" Data="M0.5,8.5 5,13.5 15.5,3" />
</Button>
<Button Name="DismissButton" Grid.Column="1" Classes="DateTimeFlyoutButtonStyle"
FontSize="16" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Path Stroke="{Binding $parent[Button].Foreground}" StrokeLineCap="Round"
StrokeThickness="0.75" Data="M2,2 14,14 M2,14 14 2" />
</Button>
</Grid>
</Grid>
</Border>
</ControlTemplate>
</Setter>
</Style>
<Style Selector="TimePickerPresenter /template/ Panel RepeatButton">
<Setter Property="IsVisible" Value="False" />
</Style>
<Style Selector="TimePickerPresenter /template/ Panel:pointerover RepeatButton">
<Setter Property="IsVisible" Value="True" />
</Style>
</Styles>

6
src/Avalonia.Themes.Default/TitleBar.xaml

@ -5,7 +5,7 @@
</Border> </Border>
</Design.PreviewWith> </Design.PreviewWith>
<Style Selector="TitleBar"> <Style Selector="TitleBar">
<Setter Property="Foreground" Value="{DynamicResource SystemControlForegroundBaseHighBrush}"/> <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
<Setter Property="VerticalAlignment" Value="Top" /> <Setter Property="VerticalAlignment" Value="Top" />
<Setter Property="HorizontalAlignment" Value="Stretch" /> <Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
@ -15,7 +15,7 @@
<Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" /> <Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" />
<Panel x:Name="PART_Container"> <Panel x:Name="PART_Container">
<Border x:Name="PART_Background" Background="{TemplateBinding Background}" /> <Border x:Name="PART_Background" Background="{TemplateBinding Background}" />
<CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" MaxHeight="30" /> <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" />
</Panel> </Panel>
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>
@ -23,7 +23,7 @@
</Style> </Style>
<Style Selector="TitleBar:fullscreen"> <Style Selector="TitleBar:fullscreen">
<Setter Property="Background" Value="{DynamicResource SystemAccentColor}" /> <Setter Property="Background" Value="{DynamicResource ThemeAccentColor}" />
</Style> </Style>
<Style Selector="TitleBar /template/ Border#PART_Background"> <Style Selector="TitleBar /template/ Border#PART_Background">

47
src/Avalonia.Themes.Default/ToggleSwitch.xaml

@ -6,8 +6,40 @@
<GridLength x:Key="ToggleSwitchPreContentMargin">6</GridLength> <GridLength x:Key="ToggleSwitchPreContentMargin">6</GridLength>
<GridLength x:Key="ToggleSwitchPostContentMargin">6</GridLength> <GridLength x:Key="ToggleSwitchPostContentMargin">6</GridLength>
<x:Double x:Key="ToggleSwitchThemeMinWidth">154</x:Double> <x:Double x:Key="ToggleSwitchThemeMinWidth">154</x:Double>
<x:Double x:Key="KnobOnPosition">20</x:Double> <Thickness x:Key="ToggleSwitchOnStrokeThickness">0</Thickness>
<x:Double x:Key="KnobOffPosition">0</x:Double> <Thickness x:Key="ToggleSwitchOuterBorderStrokeThickness">1</Thickness>
<SolidColorBrush x:Key="ToggleSwitchContentForeground" Color="{DynamicResource ThemeForegroundColor}" />
<SolidColorBrush x:Key="ToggleSwitchContentForegroundDisabled" Color="{DynamicResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ToggleSwitchHeaderForeground" Color="{DynamicResource ThemeForegroundColor}" />
<SolidColorBrush x:Key="ToggleSwitchHeaderForegroundDisabled" Color="{DynamicResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ToggleSwitchContainerBackground" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchContainerBackgroundPointerOver" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchContainerBackgroundPressed" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchContainerBackgroundDisabled" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchFillOff" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchFillOffPointerOver" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchFillOffPressed" Color="{DynamicResource ThemeControlMidHighColor}" />
<SolidColorBrush x:Key="ToggleSwitchFillOffDisabled" Color="{DynamicResource ThemeControlTransparentColor}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOff" Color="{DynamicResource ThemeBorderMidColor}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOffPointerOver" Color="{DynamicResource ThemeBorderHighColor}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOffPressed" Color="{DynamicResource ThemeBorderHighColor}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOffDisabled" Color="{DynamicResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ToggleSwitchFillOn" Color="{DynamicResource ThemeAccentColor}" />
<SolidColorBrush x:Key="ToggleSwitchFillOnPointerOver" Color="{DynamicResource ThemeAccentColor2}" />
<SolidColorBrush x:Key="ToggleSwitchFillOnPressed" Color="{DynamicResource ThemeAccentColor3}" />
<SolidColorBrush x:Key="ToggleSwitchFillOnDisabled" Color="{DynamicResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOn" Color="{DynamicResource ThemeAccentColor}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOnPointerOver" Color="{DynamicResource ThemeAccentColor2}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOnPressed" Color="{DynamicResource ThemeAccentColor3}" />
<SolidColorBrush x:Key="ToggleSwitchStrokeOnDisabled" Color="{DynamicResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOff" Color="{DynamicResource ThemeBorderMidColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOffPointerOver" Color="{DynamicResource ThemeBorderHighColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOffPressed" Color="{DynamicResource ThemeBorderHighColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOffDisabled" Color="{DynamicResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOn" Color="{DynamicResource HighlightForegroundColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOnPointerOver" Color="{DynamicResource HighlightForegroundColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOnPressed" Color="{DynamicResource HighlightForegroundColor}" />
<SolidColorBrush x:Key="ToggleSwitchKnobFillOnDisabled" Color="{DynamicResource HighlightForegroundColor}" />
</Styles.Resources> </Styles.Resources>
<Design.PreviewWith> <Design.PreviewWith>
<StackPanel Margin="20" Width="250" Spacing="24" > <StackPanel Margin="20" Width="250" Spacing="24" >
@ -148,16 +180,13 @@
<Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOn"> <Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOn">
<Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOn}"/> <Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOn}"/>
<Setter Property="Stroke" Value="{DynamicResource ToggleSwitchKnobStrokeOn}"/>
</Style> </Style>
<Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOff"> <Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOff">
<Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOff}"/> <Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOff}"/>
<Setter Property="Stroke" Value="{DynamicResource ToggleSwitchKnobStrokeOff}"/>
</Style> </Style>
<Style Selector="ToggleSwitch /template/ Grid#MovingKnobs"> <Style Selector="ToggleSwitch /template/ Grid#MovingKnobs">
<Setter Property="Canvas.Left" Value="{DynamicResource KnobOffPosition}"/>
<Setter Property="Transitions"> <Setter Property="Transitions">
<Transitions> <Transitions>
<DoubleTransition Property="Canvas.Left" Duration="0:0:0.2" Easing="CubicEaseOut"/> <DoubleTransition Property="Canvas.Left" Duration="0:0:0.2" Easing="CubicEaseOut"/>
@ -235,10 +264,6 @@
</Style> </Style>
<!-- CheckedState --> <!-- CheckedState -->
<Style Selector="ToggleSwitch:checked /template/ Grid#MovingKnobs">
<Setter Property="Canvas.Left" Value="{DynamicResource KnobOnPosition}"/>
</Style>
<Style Selector="ToggleSwitch:checked /template/ Border#OuterBorder"> <Style Selector="ToggleSwitch:checked /template/ Border#OuterBorder">
<Setter Property="Opacity" Value="0"/> <Setter Property="Opacity" Value="0"/>
</Style> </Style>
@ -264,10 +289,6 @@
</Style> </Style>
<!--UncheckedState --> <!--UncheckedState -->
<Style Selector="ToggleSwitch:unchecked /template/ Grid#MovingKnobs">
<Setter Property="Canvas.Left" Value="{DynamicResource KnobOffPosition}"/>
</Style>
<Style Selector="ToggleSwitch:unchecked /template/ Border#OuterBorder"> <Style Selector="ToggleSwitch:unchecked /template/ Border#OuterBorder">
<Setter Property="Opacity" Value="1"/> <Setter Property="Opacity" Value="1"/>
</Style> </Style>

31
src/Avalonia.Themes.Default/Window.xaml

@ -1,23 +1,24 @@
<Style xmlns="https://github.com/avaloniaui" Selector="Window"> <Style xmlns="https://github.com/avaloniaui" Selector="Window">
<Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}"/> <Setter Property="Background" Value="{DynamicResource ThemeBackgroundBrush}"/>
<Setter Property="TransparencyBackgroundFallback" Value="{DynamicResource HighlightForegroundColor}" />
<Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/> <Setter Property="Foreground" Value="{DynamicResource ThemeForegroundBrush}"/>
<Setter Property="FontSize" Value="{DynamicResource FontSizeNormal}"/> <Setter Property="FontSize" Value="{DynamicResource FontSizeSmall}"/>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Panel> <Panel>
<Panel IsHitTestVisible="False" Margin="{TemplateBinding OffScreenMargin}"> <Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" /> <Border Background="{TemplateBinding Background}" IsHitTestVisible="False" />
</Panel> <VisualLayerManager>
<Border Background="{TemplateBinding Background}"> <VisualLayerManager.ChromeOverlayLayer>
<VisualLayerManager> <TitleBar />
<ContentPresenter Name="PART_ContentPresenter" </VisualLayerManager.ChromeOverlayLayer>
ContentTemplate="{TemplateBinding ContentTemplate}" <ContentPresenter Name="PART_ContentPresenter"
Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"
Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
</VisualLayerManager> VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border> </VisualLayerManager>
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

12
src/Avalonia.Themes.Fluent/Accents/Base.xaml

@ -6,12 +6,12 @@
<!-- SystemColor Color Resources (Reflect OS High Contrast Settings) --> <!-- SystemColor Color Resources (Reflect OS High Contrast Settings) -->
<Color x:Key="SystemColorButtonFaceColor">#FFF0F0F0</Color> <Color x:Key="SystemColorButtonFaceColor">#FFF0F0F0</Color>
<Color x:Key="SystemColorButtonTextColor">#FF000000</Color> <Color x:Key="SystemColorButtonTextColor">#FF000000</Color>
<Color x:Key="SystemColorGrayText">#FF6D6D6D</Color> <Color x:Key="SystemColorGrayTextColor">#FF6D6D6D</Color>
<Color x:Key="SystemColorHighlight">#FF3399FF</Color> <Color x:Key="SystemColorHighlightColor">#FF3399FF</Color>
<Color x:Key="SystemColorHighlightText">#FFFFFFFF</Color> <Color x:Key="SystemColorHighlightTextColor">#FFFFFFFF</Color>
<Color x:Key="SystemColorHotlight">#FF0066CC</Color> <Color x:Key="SystemColorHotlightColor">#FF0066CC</Color>
<Color x:Key="SystemColorWindow">#FFFFFFFF</Color> <Color x:Key="SystemColorWindowColor">#FFFFFFFF</Color>
<Color x:Key="SystemColorWindowText">#FF000000</Color> <Color x:Key="SystemColorWindowTextColor">#FF000000</Color>
<FontFamily x:Key="ContentControlThemeFontFamily">avares://Avalonia.Themes.Fluent/Assets#Roboto</FontFamily> <FontFamily x:Key="ContentControlThemeFontFamily">avares://Avalonia.Themes.Fluent/Assets#Roboto</FontFamily>
<sys:Double x:Key="ControlContentThemeFontSize">14</sys:Double> <sys:Double x:Key="ControlContentThemeFontSize">14</sys:Double>

9
src/Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml

@ -437,6 +437,15 @@
<StaticResource x:Key="CalendarViewCalendarItemRevealBorderBrush" ResourceKey="SystemControlTransparentRevealBorderBrush" /> <StaticResource x:Key="CalendarViewCalendarItemRevealBorderBrush" ResourceKey="SystemControlTransparentRevealBorderBrush" />
<StaticResource x:Key="CalendarViewNavigationButtonBorderBrushPointerOver" ResourceKey="SystemControlHighlightTransparentBrush" /> <StaticResource x:Key="CalendarViewNavigationButtonBorderBrushPointerOver" ResourceKey="SystemControlHighlightTransparentBrush" />
<StaticResource x:Key="CalendarViewNavigationButtonBorderBrush" ResourceKey="SystemControlTransparentBrush" /> <StaticResource x:Key="CalendarViewNavigationButtonBorderBrush" ResourceKey="SystemControlTransparentBrush" />
<!--Resources for NotificationCard.xaml -->
<SolidColorBrush x:Key="NotificationCardBackgroundBrush" Color="#444444" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardProgressBackgroundBrush" Color="#9A9A9A" />
<SolidColorBrush x:Key="NotificationCardInformationBackgroundBrush" Color="#007ACC" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardSuccessBackgroundBrush" Color="#1F9E45" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardWarningBackgroundBrush" Color="#FDB328" Opacity="0.75"/>
<SolidColorBrush x:Key="NotificationCardErrorBackgroundBrush" Color="#BD202C" Opacity="0.75"/>
<!-- Resources for RadioButton.xaml --> <!-- Resources for RadioButton.xaml -->
<x:Double x:Key="RadioButtonBorderThemeThickness">1</x:Double> <x:Double x:Key="RadioButtonBorderThemeThickness">1</x:Double>
<StaticResource x:Key="RadioButtonForeground" ResourceKey="SystemControlForegroundBaseHighBrush" /> <StaticResource x:Key="RadioButtonForeground" ResourceKey="SystemControlForegroundBaseHighBrush" />

3
src/Avalonia.Themes.Fluent/AutoCompleteBox.xaml

@ -52,13 +52,12 @@
<Border Name="PART_SuggestionsContainer" <Border Name="PART_SuggestionsContainer"
Padding="{DynamicResource AutoCompleteListMargin}" Padding="{DynamicResource AutoCompleteListMargin}"
BorderThickness="{DynamicResource AutoCompleteListBorderThemeThickness}" BorderThickness="{DynamicResource AutoCompleteListBorderThemeThickness}"
BorderBrush="{DynamicResource AutoSuggestBoxSuggestionsListBorderBrush}" BorderBrush="{DynamicResource AutoCompleteBoxSuggestionsListBorderBrush}"
Background="{DynamicResource AutoCompleteBoxSuggestionsListBackground}" Background="{DynamicResource AutoCompleteBoxSuggestionsListBackground}"
CornerRadius="{DynamicResource OverlayCornerRadius}"> CornerRadius="{DynamicResource OverlayCornerRadius}">
<ListBox Name="PART_SelectingItemsControl" <ListBox Name="PART_SelectingItemsControl"
BorderThickness="0" BorderThickness="0"
Background="Transparent" Background="Transparent"
Foreground="{DynamicResource AutoCompleteBoxSuggestionsListForeground}"
ItemTemplate="{TemplateBinding ItemTemplate}" ItemTemplate="{TemplateBinding ItemTemplate}"
Margin="{DynamicResource AutoCompleteListPadding}" /> Margin="{DynamicResource AutoCompleteListPadding}" />
</Border> </Border>

1
src/Avalonia.Themes.Fluent/Avalonia.Themes.Fluent.csproj

@ -17,4 +17,5 @@
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

14
src/Avalonia.Themes.Fluent/Button.xaml

@ -41,37 +41,37 @@
</Style> </Style>
<!-- PointerOverState --> <!-- PointerOverState -->
<Style Selector="Button:pointerover /template/ ContentPresenter"> <Style Selector="Button:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" /> <Setter Property="Background" Value="{DynamicResource ButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPointerOver}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ButtonForegroundPointerOver}" />
</Style> </Style>
<Style Selector="Button:pressed /template/ ContentPresenter"> <Style Selector="Button:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" /> <Setter Property="Background" Value="{DynamicResource ButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushPressed}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ButtonForegroundPressed}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ButtonForegroundPressed}" />
</Style> </Style>
<Style Selector="Button:disabled /template/ ContentPresenter"> <Style Selector="Button:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" /> <Setter Property="Background" Value="{DynamicResource ButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource ButtonBorderBrushDisabled}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ButtonForegroundDisabled}" />
</Style> </Style>
<Style Selector="Button.accent /template/ ContentPresenter"> <Style Selector="Button.accent /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" /> <Setter Property="Background" Value="{DynamicResource AccentButtonBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrush}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForeground}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForeground}" />
</Style> </Style>
<Style Selector="Button.accent:pointerover /template/ ContentPresenter"> <Style Selector="Button.accent:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}" /> <Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPointerOver}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForegroundPointerOver}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForegroundPointerOver}" />
</Style> </Style>
<Style Selector="Button.accent:pressed /template/ ContentPresenter"> <Style Selector="Button.accent:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" /> <Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushPressed}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForegroundPressed}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForegroundPressed}" />
@ -90,7 +90,7 @@
<Setter Property="RenderTransform" Value="scale(0.98)" /> <Setter Property="RenderTransform" Value="scale(0.98)" />
</Style> </Style>
<Style Selector="Button.accent:disabled /template/ ContentPresenter"> <Style Selector="Button.accent:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundDisabled}" /> <Setter Property="Background" Value="{DynamicResource AccentButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource AccentButtonBorderBrushDisabled}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForegroundDisabled}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource AccentButtonForegroundDisabled}" />

8
src/Avalonia.Themes.Fluent/ButtonSpinner.xaml

@ -8,7 +8,11 @@
<StackPanel Spacing="20"> <StackPanel Spacing="20">
<ButtonSpinner ButtonSpinnerLocation="Right" <ButtonSpinner ButtonSpinnerLocation="Right"
Content="Right disabled inline spinner" Content="Right disabled inline spinner"
AllowSpin="False" /> AllowSpin="False">
<DataValidationErrors.Error>
<sys:Exception />
</DataValidationErrors.Error>
</ButtonSpinner>
<ButtonSpinner ButtonSpinnerLocation="Left" <ButtonSpinner ButtonSpinnerLocation="Left"
Content="Left spinner" /> Content="Left spinner" />
<ButtonSpinner ShowButtonSpinner="False" <ButtonSpinner ShowButtonSpinner="False"
@ -133,7 +137,7 @@
<!-- Error state --> <!-- Error state -->
<Style Selector="ButtonSpinner:error"> <Style Selector="ButtonSpinner:error">
<Setter Property="BorderBrush" Value="{DynamicResource ErrorBrush}" /> <Setter Property="BorderBrush" Value="{DynamicResource SystemErrorTextColor}" />
</Style> </Style>
</Styles> </Styles>

2
src/Avalonia.Themes.Fluent/CalendarButton.xaml

@ -67,7 +67,7 @@
<!-- Adjusted :selected to look like :today from DayItem --> <!-- Adjusted :selected to look like :today from DayItem -->
<Style Selector="CalendarButton:selected /template/ Border#Root"> <Style Selector="CalendarButton:selected /template/ Border#Root">
<Setter Property="Background" Value="{DynamicResource SystemAccentBrush}"/> <Setter Property="Background" Value="{DynamicResource SystemAccentColor}"/>
</Style> </Style>
<Style Selector="CalendarButton:selected /template/ Border#Border"> <Style Selector="CalendarButton:selected /template/ Border#Border">
<Setter Property="BorderBrush" Value="{DynamicResource CalendarViewSelectedBorderBrush}"/> <Setter Property="BorderBrush" Value="{DynamicResource CalendarViewSelectedBorderBrush}"/>

6
src/Avalonia.Themes.Fluent/CalendarDatePicker.xaml

@ -13,6 +13,10 @@
<CalendarDatePicker/> <CalendarDatePicker/>
</Border> </Border>
</Design.PreviewWith> </Design.PreviewWith>
<Styles.Resources>
<sys:Double x:Key="CalendarDatePickerCurrentDayFontSize">12</sys:Double>
</Styles.Resources>
<Style Selector="CalendarDatePicker"> <Style Selector="CalendarDatePicker">
@ -70,7 +74,7 @@
Grid.Row="1" Grid.Row="1"
Grid.ColumnSpan="4" Grid.ColumnSpan="4"
Grid.RowSpan="3" Grid.RowSpan="3"
FontSize="{DynamicResource FontSizeSmall}" FontSize="{StaticResource CalendarDatePickerCurrentDayFontSize}"
Text="{Binding Source={x:Static sys:DateTime.Today}, Path=Day}"/> Text="{Binding Source={x:Static sys:DateTime.Today}, Path=Day}"/>
<Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Fill="{DynamicResource SystemControlBackgroundChromeBlackHighBrush}" StrokeThickness="0" Grid.ColumnSpan="4" Width="3" Height="3"/> <Ellipse HorizontalAlignment="Center" VerticalAlignment="Center" Fill="{DynamicResource SystemControlBackgroundChromeBlackHighBrush}" StrokeThickness="0" Grid.ColumnSpan="4" Width="3" Height="3"/>

1
src/Avalonia.Themes.Fluent/ComboBox.xaml

@ -79,6 +79,7 @@
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" Margin="{TemplateBinding Padding}"
Text="{TemplateBinding PlaceholderText}" Text="{TemplateBinding PlaceholderText}"
Foreground="{TemplateBinding PlaceholderForeground}"
IsVisible="{TemplateBinding SelectionBoxItem, Converter={x:Static ObjectConverters.IsNull}}" /> IsVisible="{TemplateBinding SelectionBoxItem, Converter={x:Static ObjectConverters.IsNull}}" />
<ContentControl x:Name="ContentPresenter" <ContentControl x:Name="ContentPresenter"
Content="{TemplateBinding SelectionBoxItem}" Content="{TemplateBinding SelectionBoxItem}"

18
src/Avalonia.Themes.Fluent/DataValidationErrors.xaml

@ -1,5 +1,16 @@
<Style xmlns="https://github.com/avaloniaui" <Style xmlns="https://github.com/avaloniaui"
Selector="DataValidationErrors"> Selector="DataValidationErrors"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Design.PreviewWith>
<Border Padding="20">
<TextBox Text="Sample">
<DataValidationErrors.Error>
<sys:Exception/>
</DataValidationErrors.Error>
</TextBox>
</Border>
</Design.PreviewWith>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<DockPanel LastChildFill="True"> <DockPanel LastChildFill="True">
@ -24,14 +35,13 @@
Background="Transparent"> Background="Transparent">
<Canvas.Styles> <Canvas.Styles>
<Style Selector="ToolTip"> <Style Selector="ToolTip">
<Setter Property="Background" Value="{DynamicResource ErrorLowBrush}"/> <Setter Property="BorderBrush" Value="{DynamicResource SystemControlErrorTextForegroundBrush}"/>
<Setter Property="BorderBrush" Value="{DynamicResource ErrorBrush}"/>
</Style> </Style>
</Canvas.Styles> </Canvas.Styles>
<ToolTip.Tip> <ToolTip.Tip>
<ItemsControl Items="{Binding}"/> <ItemsControl Items="{Binding}"/>
</ToolTip.Tip> </ToolTip.Tip>
<Path Data="M14,7 A7,7 0 0,0 0,7 M0,7 A7,7 0 1,0 14,7 M7,3l0,5 M7,9l0,2" Stroke="{DynamicResource ErrorBrush}" StrokeThickness="2"/> <Path Data="M14,7 A7,7 0 0,0 0,7 M0,7 A7,7 0 1,0 14,7 M7,3l0,5 M7,9l0,2" Stroke="{DynamicResource SystemControlErrorTextForegroundBrush}" StrokeThickness="2"/>
</Canvas> </Canvas>
</DataTemplate> </DataTemplate>
</Setter> </Setter>

6
src/Avalonia.Themes.Fluent/Menu.xaml

@ -11,10 +11,12 @@
</Design.PreviewWith> </Design.PreviewWith>
<Style.Resources> <Style.Resources>
<x:Double x:Key="MenuHeight">32</x:Double> <x:Double x:Key="MenuBarHeight">32</x:Double>
<Thickness x:Key="MenuBarItemPadding">12,0,12,0</Thickness>
</Style.Resources> </Style.Resources>
<Setter Property="Background" Value="Transparent" /> <Setter Property="Background" Value="Transparent" />
<Setter Property="Height" Value="{StaticResource MenuHeight}" /> <Setter Property="Height" Value="{StaticResource MenuBarHeight}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Border Background="{TemplateBinding Background}" <Border Background="{TemplateBinding Background}"

188
src/Avalonia.Themes.Fluent/MenuItem.xaml

@ -25,11 +25,12 @@
</MenuItem> </MenuItem>
<MenuItem Header="Edit"> <MenuItem Header="Edit">
<MenuItem Header="Go To"> <MenuItem Header="Go To">
<MenuItem Header="Go To Line"/> <MenuItem Header="Go To Line" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
<MenuItem Header="View"> <MenuItem Header="View">
<MenuItem Header="Designer" InputGesture="Shift+F7" /> <MenuItem Header="Designer"
InputGesture="Shift+F7" />
</MenuItem> </MenuItem>
<MenuItem Header="Project"> <MenuItem Header="Project">
<MenuItem Header="Add class" /> <MenuItem Header="Add class" />
@ -40,97 +41,98 @@
<Styles.Resources> <Styles.Resources>
<conv:PlatformKeyGestureConverter x:Key="KeyGestureConverter" /> <conv:PlatformKeyGestureConverter x:Key="KeyGestureConverter" />
<x:Double x:Key="MenuFlyoutSubItemPopupHorizontalOffset">-4</x:Double>
<Thickness x:Key="MenuFlyoutScrollerMargin">0,4,0,4</Thickness> <Thickness x:Key="MenuFlyoutScrollerMargin">0,4,0,4</Thickness>
<Thickness x:Key="MenuIconPresenterMargin">0,0,12,0</Thickness> <Thickness x:Key="MenuIconPresenterMargin">0,0,12,0</Thickness>
<Thickness x:Key="MenuInputGestureTextMargin">24,0,0,0</Thickness> <Thickness x:Key="MenuInputGestureTextMargin">24,0,0,0</Thickness>
<StreamGeometry x:Key="MenuItemChevronPathData">M 1,0 10,10 l -9,10 -1,-1 L 8,10 -0,1 Z</StreamGeometry> <StreamGeometry x:Key="MenuItemChevronPathData">M 1,0 10,10 l -9,10 -1,-1 L 8,10 -0,1 Z</StreamGeometry>
</Styles.Resources> </Styles.Resources>
<Style Selector="MenuItem"> <Style Selector="MenuItem">
<Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackground}" /> <Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackground}" />
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutItemRevealBorderBrush}" />
<Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemForeground}" /> <Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemForeground}" />
<Setter Property="Padding" Value="{DynamicResource MenuFlyoutItemThemePadding}" /> <Setter Property="Padding" Value="{DynamicResource MenuFlyoutItemThemePadding}" />
<Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" /> <Setter Property="FontSize" Value="{DynamicResource ControlContentThemeFontSize}" />
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Border Name="PART_LayoutRoot" <Panel>
Padding="{TemplateBinding Padding}" <Border Name="PART_LayoutRoot"
Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}"
BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"> BorderBrush="{TemplateBinding BorderBrush}"
<Grid> BorderThickness="{TemplateBinding BorderThickness}">
<Grid.ColumnDefinitions> <Grid>
<ColumnDefinition Width="Auto" <Grid.ColumnDefinitions>
SharedSizeGroup="MenuItemIcon" /> <ColumnDefinition Width="Auto"
<ColumnDefinition Width="*" /> SharedSizeGroup="MenuItemIcon" />
<ColumnDefinition Width="Auto" <ColumnDefinition Width="*" />
SharedSizeGroup="MenuItemIGT" /> <ColumnDefinition Width="Auto"
<ColumnDefinition Width="Auto" SharedSizeGroup="MenuItemIGT" />
SharedSizeGroup="MenuItemChevron" /> <ColumnDefinition Width="Auto"
</Grid.ColumnDefinitions> SharedSizeGroup="MenuItemChevron" />
<ContentPresenter Name="PART_IconPresenter" </Grid.ColumnDefinitions>
Content="{TemplateBinding Icon}" <ContentPresenter Name="PART_IconPresenter"
Width="16" Content="{TemplateBinding Icon}"
Height="16" Width="16"
Margin="{DynamicResource MenuIconPresenterMargin}" Height="16"
HorizontalAlignment="Center" Margin="{DynamicResource MenuIconPresenterMargin}"
VerticalAlignment="Center"/> HorizontalAlignment="Center"
VerticalAlignment="Center" />
<ContentPresenter Name="PART_HeaderPresenter" <ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}" Content="{TemplateBinding Header}"
VerticalAlignment="Center" VerticalAlignment="Center"
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
TextBlock.Foreground="{TemplateBinding Foreground}" TextBlock.Foreground="{TemplateBinding Foreground}"
Grid.Column="1"> Grid.Column="1">
<ContentPresenter.DataTemplates> <ContentPresenter.DataTemplates>
<DataTemplate DataType="sys:String"> <DataTemplate DataType="sys:String">
<AccessText Text="{Binding}" /> <AccessText Text="{Binding}" />
</DataTemplate> </DataTemplate>
</ContentPresenter.DataTemplates> </ContentPresenter.DataTemplates>
</ContentPresenter> </ContentPresenter>
<TextBlock x:Name="PART_InputGestureText" <TextBlock x:Name="PART_InputGestureText"
Grid.Column="2" Grid.Column="2"
Classes="CaptionTextBlockStyle" Classes="CaptionTextBlockStyle"
Margin="{DynamicResource MenuInputGestureTextMargin}" Margin="{DynamicResource MenuInputGestureTextMargin}"
Text="{TemplateBinding InputGesture, Text="{TemplateBinding InputGesture, Converter={StaticResource KeyGestureConverter}}"
Converter={StaticResource KeyGestureConverter}}" HorizontalAlignment="Right"
HorizontalAlignment="Right" VerticalAlignment="Center" />
VerticalAlignment="Center" /> <Path Name="PART_ChevronPath"
<Path Name="PART_ChevronPath" Stretch="Uniform"
Stretch="Uniform" Width="8"
Width="8" Height="16"
Height="16" Data="{StaticResource MenuItemChevronPathData}"
Data="{StaticResource MenuItemChevronPathData}" Margin="{DynamicResource MenuFlyoutItemChevronMargin}"
Margin="{DynamicResource MenuFlyoutItemChevronMargin}" VerticalAlignment="Center"
VerticalAlignment="Center" Grid.Column="3" />
Grid.Column="3" /> </Grid>
<Popup Name="PART_Popup" </Border>
WindowManagerAddShadowHint="True" <Popup Name="PART_Popup"
PlacementMode="Right" WindowManagerAddShadowHint="True"
StaysOpen="True" PlacementMode="Right"
IsOpen="{TemplateBinding IsSubMenuOpen, HorizontalOffset="{StaticResource MenuFlyoutSubItemPopupHorizontalOffset}"
Mode=TwoWay}"> StaysOpen="True"
<Border Background="{DynamicResource MenuFlyoutPresenterBackground}" IsOpen="{TemplateBinding IsSubMenuOpen, Mode=TwoWay}">
BorderBrush="{DynamicResource MenuFlyoutPresenterBorderBrush}" <Border Background="{DynamicResource MenuFlyoutPresenterBackground}"
BorderThickness="{DynamicResource MenuFlyoutPresenterBorderThemeThickness}" BorderBrush="{DynamicResource MenuFlyoutPresenterBorderBrush}"
Padding="{DynamicResource MenuFlyoutPresenterThemePadding}" BorderThickness="{DynamicResource MenuFlyoutPresenterBorderThemeThickness}"
MaxWidth="{DynamicResource FlyoutThemeMaxWidth}" Padding="{DynamicResource MenuFlyoutPresenterThemePadding}"
MinHeight="{DynamicResource MenuFlyoutThemeMinHeight}" MaxWidth="{DynamicResource FlyoutThemeMaxWidth}"
HorizontalAlignment="Stretch" MinHeight="{DynamicResource MenuFlyoutThemeMinHeight}"
CornerRadius="{DynamicResource OverlayCornerRadius}"> HorizontalAlignment="Stretch"
<ScrollViewer> CornerRadius="{DynamicResource OverlayCornerRadius}">
<ItemsPresenter Name="PART_ItemsPresenter" <ScrollViewer>
Items="{TemplateBinding Items}" <ItemsPresenter Name="PART_ItemsPresenter"
ItemsPanel="{TemplateBinding ItemsPanel}" Items="{TemplateBinding Items}"
ItemTemplate="{TemplateBinding ItemTemplate}" ItemsPanel="{TemplateBinding ItemsPanel}"
Margin="{DynamicResource MenuFlyoutScrollerMargin}" ItemTemplate="{TemplateBinding ItemTemplate}"
Grid.IsSharedSizeScope="True" /> Margin="{DynamicResource MenuFlyoutScrollerMargin}"
</ScrollViewer> Grid.IsSharedSizeScope="True" />
</Border> </ScrollViewer>
</Popup> </Border>
</Grid> </Popup>
</Border> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>
</Style> </Style>
@ -145,6 +147,8 @@
<Panel> <Panel>
<ContentPresenter Name="PART_HeaderPresenter" <ContentPresenter Name="PART_HeaderPresenter"
Content="{TemplateBinding Header}" Content="{TemplateBinding Header}"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Margin="{TemplateBinding Padding}"> Margin="{TemplateBinding Padding}">
<ContentPresenter.DataTemplates> <ContentPresenter.DataTemplates>
<DataTemplate DataType="sys:String"> <DataTemplate DataType="sys:String">
@ -155,8 +159,7 @@
<Popup Name="PART_Popup" <Popup Name="PART_Popup"
WindowManagerAddShadowHint="False" WindowManagerAddShadowHint="False"
MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}" MinWidth="{Binding Bounds.Width, RelativeSource={RelativeSource TemplatedParent}}"
IsOpen="{TemplateBinding IsSubMenuOpen, IsOpen="{TemplateBinding IsSubMenuOpen, Mode=TwoWay}"
Mode=TwoWay}"
StaysOpen="True"> StaysOpen="True">
<Border Background="{DynamicResource MenuFlyoutPresenterBackground}" <Border Background="{DynamicResource MenuFlyoutPresenterBackground}"
BorderBrush="{DynamicResource MenuFlyoutPresenterBorderBrush}" BorderBrush="{DynamicResource MenuFlyoutPresenterBorderBrush}"
@ -183,10 +186,15 @@
</Style> </Style>
<Style Selector="MenuItem"> <Style Selector="MenuItem">
<!-- Narrow padding should be used for mouse input, when non-narrow one should be used for touch input in future. --> <!-- Narrow padding should be used for mouse input, when non-narrow one should be used for touch input in future. -->
<Setter Property="Padding" Value="{DynamicResource MenuFlyoutItemThemePaddingNarrow}" /> <Setter Property="Padding" Value="{StaticResource MenuFlyoutItemThemePaddingNarrow}" />
</Style> </Style>
<Style Selector="Menu > MenuItem">
<!-- Custom padding for Menu > MenuItem -->
<Setter Property="Padding" Value="{StaticResource MenuBarItemPadding}" />
</Style>
<Style Selector="MenuItem /template/ ContentPresenter#PART_IconPresenter"> <Style Selector="MenuItem /template/ ContentPresenter#PART_IconPresenter">
<Setter Property="IsVisible" Value="False" /> <Setter Property="IsVisible" Value="False" />
</Style> </Style>
@ -203,7 +211,6 @@
<Style Selector="MenuItem:selected /template/ Border#PART_LayoutRoot"> <Style Selector="MenuItem:selected /template/ Border#PART_LayoutRoot">
<Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundPointerOver}" /> <Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutItemBorderBrushPointerOver}" />
</Style> </Style>
<Style Selector="MenuItem:selected /template/ TextBlock#PART_InputGestureText"> <Style Selector="MenuItem:selected /template/ TextBlock#PART_InputGestureText">
<Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForegroundPointerOver}" /> <Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForegroundPointerOver}" />
@ -212,20 +219,19 @@
<Setter Property="Fill" Value="{DynamicResource MenuFlyoutSubItemChevronPointerOver}" /> <Setter Property="Fill" Value="{DynamicResource MenuFlyoutSubItemChevronPointerOver}" />
</Style> </Style>
<Style Selector="MenuItem:pressed /template/ Border#PART_LayoutRoot"> <!-- Listen for PART_LayoutRoot:pointerover, so it will not be triggered when subitem is pressed -->
<Style Selector="MenuItem:pressed /template/ Border#PART_LayoutRoot:pointerover">
<Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundPressed}" /> <Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutItemBorderBrushPressed}" />
</Style> </Style>
<Style Selector="MenuItem:pressed /template/ TextBlock#PART_InputGestureText"> <Style Selector="MenuItem:pressed /template/ Border#PART_LayoutRoot:pointerover TextBlock#PART_InputGestureText">
<Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForegroundPressed}" /> <Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForegroundPressed}" />
</Style> </Style>
<Style Selector="MenuItem:pressed /template/ Path#PART_ChevronPath"> <Style Selector="MenuItem:pressed /template/ Border#PART_LayoutRoot:pointerover Path#PART_ChevronPath">
<Setter Property="Fill" Value="{DynamicResource MenuFlyoutSubItemChevronPressed}" /> <Setter Property="Fill" Value="{DynamicResource MenuFlyoutSubItemChevronPressed}" />
</Style> </Style>
<Style Selector="MenuItem:disabled"> <Style Selector="MenuItem:disabled">
<Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundDisabled}" /> <Setter Property="Background" Value="{DynamicResource MenuFlyoutItemBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource MenuFlyoutItemBorderBrushDisabled}" />
</Style> </Style>
<Style Selector="MenuItem:disabled /template/ TextBlock#PART_InputGestureText"> <Style Selector="MenuItem:disabled /template/ TextBlock#PART_InputGestureText">
<Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForegroundDisabled}" /> <Setter Property="Foreground" Value="{DynamicResource MenuFlyoutItemKeyboardAcceleratorTextForegroundDisabled}" />

2
src/Avalonia.Themes.Fluent/NumericUpDown.xaml

@ -43,7 +43,7 @@
<TextBox Name="PART_TextBox" <TextBox Name="PART_TextBox"
Background="Transparent" Background="Transparent"
BorderBrush="Transparent" BorderBrush="Transparent"
Margin="-2" Margin="-1"
Padding="{TemplateBinding Padding}" Padding="{TemplateBinding Padding}"
Watermark="{TemplateBinding Watermark}" Watermark="{TemplateBinding Watermark}"
DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}" DataValidationErrors.Errors="{TemplateBinding (DataValidationErrors.Errors)}"

8
src/Avalonia.Themes.Fluent/RepeatButton.xaml

@ -37,23 +37,23 @@
</Setter> </Setter>
</Style> </Style>
<Style Selector="RepeatButton /template/ ContentPresenter"> <Style Selector="RepeatButton /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" /> <Setter Property="CornerRadius" Value="{DynamicResource ControlCornerRadius}" />
</Style> </Style>
<Style Selector="RepeatButton:pointerover /template/ ContentPresenter"> <Style Selector="RepeatButton:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource RepeatButtonBackgroundPointerOver}" /> <Setter Property="Background" Value="{DynamicResource RepeatButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource RepeatButtonBorderBrushPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource RepeatButtonBorderBrushPointerOver}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource RepeatButtonForegroundPointerOver}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource RepeatButtonForegroundPointerOver}" />
</Style> </Style>
<Style Selector="RepeatButton:pressed /template/ ContentPresenter"> <Style Selector="RepeatButton:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource RepeatButtonBackgroundPressed}" /> <Setter Property="Background" Value="{DynamicResource RepeatButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource RepeatButtonBorderBrushPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource RepeatButtonBorderBrushPressed}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource RepeatButtonForegroundPressed}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource RepeatButtonForegroundPressed}" />
</Style> </Style>
<Style Selector="RepeatButton:disabled /template/ ContentPresenter"> <Style Selector="RepeatButton:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource RepeatButtonBackgroundDisabled}" /> <Setter Property="Background" Value="{DynamicResource RepeatButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource RepeatButtonBorderBrushDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource RepeatButtonBorderBrushDisabled}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource RepeatButtonForegroundDisabled}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource RepeatButtonForegroundDisabled}" />

21
src/Avalonia.Themes.Fluent/TextBox.xaml

@ -1,4 +1,13 @@
<Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Styles xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Design.PreviewWith>
<Border Padding="20">
<TextBox Text="Sample"
FontSize="20"
Width="100"
TextAlignment="Center"/>
</Border>
</Design.PreviewWith>
<Styles.Resources> <Styles.Resources>
<Thickness x:Key="TextBoxTopHeaderMargin">0,0,0,4</Thickness> <Thickness x:Key="TextBoxTopHeaderMargin">0,0,0,4</Thickness>
</Styles.Resources> </Styles.Resources>
@ -42,7 +51,7 @@
<DockPanel> <DockPanel>
<TextBlock Name="floatingWatermark" <TextBlock Name="floatingWatermark"
Foreground="{DynamicResource SystemAccentColor}" Foreground="{DynamicResource SystemAccentColor}"
FontSize="{DynamicResource FontSizeSmall}" FontSize="{TemplateBinding FontSize}"
Text="{TemplateBinding Watermark}" Text="{TemplateBinding Watermark}"
DockPanel.Dock="Top"> DockPanel.Dock="Top">
<TextBlock.IsVisible> <TextBlock.IsVisible>
@ -66,7 +75,9 @@
Text="{TemplateBinding Watermark}" Text="{TemplateBinding Watermark}"
TextAlignment="{TemplateBinding TextAlignment}" TextAlignment="{TemplateBinding TextAlignment}"
TextWrapping="{TemplateBinding TextWrapping}" TextWrapping="{TemplateBinding TextWrapping}"
IsVisible="{TemplateBinding Text, Converter={x:Static StringConverters.IsNullOrEmpty}}"/> IsVisible="{TemplateBinding Text, Converter={x:Static StringConverters.IsNullOrEmpty}}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
<!-- TODO eliminate this margin... text layout issue? --> <!-- TODO eliminate this margin... text layout issue? -->
<TextPresenter Name="PART_TextPresenter" <TextPresenter Name="PART_TextPresenter"
Margin="0 1 0 0" Margin="0 1 0 0"
@ -79,7 +90,9 @@
PasswordChar="{TemplateBinding PasswordChar}" PasswordChar="{TemplateBinding PasswordChar}"
SelectionBrush="{TemplateBinding SelectionBrush}" SelectionBrush="{TemplateBinding SelectionBrush}"
SelectionForegroundBrush="{TemplateBinding SelectionForegroundBrush}" SelectionForegroundBrush="{TemplateBinding SelectionForegroundBrush}"
CaretBrush="{TemplateBinding CaretBrush}"/> CaretBrush="{TemplateBinding CaretBrush}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Panel> </Panel>
</ScrollViewer> </ScrollViewer>
</DataValidationErrors> </DataValidationErrors>
@ -136,7 +149,7 @@
<Style Selector="TextBox:error /template/ Border#border"> <Style Selector="TextBox:error /template/ Border#border">
<Setter Property="BorderBrush" Value="{DynamicResource ErrorBrush}"/> <Setter Property="BorderBrush" Value="{DynamicResource SystemControlErrorTextForegroundBrush}"/>
</Style> </Style>
<Style Selector="TextBox /template/ DockPanel"> <Style Selector="TextBox /template/ DockPanel">

2
src/Avalonia.Themes.Fluent/TitleBar.xaml

@ -15,7 +15,7 @@
<Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" /> <Panel x:Name="PART_MouseTracker" Height="1" VerticalAlignment="Top" />
<Panel x:Name="PART_Container"> <Panel x:Name="PART_Container">
<Border x:Name="PART_Background" Background="{TemplateBinding Background}" /> <Border x:Name="PART_Background" Background="{TemplateBinding Background}" />
<CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" MaxHeight="30" /> <CaptionButtons x:Name="PART_CaptionButtons" VerticalAlignment="Top" HorizontalAlignment="Right" Foreground="{TemplateBinding Foreground}" />
</Panel> </Panel>
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>

22
src/Avalonia.Themes.Fluent/ToggleButton.xaml

@ -39,67 +39,67 @@
</Setter> </Setter>
</Style> </Style>
<Style Selector="ToggleButton:pointerover /template/ ContentPresenter"> <Style Selector="ToggleButton:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPointerOver}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushPointerOver}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundPointerOver}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundPointerOver}" />
</Style> </Style>
<Style Selector="ToggleButton:pressed /template/ ContentPresenter"> <Style Selector="ToggleButton:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPressed}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushPressed}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundPressed}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundPressed}" />
</Style> </Style>
<Style Selector="ToggleButton:disabled /template/ ContentPresenter"> <Style Selector="ToggleButton:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundDisabled}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushDisabled}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundDisabled}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundDisabled}" />
</Style> </Style>
<Style Selector="ToggleButton:checked /template/ ContentPresenter"> <Style Selector="ToggleButton:checked /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundChecked}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundChecked}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushChecked}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushChecked}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundChecked}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundChecked}" />
</Style> </Style>
<Style Selector="ToggleButton:checked:pointerover /template/ ContentPresenter"> <Style Selector="ToggleButton:checked:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPointerOver}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedPointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedPointerOver}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPointerOver}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPointerOver}" />
</Style> </Style>
<Style Selector="ToggleButton:checked:pressed /template/ ContentPresenter"> <Style Selector="ToggleButton:checked:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPressed}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedPressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedPressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedPressed}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPressed}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedPressed}" />
</Style> </Style>
<Style Selector="ToggleButton:checked:disabled /template/ ContentPresenter"> <Style Selector="ToggleButton:checked:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedDisabled}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundCheckedDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushCheckedDisabled}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedDisabled}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundCheckedDisabled}" />
</Style> </Style>
<Style Selector="ToggleButton:indeterminate /template/ ContentPresenter"> <Style Selector="ToggleButton:indeterminate /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminate}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminate}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminate}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminate}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminate}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminate}" />
</Style> </Style>
<Style Selector="ToggleButton:indeterminate:pointerover /template/ ContentPresenter"> <Style Selector="ToggleButton:indeterminate:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminatePointerOver}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminatePointerOver}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminatePointerOver}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminatePointerOver}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminatePointerOver}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminatePointerOver}" />
</Style> </Style>
<Style Selector="ToggleButton:indeterminate:pressed /template/ ContentPresenter"> <Style Selector="ToggleButton:indeterminate:pressed /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminatePressed}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminatePressed}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminatePressed}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminatePressed}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminatePressed}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminatePressed}" />
</Style> </Style>
<Style Selector="ToggleButton:indeterminate:disabled /template/ ContentPresenter"> <Style Selector="ToggleButton:indeterminate:disabled /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminateDisabled}" /> <Setter Property="Background" Value="{DynamicResource ToggleButtonBackgroundIndeterminateDisabled}" />
<Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminateDisabled}" /> <Setter Property="BorderBrush" Value="{DynamicResource ToggleButtonBorderBrushIndeterminateDisabled}" />
<Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminateDisabled}" /> <Setter Property="TextBlock.Foreground" Value="{DynamicResource ToggleButtonForegroundIndeterminateDisabled}" />

4
src/Avalonia.Themes.Fluent/ToggleSwitch.xaml

@ -6,8 +6,6 @@
<GridLength x:Key="ToggleSwitchPreContentMargin">6</GridLength> <GridLength x:Key="ToggleSwitchPreContentMargin">6</GridLength>
<GridLength x:Key="ToggleSwitchPostContentMargin">6</GridLength> <GridLength x:Key="ToggleSwitchPostContentMargin">6</GridLength>
<x:Double x:Key="ToggleSwitchThemeMinWidth">154</x:Double> <x:Double x:Key="ToggleSwitchThemeMinWidth">154</x:Double>
<x:Double x:Key="KnobOnPosition">20</x:Double>
<x:Double x:Key="KnobOffPosition">0</x:Double>
</Styles.Resources> </Styles.Resources>
<Design.PreviewWith> <Design.PreviewWith>
<StackPanel Margin="20" Width="250" Spacing="24" > <StackPanel Margin="20" Width="250" Spacing="24" >
@ -148,12 +146,10 @@
<Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOn"> <Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOn">
<Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOn}"/> <Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOn}"/>
<Setter Property="Stroke" Value="{DynamicResource ToggleSwitchKnobStrokeOn}"/>
</Style> </Style>
<Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOff"> <Style Selector="ToggleSwitch /template/ Ellipse#SwitchKnobOff">
<Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOff}"/> <Setter Property="Fill" Value="{DynamicResource ToggleSwitchKnobFillOff}"/>
<Setter Property="Stroke" Value="{DynamicResource ToggleSwitchKnobStrokeOff}"/>
</Style> </Style>
<Style Selector="ToggleSwitch:not(:dragging) /template/ Grid#MovingKnobs"> <Style Selector="ToggleSwitch:not(:dragging) /template/ Grid#MovingKnobs">

22
src/Avalonia.Themes.Fluent/Window.xaml

@ -8,16 +8,18 @@
<ControlTemplate> <ControlTemplate>
<Panel> <Panel>
<Border Name="PART_TransparencyFallback" IsHitTestVisible="False" /> <Border Name="PART_TransparencyFallback" IsHitTestVisible="False" />
<Border Background="{TemplateBinding Background}"> <Border Background="{TemplateBinding Background}" IsHitTestVisible="False" />
<VisualLayerManager> <VisualLayerManager>
<ContentPresenter Name="PART_ContentPresenter" <VisualLayerManager.ChromeOverlayLayer>
ContentTemplate="{TemplateBinding ContentTemplate}" <TitleBar />
Content="{TemplateBinding Content}" </VisualLayerManager.ChromeOverlayLayer>
Margin="{TemplateBinding Padding}" <ContentPresenter Name="PART_ContentPresenter"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" ContentTemplate="{TemplateBinding ContentTemplate}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/> Content="{TemplateBinding Content}"
</VisualLayerManager> Margin="{TemplateBinding Padding}"
</Border> HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</VisualLayerManager>
</Panel> </Panel>
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

4
src/Avalonia.Visuals/ApiCompatBaseline.txt

@ -0,0 +1,4 @@
Compat issues with assembly Avalonia.Visuals:
EnumValuesMustMatch : Enum value 'Avalonia.Media.FontStyle Avalonia.Media.FontStyle.Italic' is (System.Int32)1 in the implementation but (System.Int32)2 in the contract.
EnumValuesMustMatch : Enum value 'Avalonia.Media.FontStyle Avalonia.Media.FontStyle.Oblique' is (System.Int32)2 in the implementation but (System.Int32)1 in the contract.
Total Issues: 2

1
src/Avalonia.Visuals/Avalonia.Visuals.csproj

@ -14,4 +14,5 @@
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />
<Import Project="..\..\build\System.Memory.props" /> <Import Project="..\..\build\System.Memory.props" />
<Import Project="..\..\build\ApiDiff.props" />
</Project> </Project>

2
src/Avalonia.Visuals/Media/CharacterHit.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics;
namespace Avalonia.Media namespace Avalonia.Media
{ {
@ -9,6 +10,7 @@ namespace Avalonia.Media
/// The CharacterHit structure provides information about the index of the first /// The CharacterHit structure provides information about the index of the first
/// character that got hit as well as information about leading or trailing edge. /// character that got hit as well as information about leading or trailing edge.
/// </remarks> /// </remarks>
[DebuggerDisplay("CharacterHit({FirstCharacterIndex}, {TrailingLength})")]
public readonly struct CharacterHit : IEquatable<CharacterHit> public readonly struct CharacterHit : IEquatable<CharacterHit>
{ {
/// <summary> /// <summary>

8
src/Avalonia.Visuals/Media/FontStyle.cs

@ -11,13 +11,13 @@ namespace Avalonia.Media
Normal, Normal,
/// <summary> /// <summary>
/// An oblique font. /// An italic font.
/// </summary> /// </summary>
Oblique, Italic,
/// <summary> /// <summary>
/// An italic font. /// An oblique font.
/// </summary> /// </summary>
Italic, Oblique
} }
} }

5
src/Avalonia.Visuals/Media/RadialGradientBrush.cs

@ -30,6 +30,11 @@ namespace Avalonia.Media
AvaloniaProperty.Register<RadialGradientBrush, double>( AvaloniaProperty.Register<RadialGradientBrush, double>(
nameof(Radius), nameof(Radius),
0.5); 0.5);
static RadialGradientBrush()
{
AffectsRender<RadialGradientBrush>(CenterProperty, GradientOriginProperty, RadiusProperty);
}
/// <summary> /// <summary>
/// Gets or sets the start point for the gradient. /// Gets or sets the start point for the gradient.

79
src/Avalonia.Visuals/Media/TextFormatting/TextFormatterImpl.cs

@ -31,7 +31,8 @@ namespace Avalonia.Media.TextFormatting
case TextWrapping.WrapWithOverflow: case TextWrapping.WrapWithOverflow:
case TextWrapping.Wrap: case TextWrapping.Wrap:
{ {
textLine = PerformTextWrapping(textRuns, textRange, paragraphWidth, paragraphProperties); textLine = PerformTextWrapping(textRuns, textRange, paragraphWidth, paragraphProperties,
nextLineBreak);
break; break;
} }
default: default:
@ -118,7 +119,7 @@ namespace Avalonia.Media.TextFormatting
/// <param name="textRuns">The text run's.</param> /// <param name="textRuns">The text run's.</param>
/// <param name="length">The length to split at.</param> /// <param name="length">The length to split at.</param>
/// <returns>The split text runs.</returns> /// <returns>The split text runs.</returns>
internal static SplitTextRunsResult SplitTextRuns(IReadOnlyList<ShapedTextCharacters> textRuns, int length) internal static SplitTextRunsResult SplitTextRuns(List<ShapedTextCharacters> textRuns, int length)
{ {
var currentLength = 0; var currentLength = 0;
@ -134,13 +135,13 @@ namespace Avalonia.Media.TextFormatting
var firstCount = currentRun.GlyphRun.Characters.Length >= 1 ? i + 1 : i; var firstCount = currentRun.GlyphRun.Characters.Length >= 1 ? i + 1 : i;
var first = new ShapedTextCharacters[firstCount]; var first = new List<ShapedTextCharacters>(firstCount);
if (firstCount > 1) if (firstCount > 1)
{ {
for (var j = 0; j < i; j++) for (var j = 0; j < i; j++)
{ {
first[j] = textRuns[j]; first.Add(textRuns[j]);
} }
} }
@ -148,7 +149,7 @@ namespace Avalonia.Media.TextFormatting
if (currentLength + currentRun.GlyphRun.Characters.Length == length) if (currentLength + currentRun.GlyphRun.Characters.Length == length)
{ {
var second = new ShapedTextCharacters[secondCount]; var second = new List<ShapedTextCharacters>(secondCount);
var offset = currentRun.GlyphRun.Characters.Length > 1 ? 1 : 0; var offset = currentRun.GlyphRun.Characters.Length > 1 ? 1 : 0;
@ -156,11 +157,11 @@ namespace Avalonia.Media.TextFormatting
{ {
for (var j = 0; j < secondCount; j++) for (var j = 0; j < secondCount; j++)
{ {
second[j] = textRuns[i + j + offset]; second.Add(textRuns[i + j + offset]);
} }
} }
first[i] = currentRun; first.Add(currentRun);
return new SplitTextRunsResult(first, second); return new SplitTextRunsResult(first, second);
} }
@ -168,22 +169,22 @@ namespace Avalonia.Media.TextFormatting
{ {
secondCount++; secondCount++;
var second = new ShapedTextCharacters[secondCount]; var second = new List<ShapedTextCharacters>(secondCount);
var split = currentRun.Split(length - currentLength);
first.Add(split.First);
second.Add(split.Second);
if (secondCount > 0) if (secondCount > 0)
{ {
for (var j = 1; j < secondCount; j++) for (var j = 1; j < secondCount; j++)
{ {
second[j] = textRuns[i + j]; second.Add(textRuns[i + j]);
} }
} }
var split = currentRun.Split(length - currentLength);
first[i] = split.First;
second[0] = split.Second;
return new SplitTextRunsResult(first, second); return new SplitTextRunsResult(first, second);
} }
} }
@ -201,7 +202,7 @@ namespace Avalonia.Media.TextFormatting
/// <returns> /// <returns>
/// The formatted text runs. /// The formatted text runs.
/// </returns> /// </returns>
private static IReadOnlyList<ShapedTextCharacters> FetchTextRuns(ITextSource textSource, private static List<ShapedTextCharacters> FetchTextRuns(ITextSource textSource,
int firstTextSourceIndex, TextLineBreak previousLineBreak, out TextLineBreak nextLineBreak) int firstTextSourceIndex, TextLineBreak previousLineBreak, out TextLineBreak nextLineBreak)
{ {
nextLineBreak = default; nextLineBreak = default;
@ -212,8 +213,10 @@ namespace Avalonia.Media.TextFormatting
if (previousLineBreak != null) if (previousLineBreak != null)
{ {
foreach (var shapedCharacters in previousLineBreak.RemainingCharacters) for (var index = 0; index < previousLineBreak.RemainingCharacters.Count; index++)
{ {
var shapedCharacters = previousLineBreak.RemainingCharacters[index];
if (shapedCharacters == null) if (shapedCharacters == null)
{ {
continue; continue;
@ -225,6 +228,14 @@ namespace Avalonia.Media.TextFormatting
{ {
var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap); var splitResult = SplitTextRuns(textRuns, currentLength + runLineBreak.PositionWrap);
if (++index < previousLineBreak.RemainingCharacters.Count)
{
for (; index < previousLineBreak.RemainingCharacters.Count; index++)
{
splitResult.Second.Add(previousLineBreak.RemainingCharacters[index]);
}
}
nextLineBreak = new TextLineBreak(splitResult.Second); nextLineBreak = new TextLineBreak(splitResult.Second);
return splitResult.First; return splitResult.First;
@ -323,9 +334,10 @@ namespace Avalonia.Media.TextFormatting
/// <param name="textRange">The text range that is covered by the text runs.</param> /// <param name="textRange">The text range that is covered by the text runs.</param>
/// <param name="paragraphWidth">The paragraph width.</param> /// <param name="paragraphWidth">The paragraph width.</param>
/// <param name="paragraphProperties">The text paragraph properties.</param> /// <param name="paragraphProperties">The text paragraph properties.</param>
/// <param name="currentLineBreak">The current line break if the line was explicitly broken.</param>
/// <returns>The wrapped text line.</returns> /// <returns>The wrapped text line.</returns>
private static TextLine PerformTextWrapping(IReadOnlyList<ShapedTextCharacters> textRuns, TextRange textRange, private static TextLine PerformTextWrapping(List<ShapedTextCharacters> textRuns, TextRange textRange,
double paragraphWidth, TextParagraphProperties paragraphProperties) double paragraphWidth, TextParagraphProperties paragraphProperties, TextLineBreak currentLineBreak)
{ {
var availableWidth = paragraphWidth; var availableWidth = paragraphWidth;
var currentWidth = 0.0; var currentWidth = 0.0;
@ -388,8 +400,22 @@ namespace Avalonia.Media.TextFormatting
var textLineMetrics = TextLineMetrics.Create(splitResult.First, var textLineMetrics = TextLineMetrics.Create(splitResult.First,
new TextRange(textRange.Start, currentLength), paragraphWidth, paragraphProperties); new TextRange(textRange.Start, currentLength), paragraphWidth, paragraphProperties);
var lineBreak = splitResult.Second != null && splitResult.Second.Count > 0 ? var remainingCharacters = splitResult.Second;
new TextLineBreak(splitResult.Second) :
if (currentLineBreak?.RemainingCharacters != null)
{
if (remainingCharacters != null)
{
remainingCharacters.AddRange(currentLineBreak.RemainingCharacters);
}
else
{
remainingCharacters = new List<ShapedTextCharacters>(currentLineBreak.RemainingCharacters);
}
}
var lineBreak = remainingCharacters != null && remainingCharacters.Count > 0 ?
new TextLineBreak(remainingCharacters) :
null; null;
return new TextLineImpl(splitResult.First, textLineMetrics, lineBreak); return new TextLineImpl(splitResult.First, textLineMetrics, lineBreak);
@ -403,7 +429,10 @@ namespace Avalonia.Media.TextFormatting
} }
return new TextLineImpl(textRuns, return new TextLineImpl(textRuns,
TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties)); TextLineMetrics.Create(textRuns, textRange, paragraphWidth, paragraphProperties),
currentLineBreak?.RemainingCharacters != null ?
new TextLineBreak(currentLineBreak.RemainingCharacters) :
null);
} }
/// <summary> /// <summary>
@ -434,7 +463,7 @@ namespace Avalonia.Media.TextFormatting
internal readonly struct SplitTextRunsResult internal readonly struct SplitTextRunsResult
{ {
public SplitTextRunsResult(IReadOnlyList<ShapedTextCharacters> first, IReadOnlyList<ShapedTextCharacters> second) public SplitTextRunsResult(List<ShapedTextCharacters> first, List<ShapedTextCharacters> second)
{ {
First = first; First = first;
@ -447,7 +476,7 @@ namespace Avalonia.Media.TextFormatting
/// <value> /// <value>
/// The first text runs. /// The first text runs.
/// </value> /// </value>
public IReadOnlyList<ShapedTextCharacters> First { get; } public List<ShapedTextCharacters> First { get; }
/// <summary> /// <summary>
/// Gets the second text runs. /// Gets the second text runs.
@ -455,7 +484,7 @@ namespace Avalonia.Media.TextFormatting
/// <value> /// <value>
/// The second text runs. /// The second text runs.
/// </value> /// </value>
public IReadOnlyList<ShapedTextCharacters> Second { get; } public List<ShapedTextCharacters> Second { get; }
} }
private struct TextRunEnumerator private struct TextRunEnumerator

5
src/Avalonia.Visuals/Media/TextFormatting/TextLayout.cs

@ -183,7 +183,10 @@ namespace Avalonia.Media.TextFormatting
var glyphRun = TextShaper.Current.ShapeText(new ReadOnlySlice<char>(s_empty, startingIndex, 1), var glyphRun = TextShaper.Current.ShapeText(new ReadOnlySlice<char>(s_empty, startingIndex, 1),
properties.Typeface, properties.FontRenderingEmSize, properties.CultureInfo); properties.Typeface, properties.FontRenderingEmSize, properties.CultureInfo);
var textRuns = new[] { new ShapedTextCharacters(glyphRun, _paragraphProperties.DefaultTextRunProperties) }; var textRuns = new List<ShapedTextCharacters>
{
new ShapedTextCharacters(glyphRun, _paragraphProperties.DefaultTextRunProperties)
};
return new TextLineImpl(textRuns, return new TextLineImpl(textRuns,
TextLineMetrics.Create(textRuns, new TextRange(startingIndex, 1), MaxWidth, _paragraphProperties)); TextLineMetrics.Create(textRuns, new TextRange(startingIndex, 1), MaxWidth, _paragraphProperties));

22
src/Avalonia.Visuals/Media/TextFormatting/TextLineImpl.cs

@ -6,9 +6,9 @@ namespace Avalonia.Media.TextFormatting
{ {
internal class TextLineImpl : TextLine internal class TextLineImpl : TextLine
{ {
private readonly IReadOnlyList<ShapedTextCharacters> _textRuns; private readonly List<ShapedTextCharacters> _textRuns;
public TextLineImpl(IReadOnlyList<ShapedTextCharacters> textRuns, TextLineMetrics lineMetrics, public TextLineImpl(List<ShapedTextCharacters> textRuns, TextLineMetrics lineMetrics,
TextLineBreak lineBreak = null, bool hasCollapsed = false) TextLineBreak lineBreak = null, bool hasCollapsed = false)
{ {
_textRuns = textRuns; _textRuns = textRuns;
@ -236,7 +236,7 @@ namespace Avalonia.Media.TextFormatting
var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
if (codepointIndex >= TextRange.Start + TextRange.Length) if (codepointIndex > TextRange.End)
{ {
return false; // Cannot go forward anymore return false; // Cannot go forward anymore
} }
@ -249,11 +249,14 @@ namespace Avalonia.Media.TextFormatting
var foundCharacterHit = run.GlyphRun.FindNearestCharacterHit(characterHit.FirstCharacterIndex + characterHit.TrailingLength, out _); var foundCharacterHit = run.GlyphRun.FindNearestCharacterHit(characterHit.FirstCharacterIndex + characterHit.TrailingLength, out _);
nextCharacterHit = characterHit.TrailingLength != 0 ? var isAtEnd = foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength ==
TextRange.Length;
nextCharacterHit = isAtEnd || characterHit.TrailingLength != 0 ?
foundCharacterHit : foundCharacterHit :
new CharacterHit(foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength); new CharacterHit(foundCharacterHit.FirstCharacterIndex + foundCharacterHit.TrailingLength);
if (nextCharacterHit.FirstCharacterIndex > characterHit.FirstCharacterIndex) if (isAtEnd || nextCharacterHit.FirstCharacterIndex > characterHit.FirstCharacterIndex)
{ {
return true; return true;
} }
@ -272,6 +275,13 @@ namespace Avalonia.Media.TextFormatting
/// <returns></returns> /// <returns></returns>
private bool TryFindPreviousCharacterHit(CharacterHit characterHit, out CharacterHit previousCharacterHit) private bool TryFindPreviousCharacterHit(CharacterHit characterHit, out CharacterHit previousCharacterHit)
{ {
if (characterHit.FirstCharacterIndex == TextRange.Start)
{
previousCharacterHit = new CharacterHit(TextRange.Start);
return true;
}
previousCharacterHit = characterHit; previousCharacterHit = characterHit;
var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength; var codepointIndex = characterHit.FirstCharacterIndex + characterHit.TrailingLength;
@ -354,7 +364,7 @@ namespace Avalonia.Media.TextFormatting
return new ShapedTextCharacters(glyphRun, textRun.Properties); return new ShapedTextCharacters(glyphRun, textRun.Properties);
} }
/// <summary> /// <summary>
/// Gets the shaped width of specified shaped text characters. /// Gets the shaped width of specified shaped text characters.
/// </summary> /// </summary>

38
src/Avalonia.Visuals/Rendering/RenderLoop.cs

@ -18,6 +18,7 @@ namespace Avalonia.Rendering
{ {
private readonly IDispatcher _dispatcher; private readonly IDispatcher _dispatcher;
private List<IRenderLoopTask> _items = new List<IRenderLoopTask>(); private List<IRenderLoopTask> _items = new List<IRenderLoopTask>();
private List<IRenderLoopTask> _itemsCopy = new List<IRenderLoopTask>();
private IRenderTimer _timer; private IRenderTimer _timer;
private int _inTick; private int _inTick;
private int _inUpdate; private int _inUpdate;
@ -63,11 +64,14 @@ namespace Avalonia.Rendering
Contract.Requires<ArgumentNullException>(i != null); Contract.Requires<ArgumentNullException>(i != null);
Dispatcher.UIThread.VerifyAccess(); Dispatcher.UIThread.VerifyAccess();
_items.Add(i); lock (_items)
if (_items.Count == 1)
{ {
Timer.Tick += TimerTick; _items.Add(i);
if (_items.Count == 1)
{
Timer.Tick += TimerTick;
}
} }
} }
@ -76,12 +80,14 @@ namespace Avalonia.Rendering
{ {
Contract.Requires<ArgumentNullException>(i != null); Contract.Requires<ArgumentNullException>(i != null);
Dispatcher.UIThread.VerifyAccess(); Dispatcher.UIThread.VerifyAccess();
lock (_items)
_items.Remove(i);
if (_items.Count == 0)
{ {
Timer.Tick -= TimerTick; _items.Remove(i);
if (_items.Count == 0)
{
Timer.Tick -= TimerTick;
}
} }
} }
@ -129,10 +135,20 @@ namespace Avalonia.Rendering
}, DispatcherPriority.Render); }, DispatcherPriority.Render);
} }
for(int i = 0; i < _items.Count; i++) lock (_items)
{
_itemsCopy.Clear();
foreach (var i in _items)
_itemsCopy.Add(i);
}
for (int i = 0; i < _itemsCopy.Count; i++)
{ {
_items[i].Render(); _itemsCopy[i].Render();
} }
_itemsCopy.Clear();
} }
catch (Exception ex) catch (Exception ex)
{ {

72
src/Avalonia.Visuals/Rendering/SleepLoopRenderTimer.cs

@ -0,0 +1,72 @@
using System;
using System.Diagnostics;
using System.Threading;
namespace Avalonia.Rendering
{
public class SleepLoopRenderTimer : IRenderTimer
{
private Action<TimeSpan> _tick;
private int _count;
private readonly object _lock = new object();
private bool _running;
private readonly Stopwatch _st = Stopwatch.StartNew();
private readonly TimeSpan _timeBetweenTicks;
public SleepLoopRenderTimer(int fps)
{
_timeBetweenTicks = TimeSpan.FromSeconds(1d / fps);
}
public event Action<TimeSpan> Tick
{
add
{
lock (_lock)
{
_tick += value;
_count++;
if (_running)
return;
_running = true;
new Thread(LoopProc) { IsBackground = true }.Start();
}
}
remove
{
lock (_lock)
{
_tick -= value;
_count--;
}
}
}
void LoopProc()
{
var now = _st.Elapsed;
var lastTick = now;
while (true)
{
var timeTillNextTick = lastTick + _timeBetweenTicks - now;
if (timeTillNextTick.TotalMilliseconds > 1) Thread.Sleep(timeTillNextTick);
lock (_lock)
{
if (_count == 0)
{
_running = false;
return;
}
}
_tick?.Invoke(now);
now = _st.Elapsed;
}
}
}
}

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

Loading…
Cancel
Save