Browse Source

Merge branch 'master' into datagrid_osx_hotkeys

pull/7321/head
Max Katz 5 years ago
committed by GitHub
parent
commit
008acfd38c
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      build/SourceLink.props
  2. 1
      samples/ControlCatalog/App.xaml
  3. 21
      samples/ControlCatalog/App.xaml.cs
  4. 2
      samples/ControlCatalog/MainView.xaml.cs
  5. 16
      src/Avalonia.Animation/Animatable.cs
  6. 46
      src/Avalonia.Animation/Animation.cs
  7. 33
      src/Avalonia.Animation/AnimationInstance`1.cs
  8. 20
      src/Avalonia.Animation/AnimatorKeyFrame.cs
  9. 9
      src/Avalonia.Animation/Animators/Animator`1.cs
  10. 4
      src/Avalonia.Animation/Avalonia.Animation.csproj
  11. 2
      src/Avalonia.Animation/Clock.cs
  12. 8
      src/Avalonia.Animation/Cue.cs
  13. 8
      src/Avalonia.Animation/DisposeAnimationInstanceSubject.cs
  14. 4
      src/Avalonia.Animation/Easing/Easing.cs
  15. 4
      src/Avalonia.Animation/Easing/EasingTypeConverter.cs
  16. 2
      src/Avalonia.Animation/IAnimation.cs
  17. 4
      src/Avalonia.Animation/IAnimationSetter.cs
  18. 4
      src/Avalonia.Animation/IAnimator.cs
  19. 2
      src/Avalonia.Animation/ITransition.cs
  20. 2
      src/Avalonia.Animation/IterationCount.cs
  21. 4
      src/Avalonia.Animation/IterationCountTypeConverter.cs
  22. 4
      src/Avalonia.Animation/KeyFrame.cs
  23. 4
      src/Avalonia.Animation/KeySplineTypeConverter.cs
  24. 21
      src/Avalonia.Animation/Transition.cs
  25. 6
      src/Avalonia.Animation/TransitionInstance.cs
  26. 2
      src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs
  27. 3
      src/Avalonia.Controls/ApiCompatBaseline.txt
  28. 96
      src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs
  29. 6
      src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs
  30. 2
      src/Avalonia.Controls/LayoutTransformControl.cs
  31. 2
      src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
  32. 2
      src/Avalonia.Controls/Primitives/PopupRoot.cs
  33. 9
      src/Avalonia.Controls/TopLevel.cs
  34. 337
      src/Avalonia.Controls/ValidatingToplevel.cs
  35. 11
      src/Avalonia.Controls/Window.cs
  36. 9
      src/Avalonia.Controls/WindowBase.cs
  37. 4
      src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml
  38. 2
      src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml
  39. 1
      src/Avalonia.Dialogs/Avalonia.Dialogs.csproj
  40. 6
      src/Avalonia.Input/KeyBinding.cs
  41. 113
      src/Avalonia.Native/AvaloniaNativeMenuExporter.cs
  42. 64
      src/Avalonia.Themes.Default/Accents/Base.xaml
  43. 77
      src/Avalonia.Themes.Default/Accents/BaseDark.xaml
  44. 82
      src/Avalonia.Themes.Default/Accents/BaseLight.xaml
  45. 5
      src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj
  46. 0
      src/Avalonia.Themes.Default/Controls/AutoCompleteBox.xaml
  47. 0
      src/Avalonia.Themes.Default/Controls/Button.xaml
  48. 0
      src/Avalonia.Themes.Default/Controls/ButtonSpinner.xaml
  49. 0
      src/Avalonia.Themes.Default/Controls/Calendar.xaml
  50. 0
      src/Avalonia.Themes.Default/Controls/CalendarButton.xaml
  51. 0
      src/Avalonia.Themes.Default/Controls/CalendarDatePicker.xaml
  52. 0
      src/Avalonia.Themes.Default/Controls/CalendarDayButton.xaml
  53. 0
      src/Avalonia.Themes.Default/Controls/CalendarItem.xaml
  54. 0
      src/Avalonia.Themes.Default/Controls/CaptionButtons.xaml
  55. 0
      src/Avalonia.Themes.Default/Controls/Carousel.xaml
  56. 0
      src/Avalonia.Themes.Default/Controls/CheckBox.xaml
  57. 0
      src/Avalonia.Themes.Default/Controls/ComboBox.xaml
  58. 0
      src/Avalonia.Themes.Default/Controls/ComboBoxItem.xaml
  59. 0
      src/Avalonia.Themes.Default/Controls/ContentControl.xaml
  60. 0
      src/Avalonia.Themes.Default/Controls/ContextMenu.xaml
  61. 0
      src/Avalonia.Themes.Default/Controls/DataValidationErrors.xaml
  62. 0
      src/Avalonia.Themes.Default/Controls/DatePicker.xaml
  63. 0
      src/Avalonia.Themes.Default/Controls/EmbeddableControlRoot.xaml
  64. 0
      src/Avalonia.Themes.Default/Controls/Expander.xaml
  65. 0
      src/Avalonia.Themes.Default/Controls/FlyoutPresenter.xaml
  66. 0
      src/Avalonia.Themes.Default/Controls/FocusAdorner.xaml
  67. 0
      src/Avalonia.Themes.Default/Controls/GridSplitter.xaml
  68. 0
      src/Avalonia.Themes.Default/Controls/ItemsControl.xaml
  69. 0
      src/Avalonia.Themes.Default/Controls/Label.xaml
  70. 0
      src/Avalonia.Themes.Default/Controls/ListBox.xaml
  71. 0
      src/Avalonia.Themes.Default/Controls/ListBoxItem.xaml
  72. 0
      src/Avalonia.Themes.Default/Controls/ManagedFileChooser.xaml
  73. 0
      src/Avalonia.Themes.Default/Controls/Menu.xaml
  74. 0
      src/Avalonia.Themes.Default/Controls/MenuFlyoutPresenter.xaml
  75. 0
      src/Avalonia.Themes.Default/Controls/MenuItem.xaml
  76. 0
      src/Avalonia.Themes.Default/Controls/NativeMenuBar.xaml
  77. 0
      src/Avalonia.Themes.Default/Controls/NotificationCard.xaml
  78. 0
      src/Avalonia.Themes.Default/Controls/NumericUpDown.xaml
  79. 0
      src/Avalonia.Themes.Default/Controls/OverlayPopupHost.xaml
  80. 0
      src/Avalonia.Themes.Default/Controls/PathIcon.xaml
  81. 0
      src/Avalonia.Themes.Default/Controls/PopupRoot.xaml
  82. 0
      src/Avalonia.Themes.Default/Controls/ProgressBar.xaml
  83. 0
      src/Avalonia.Themes.Default/Controls/RadioButton.xaml
  84. 0
      src/Avalonia.Themes.Default/Controls/RepeatButton.xaml
  85. 0
      src/Avalonia.Themes.Default/Controls/ScrollBar.xaml
  86. 0
      src/Avalonia.Themes.Default/Controls/ScrollViewer.xaml
  87. 0
      src/Avalonia.Themes.Default/Controls/Separator.xaml
  88. 0
      src/Avalonia.Themes.Default/Controls/Slider.xaml
  89. 0
      src/Avalonia.Themes.Default/Controls/SplitView.xaml
  90. 0
      src/Avalonia.Themes.Default/Controls/TabControl.xaml
  91. 0
      src/Avalonia.Themes.Default/Controls/TabItem.xaml
  92. 0
      src/Avalonia.Themes.Default/Controls/TabStrip.xaml
  93. 0
      src/Avalonia.Themes.Default/Controls/TabStripItem.xaml
  94. 0
      src/Avalonia.Themes.Default/Controls/TextBox.xaml
  95. 0
      src/Avalonia.Themes.Default/Controls/TimePicker.xaml
  96. 0
      src/Avalonia.Themes.Default/Controls/TitleBar.xaml
  97. 0
      src/Avalonia.Themes.Default/Controls/ToggleButton.xaml
  98. 0
      src/Avalonia.Themes.Default/Controls/ToggleSwitch.xaml
  99. 0
      src/Avalonia.Themes.Default/Controls/ToolTip.xaml
  100. 0
      src/Avalonia.Themes.Default/Controls/TreeView.xaml

5
build/SourceLink.props

@ -3,7 +3,6 @@
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<IncludeSymbols>false</IncludeSymbols> <IncludeSymbols>false</IncludeSymbols>
<EmbedUntrackedSources>true</EmbedUntrackedSources> <EmbedUntrackedSources>true</EmbedUntrackedSources>
<DebugType>embedded</DebugType>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
</PropertyGroup> </PropertyGroup>
@ -15,6 +14,10 @@
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild> <ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<DebugType Condition="$(ContinuousIntegrationBuild) == 'true'">embedded</DebugType>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
</ItemGroup> </ItemGroup>

1
samples/ControlCatalog/App.xaml

@ -3,6 +3,7 @@
xmlns:vm="using:ControlCatalog.ViewModels" xmlns:vm="using:ControlCatalog.ViewModels"
x:DataType="vm:ApplicationViewModel" x:DataType="vm:ApplicationViewModel"
x:CompileBindings="True" x:CompileBindings="True"
Name="Avalonia ControlCatalog"
x:Class="ControlCatalog.App"> x:Class="ControlCatalog.App">
<Application.Styles> <Application.Styles>
<Style Selector="TextBlock.h1, TextBlock.h2, TextBlock.h3"> <Style Selector="TextBlock.h1, TextBlock.h2, TextBlock.h3">

21
samples/ControlCatalog/App.xaml.cs

@ -5,6 +5,7 @@ using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling; using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.Themes.Default;
using Avalonia.Themes.Fluent; using Avalonia.Themes.Fluent;
using ControlCatalog.ViewModels; using ControlCatalog.ViewModels;
@ -29,6 +30,8 @@ namespace ControlCatalog
public static FluentTheme Fluent = new FluentTheme(new Uri("avares://ControlCatalog/Styles")); public static FluentTheme Fluent = new FluentTheme(new Uri("avares://ControlCatalog/Styles"));
public static SimpleTheme Default = new SimpleTheme(new Uri("avares://ControlCatalog/Styles"));
public static Styles DefaultLight = new Styles public static Styles DefaultLight = new Styles
{ {
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
@ -43,14 +46,7 @@ namespace ControlCatalog
{ {
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml") Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml")
}, },
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) Default
{
Source = new Uri("avares://Avalonia.Themes.Default/Accents/BaseLight.xaml")
},
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
}
}; };
public static Styles DefaultDark = new Styles public static Styles DefaultDark = new Styles
@ -67,14 +63,7 @@ namespace ControlCatalog
{ {
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml") Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml")
}, },
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog")) Default
{
Source = new Uri("avares://Avalonia.Themes.Default/Accents/BaseDark.xaml")
},
new StyleInclude(new Uri("resm:Styles?assembly=ControlCatalog"))
{
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
}
}; };
public override void Initialize() public override void Initialize()

2
samples/ControlCatalog/MainView.xaml.cs

@ -63,11 +63,13 @@ namespace ControlCatalog
} }
else if (theme == CatalogTheme.DefaultLight) else if (theme == CatalogTheme.DefaultLight)
{ {
App.Default.Mode = Avalonia.Themes.Default.SimpleThemeMode.Light;
Application.Current.Styles[0] = App.DefaultLight; Application.Current.Styles[0] = App.DefaultLight;
Application.Current.Styles[1] = App.DataGridDefault; Application.Current.Styles[1] = App.DataGridDefault;
} }
else if (theme == CatalogTheme.DefaultDark) else if (theme == CatalogTheme.DefaultDark)
{ {
App.Default.Mode = Avalonia.Themes.Default.SimpleThemeMode.Dark;
Application.Current.Styles[0] = App.DefaultDark; Application.Current.Styles[0] = App.DefaultDark;
Application.Current.Styles[1] = App.DataGridDefault; Application.Current.Styles[1] = App.DataGridDefault;
} }

16
src/Avalonia.Animation/Animatable.cs

@ -157,7 +157,7 @@ namespace Avalonia.Animation
state.Instance?.Dispose(); state.Instance?.Dispose();
state.Instance = transition.Apply( state.Instance = transition.Apply(
this, this,
Clock ?? AvaloniaLocator.Current.GetService<IGlobalClock>(), Clock ?? AvaloniaLocator.Current.GetRequiredService<IGlobalClock>(),
oldValue, oldValue,
newValue); newValue);
return; return;
@ -169,7 +169,7 @@ namespace Avalonia.Animation
base.OnPropertyChangedCore(change); base.OnPropertyChangedCore(change);
} }
private void TransitionsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e) private void TransitionsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
{ {
if (!_transitionsEnabled) if (!_transitionsEnabled)
{ {
@ -179,14 +179,14 @@ namespace Avalonia.Animation
switch (e.Action) switch (e.Action)
{ {
case NotifyCollectionChangedAction.Add: case NotifyCollectionChangedAction.Add:
AddTransitions(e.NewItems); AddTransitions(e.NewItems!);
break; break;
case NotifyCollectionChangedAction.Remove: case NotifyCollectionChangedAction.Remove:
RemoveTransitions(e.OldItems); RemoveTransitions(e.OldItems!);
break; break;
case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Replace:
RemoveTransitions(e.OldItems); RemoveTransitions(e.OldItems!);
AddTransitions(e.NewItems); AddTransitions(e.NewItems!);
break; break;
case NotifyCollectionChangedAction.Reset: case NotifyCollectionChangedAction.Reset:
throw new NotSupportedException("Transitions collection cannot be reset."); throw new NotSupportedException("Transitions collection cannot be reset.");
@ -204,7 +204,7 @@ namespace Avalonia.Animation
for (var i = 0; i < items.Count; ++i) for (var i = 0; i < items.Count; ++i)
{ {
var t = (ITransition)items[i]; var t = (ITransition)items[i]!;
_transitionState.Add(t, new TransitionState _transitionState.Add(t, new TransitionState
{ {
@ -222,7 +222,7 @@ namespace Avalonia.Animation
for (var i = 0; i < items.Count; ++i) for (var i = 0; i < items.Count; ++i)
{ {
var t = (ITransition)items[i]; var t = (ITransition)items[i]!;
if (_transitionState.TryGetValue(t, out var state)) if (_transitionState.TryGetValue(t, out var state))
{ {

46
src/Avalonia.Animation/Animation.cs

@ -203,7 +203,7 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <param name="setter">The animation setter.</param> /// <param name="setter">The animation setter.</param>
/// <returns>The property animator type.</returns> /// <returns>The property animator type.</returns>
public static Type GetAnimator(IAnimationSetter setter) public static Type? GetAnimator(IAnimationSetter setter)
{ {
if (s_animators.TryGetValue(setter, out var type)) if (s_animators.TryGetValue(setter, out var type))
{ {
@ -254,7 +254,7 @@ namespace Avalonia.Animation
Animators.Insert(0, (condition, typeof(TAnimator))); Animators.Insert(0, (condition, typeof(TAnimator)));
} }
private static Type GetAnimatorType(AvaloniaProperty property) private static Type? GetAnimatorType(AvaloniaProperty property)
{ {
foreach (var (condition, type) in Animators) foreach (var (condition, type) in Animators)
{ {
@ -276,6 +276,11 @@ namespace Avalonia.Animation
{ {
foreach (var setter in keyframe.Setters) foreach (var setter in keyframe.Setters)
{ {
if (setter.Property is null)
{
throw new InvalidOperationException("No Setter property assigned.");
}
var handler = Animation.GetAnimator(setter) ?? GetAnimatorType(setter.Property); var handler = Animation.GetAnimator(setter) ?? GetAnimatorType(setter.Property);
if (handler == null) if (handler == null)
@ -305,7 +310,7 @@ namespace Avalonia.Animation
foreach (var (handlerType, property) in handlerList) foreach (var (handlerType, property) in handlerList)
{ {
var newInstance = (IAnimator)Activator.CreateInstance(handlerType); var newInstance = (IAnimator)Activator.CreateInstance(handlerType)!;
newInstance.Property = property; newInstance.Property = property;
newAnimatorInstances.Add(newInstance); newAnimatorInstances.Add(newInstance);
} }
@ -321,32 +326,43 @@ namespace Avalonia.Animation
} }
/// <inheritdoc/> /// <inheritdoc/>
public IDisposable Apply(Animatable control, IClock clock, IObservable<bool> match, Action onComplete) public IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
{ {
var (animators, subscriptions) = InterpretKeyframes(control); var (animators, subscriptions) = InterpretKeyframes(control);
if (animators.Count == 1) if (animators.Count == 1)
{ {
subscriptions.Add(animators[0].Apply(this, control, clock, match, onComplete)); var subscription = animators[0].Apply(this, control, clock, match, onComplete);
if (subscription is not null)
{
subscriptions.Add(subscription);
}
} }
else else
{ {
var completionTasks = onComplete != null ? new List<Task>() : null; var completionTasks = onComplete != null ? new List<Task>() : null;
foreach (IAnimator animator in animators) foreach (IAnimator animator in animators)
{ {
Action animatorOnComplete = null; Action? animatorOnComplete = null;
if (onComplete != null) if (onComplete != null)
{ {
var tcs = new TaskCompletionSource<object>(); var tcs = new TaskCompletionSource<object?>();
animatorOnComplete = () => tcs.SetResult(null); animatorOnComplete = () => tcs.SetResult(null);
completionTasks.Add(tcs.Task); completionTasks!.Add(tcs.Task);
}
var subscription = animator.Apply(this, control, clock, match, animatorOnComplete);
if (subscription is not null)
{
subscriptions.Add(subscription);
} }
subscriptions.Add(animator.Apply(this, control, clock, match, animatorOnComplete));
} }
if (onComplete != null) if (onComplete != null)
{ {
Task.WhenAll(completionTasks).ContinueWith( Task.WhenAll(completionTasks!).ContinueWith(
(_, state) => ((Action)state).Invoke(), (_, state) => ((Action)state!).Invoke(),
onComplete); onComplete);
} }
} }
@ -354,25 +370,25 @@ namespace Avalonia.Animation
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task RunAsync(Animatable control, IClock clock = null) public Task RunAsync(Animatable control, IClock? clock = null)
{ {
return RunAsync(control, clock, default); return RunAsync(control, clock, default);
} }
/// <inheritdoc/> /// <inheritdoc/>
public Task RunAsync(Animatable control, IClock clock = null, CancellationToken cancellationToken = default) public Task RunAsync(Animatable control, IClock? clock = null, CancellationToken cancellationToken = default)
{ {
if (cancellationToken.IsCancellationRequested) if (cancellationToken.IsCancellationRequested)
{ {
return Task.CompletedTask; return Task.CompletedTask;
} }
var run = new TaskCompletionSource<object>(); var run = new TaskCompletionSource<object?>();
if (this.IterationCount == IterationCount.Infinite) if (this.IterationCount == IterationCount.Infinite)
run.SetException(new InvalidOperationException("Looping animations must not use the Run method.")); run.SetException(new InvalidOperationException("Looping animations must not use the Run method."));
IDisposable subscriptions = null, cancellation = null; IDisposable? subscriptions = null, cancellation = null;
subscriptions = this.Apply(control, clock, Observable.Return(true), () => subscriptions = this.Apply(control, clock, Observable.Return(true), () =>
{ {
run.TrySetResult(null); run.TrySetResult(null);

33
src/Avalonia.Animation/AnimationInstance`1.cs

@ -31,15 +31,15 @@ namespace Avalonia.Animation
private TimeSpan _initialDelay; private TimeSpan _initialDelay;
private TimeSpan _iterationDelay; private TimeSpan _iterationDelay;
private TimeSpan _duration; private TimeSpan _duration;
private Easings.Easing _easeFunc; private Easings.Easing? _easeFunc;
private Action _onCompleteAction; private Action? _onCompleteAction;
private Func<double, T, T> _interpolator; private Func<double, T, T> _interpolator;
private IDisposable _timerSub; private IDisposable? _timerSub;
private readonly IClock _baseClock; private readonly IClock _baseClock;
private IClock _clock; private IClock? _clock;
private EventHandler<AvaloniaPropertyChangedEventArgs> _propertyChangedDelegate; private EventHandler<AvaloniaPropertyChangedEventArgs>? _propertyChangedDelegate;
public AnimationInstance(Animation animation, Animatable control, Animator<T> animator, IClock baseClock, Action OnComplete, Func<double, T, T> Interpolator) public AnimationInstance(Animation animation, Animatable control, Animator<T> animator, IClock baseClock, Action? OnComplete, Func<double, T, T> Interpolator)
{ {
_animator = animator; _animator = animator;
_animation = animation; _animation = animation;
@ -47,6 +47,9 @@ namespace Avalonia.Animation
_onCompleteAction = OnComplete; _onCompleteAction = OnComplete;
_interpolator = Interpolator; _interpolator = Interpolator;
_baseClock = baseClock; _baseClock = baseClock;
_lastInterpValue = default!;
_firstKFValue = default!;
_neutralValue = default!;
FetchProperties(); FetchProperties();
} }
@ -82,7 +85,7 @@ namespace Avalonia.Animation
_targetControl.PropertyChanged -= _propertyChangedDelegate; _targetControl.PropertyChanged -= _propertyChangedDelegate;
_timerSub?.Dispose(); _timerSub?.Dispose();
_clock.PlayState = PlayState.Stop; _clock!.PlayState = PlayState.Stop;
} }
protected override void Subscribed() protected override void Subscribed()
@ -108,6 +111,8 @@ namespace Avalonia.Animation
private void ApplyFinalFill() private void ApplyFinalFill()
{ {
if (_animator.Property is null)
throw new InvalidOperationException("Animator has no property specified.");
if (_fillMode == FillMode.Forward || _fillMode == FillMode.Both) if (_fillMode == FillMode.Forward || _fillMode == FillMode.Both)
_targetControl.SetValue(_animator.Property, _lastInterpValue, BindingPriority.LocalValue); _targetControl.SetValue(_animator.Property, _lastInterpValue, BindingPriority.LocalValue);
} }
@ -130,12 +135,12 @@ namespace Avalonia.Animation
private void DoPlayStates() private void DoPlayStates()
{ {
if (_clock.PlayState == PlayState.Stop || _baseClock.PlayState == PlayState.Stop) if (_clock!.PlayState == PlayState.Stop || _baseClock.PlayState == PlayState.Stop)
DoComplete(); DoComplete();
if (!_gotFirstKFValue) if (!_gotFirstKFValue)
{ {
_firstKFValue = (T)_animator.First().Value; _firstKFValue = (T)_animator.First().Value!;
_gotFirstKFValue = true; _gotFirstKFValue = true;
} }
} }
@ -169,7 +174,7 @@ namespace Avalonia.Animation
// and snap the last iteration value to exact values. // and snap the last iteration value to exact values.
if ((_currentIteration + 1) > _iterationCount) if ((_currentIteration + 1) > _iterationCount)
{ {
var easedTime = _easeFunc.Ease(_playbackReversed ? 0.0 : 1.0); var easedTime = _easeFunc!.Ease(_playbackReversed ? 0.0 : 1.0);
_lastInterpValue = _interpolator(easedTime, _neutralValue); _lastInterpValue = _interpolator(easedTime, _neutralValue);
DoComplete(); DoComplete();
} }
@ -203,7 +208,7 @@ namespace Avalonia.Animation
normalizedTime = 1 - normalizedTime; normalizedTime = 1 - normalizedTime;
// Ease and interpolate // Ease and interpolate
var easedTime = _easeFunc.Ease(normalizedTime); var easedTime = _easeFunc!.Ease(normalizedTime);
_lastInterpValue = _interpolator(easedTime, _neutralValue); _lastInterpValue = _interpolator(easedTime, _neutralValue);
PublishNext(_lastInterpValue); PublishNext(_lastInterpValue);
@ -223,14 +228,14 @@ namespace Avalonia.Animation
private void UpdateNeutralValue() private void UpdateNeutralValue()
{ {
var property = _animator.Property; var property = _animator.Property ?? throw new InvalidOperationException("Animator has no property specified.");
var baseValue = _targetControl.GetBaseValue(property, BindingPriority.LocalValue); var baseValue = _targetControl.GetBaseValue(property, BindingPriority.LocalValue);
_neutralValue = baseValue != AvaloniaProperty.UnsetValue ? _neutralValue = baseValue != AvaloniaProperty.UnsetValue ?
(T)baseValue : (T)_targetControl.GetValue(property); (T)baseValue! : (T)_targetControl.GetValue(property)!;
} }
private void ControlPropertyChanged(object sender, AvaloniaPropertyChangedEventArgs e) private void ControlPropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
{ {
if (e.Property == _animator.Property && e.Priority > BindingPriority.Animation) if (e.Property == _animator.Property && e.Priority > BindingPriority.Animation)
{ {

20
src/Avalonia.Animation/AnimatorKeyFrame.cs

@ -12,22 +12,22 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class AnimatorKeyFrame : AvaloniaObject public class AnimatorKeyFrame : AvaloniaObject
{ {
public static readonly DirectProperty<AnimatorKeyFrame, object> ValueProperty = public static readonly DirectProperty<AnimatorKeyFrame, object?> ValueProperty =
AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object>(nameof(Value), k => k.Value, (k, v) => k.Value = v); AvaloniaProperty.RegisterDirect<AnimatorKeyFrame, object?>(nameof(Value), k => k.Value, (k, v) => k.Value = v);
public AnimatorKeyFrame() public AnimatorKeyFrame()
{ {
} }
public AnimatorKeyFrame(Type animatorType, Cue cue) public AnimatorKeyFrame(Type? animatorType, Cue cue)
{ {
AnimatorType = animatorType; AnimatorType = animatorType;
Cue = cue; Cue = cue;
KeySpline = null; KeySpline = null;
} }
public AnimatorKeyFrame(Type animatorType, Cue cue, KeySpline keySpline) public AnimatorKeyFrame(Type? animatorType, Cue cue, KeySpline? keySpline)
{ {
AnimatorType = animatorType; AnimatorType = animatorType;
Cue = cue; Cue = cue;
@ -35,14 +35,14 @@ namespace Avalonia.Animation
} }
internal bool isNeutral; internal bool isNeutral;
public Type AnimatorType { get; } public Type? AnimatorType { get; }
public Cue Cue { get; } public Cue Cue { get; }
public KeySpline KeySpline { get; } public KeySpline? KeySpline { get; }
public AvaloniaProperty Property { get; private set; } public AvaloniaProperty? Property { get; private set; }
private object _value; private object? _value;
public object Value public object? Value
{ {
get => _value; get => _value;
set => SetAndRaise(ValueProperty, ref _value, value); set => SetAndRaise(ValueProperty, ref _value, value);
@ -80,7 +80,7 @@ namespace Avalonia.Animation
throw new InvalidCastException($"KeyFrame value doesnt match property type."); throw new InvalidCastException($"KeyFrame value doesnt match property type.");
} }
return (T)typeConv.ConvertTo(Value, typeof(T)); return (T)typeConv.ConvertTo(Value, typeof(T))!;
} }
} }
} }

9
src/Avalonia.Animation/Animators/Animator`1.cs

@ -24,7 +24,7 @@ namespace Avalonia.Animation.Animators
/// <summary> /// <summary>
/// Gets or sets the target property for the keyframe. /// Gets or sets the target property for the keyframe.
/// </summary> /// </summary>
public AvaloniaProperty Property { get; set; } public AvaloniaProperty? Property { get; set; }
public Animator() public Animator()
{ {
@ -33,7 +33,7 @@ namespace Avalonia.Animation.Animators
} }
/// <inheritdoc/> /// <inheritdoc/>
public virtual IDisposable Apply(Animation animation, Animatable control, IClock clock, IObservable<bool> match, Action onComplete) public virtual IDisposable? Apply(Animation animation, Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete)
{ {
if (!_isVerifiedAndConverted) if (!_isVerifiedAndConverted)
VerifyConvertKeyFrames(); VerifyConvertKeyFrames();
@ -106,13 +106,16 @@ namespace Avalonia.Animation.Animators
public virtual IDisposable BindAnimation(Animatable control, IObservable<T> instance) public virtual IDisposable BindAnimation(Animatable control, IObservable<T> instance)
{ {
if (Property is null)
throw new InvalidOperationException("Animator has no property specified.");
return control.Bind((AvaloniaProperty<T>)Property, instance, BindingPriority.Animation); return control.Bind((AvaloniaProperty<T>)Property, instance, BindingPriority.Animation);
} }
/// <summary> /// <summary>
/// Runs the KeyFrames Animation. /// Runs the KeyFrames Animation.
/// </summary> /// </summary>
internal IDisposable Run(Animation animation, Animatable control, IClock clock, Action onComplete) internal IDisposable Run(Animation animation, Animatable control, IClock? clock, Action? onComplete)
{ {
var instance = new AnimationInstance<T>( var instance = new AnimationInstance<T>(
animation, animation,

4
src/Avalonia.Animation/Avalonia.Animation.csproj

@ -2,9 +2,13 @@
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks> <TargetFrameworks>net6.0;netstandard2.0</TargetFrameworks>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<Compile Include="..\Avalonia.Base\Metadata\NullableAttributes.cs" Link="NullableAttributes.cs" />
</ItemGroup>
<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" /> <Import Project="..\..\build\ApiDiff.props" />
<Import Project="..\..\build\NullableEnable.props" />
</Project> </Project>

2
src/Avalonia.Animation/Clock.cs

@ -4,7 +4,7 @@ namespace Avalonia.Animation
{ {
public class Clock : ClockBase public class Clock : ClockBase
{ {
public static IClock GlobalClock => AvaloniaLocator.Current.GetService<IGlobalClock>(); public static IClock GlobalClock => AvaloniaLocator.Current.GetRequiredService<IGlobalClock>();
private readonly IDisposable _parentSubscription; private readonly IDisposable _parentSubscription;

8
src/Avalonia.Animation/Cue.cs

@ -30,7 +30,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Parses a string to a <see cref="Cue"/> object. /// Parses a string to a <see cref="Cue"/> object.
/// </summary> /// </summary>
public static Cue Parse(string value, CultureInfo culture) public static Cue Parse(string value, CultureInfo? culture)
{ {
string v = value; string v = value;
@ -72,14 +72,14 @@ namespace Avalonia.Animation
public class CueTypeConverter : TypeConverter public class CueTypeConverter : TypeConverter
{ {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{ {
return sourceType == typeof(string); return sourceType == typeof(string);
} }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{ {
return Cue.Parse((string)value, culture); return Cue.Parse((string)value, culture);
} }
} }
} }

8
src/Avalonia.Animation/DisposeAnimationInstanceSubject.cs

@ -8,15 +8,15 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
internal class DisposeAnimationInstanceSubject<T> : IObserver<bool>, IDisposable internal class DisposeAnimationInstanceSubject<T> : IObserver<bool>, IDisposable
{ {
private IDisposable _lastInstance; private IDisposable? _lastInstance;
private bool _lastMatch; private bool _lastMatch;
private Animator<T> _animator; private Animator<T> _animator;
private Animation _animation; private Animation _animation;
private Animatable _control; private Animatable _control;
private Action _onComplete; private Action? _onComplete;
private IClock _clock; private IClock? _clock;
public DisposeAnimationInstanceSubject(Animator<T> animator, Animation animation, Animatable control, IClock clock, Action onComplete) public DisposeAnimationInstanceSubject(Animator<T> animator, Animation animation, Animatable control, IClock? clock, Action? onComplete)
{ {
this._animator = animator; this._animator = animator;
this._animation = animation; this._animation = animation;

4
src/Avalonia.Animation/Easing/Easing.cs

@ -15,7 +15,7 @@ namespace Avalonia.Animation.Easings
/// <inheritdoc/> /// <inheritdoc/>
public abstract double Ease(double progress); public abstract double Ease(double progress);
static Dictionary<string, Type> _easingTypes; static Dictionary<string, Type>? _easingTypes;
static readonly Type s_thisType = typeof(Easing); static readonly Type s_thisType = typeof(Easing);
@ -48,7 +48,7 @@ namespace Avalonia.Animation.Easings
if (_easingTypes.ContainsKey(e)) if (_easingTypes.ContainsKey(e))
{ {
var type = _easingTypes[e]; var type = _easingTypes[e];
return (Easing)Activator.CreateInstance(type); return (Easing)Activator.CreateInstance(type)!;
} }
else else
{ {

4
src/Avalonia.Animation/Easing/EasingTypeConverter.cs

@ -6,12 +6,12 @@ namespace Avalonia.Animation.Easings
{ {
public class EasingTypeConverter : TypeConverter public class EasingTypeConverter : TypeConverter
{ {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{ {
return sourceType == typeof(string); return sourceType == typeof(string);
} }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{ {
return Easing.Parse((string)value); return Easing.Parse((string)value);
} }

2
src/Avalonia.Animation/IAnimation.cs

@ -12,7 +12,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Apply the animation to the specified control and run it when <paramref name="match" /> produces <c>true</c>. /// Apply the animation to the specified control and run it when <paramref name="match" /> produces <c>true</c>.
/// </summary> /// </summary>
IDisposable Apply(Animatable control, IClock clock, IObservable<bool> match, Action onComplete = null); IDisposable Apply(Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete = null);
/// <summary> /// <summary>
/// Run the animation on the specified control. /// Run the animation on the specified control.

4
src/Avalonia.Animation/IAnimationSetter.cs

@ -2,7 +2,7 @@ namespace Avalonia.Animation
{ {
public interface IAnimationSetter public interface IAnimationSetter
{ {
AvaloniaProperty Property { get; set; } AvaloniaProperty? Property { get; set; }
object Value { get; set; } object? Value { get; set; }
} }
} }

4
src/Avalonia.Animation/IAnimator.cs

@ -11,11 +11,11 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// The target property. /// The target property.
/// </summary> /// </summary>
AvaloniaProperty Property {get; set;} AvaloniaProperty? Property {get; set;}
/// <summary> /// <summary>
/// Applies the current KeyFrame group to the specified control. /// Applies the current KeyFrame group to the specified control.
/// </summary> /// </summary>
IDisposable Apply(Animation animation, Animatable control, IClock clock, IObservable<bool> match, Action onComplete); IDisposable? Apply(Animation animation, Animatable control, IClock? clock, IObservable<bool> match, Action? onComplete);
} }
} }

2
src/Avalonia.Animation/ITransition.cs

@ -10,7 +10,7 @@ namespace Avalonia.Animation
/// <summary> /// <summary>
/// Applies the transition to the specified <see cref="Animatable"/>. /// Applies the transition to the specified <see cref="Animatable"/>.
/// </summary> /// </summary>
IDisposable Apply(Animatable control, IClock clock, object oldValue, object newValue); IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue);
/// <summary> /// <summary>
/// Gets the property to be animated. /// Gets the property to be animated.

2
src/Avalonia.Animation/IterationCount.cs

@ -97,7 +97,7 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
/// <param name="o">The object with which to test equality.</param> /// <param name="o">The object with which to test equality.</param>
/// <returns>True if the objects are equal, otherwise false.</returns> /// <returns>True if the objects are equal, otherwise false.</returns>
public override bool Equals(object o) public override bool Equals(object? o)
{ {
if (o == null) if (o == null)
{ {

4
src/Avalonia.Animation/IterationCountTypeConverter.cs

@ -6,12 +6,12 @@ namespace Avalonia.Animation
{ {
public class IterationCountTypeConverter : TypeConverter public class IterationCountTypeConverter : TypeConverter
{ {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{ {
return sourceType == typeof(string); return sourceType == typeof(string);
} }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{ {
return IterationCount.Parse((string)value); return IterationCount.Parse((string)value);
} }

4
src/Avalonia.Animation/KeyFrame.cs

@ -19,7 +19,7 @@ namespace Avalonia.Animation
{ {
private TimeSpan _ktimeSpan; private TimeSpan _ktimeSpan;
private Cue _kCue; private Cue _kCue;
private KeySpline _kKeySpline; private KeySpline? _kKeySpline;
public KeyFrame() public KeyFrame()
{ {
@ -79,7 +79,7 @@ namespace Avalonia.Animation
/// Gets or sets the KeySpline of this <see cref="KeyFrame"/>. /// Gets or sets the KeySpline of this <see cref="KeyFrame"/>.
/// </summary> /// </summary>
/// <value>The key spline.</value> /// <value>The key spline.</value>
public KeySpline KeySpline public KeySpline? KeySpline
{ {
get get
{ {

4
src/Avalonia.Animation/KeySplineTypeConverter.cs

@ -12,12 +12,12 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public class KeySplineTypeConverter : TypeConverter public class KeySplineTypeConverter : TypeConverter
{ {
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) public override bool CanConvertFrom(ITypeDescriptorContext? context, Type sourceType)
{ {
return sourceType == typeof(string); return sourceType == typeof(string);
} }
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) public override object ConvertFrom(ITypeDescriptorContext? context, CultureInfo? culture, object value)
{ {
return KeySpline.Parse((string)value, CultureInfo.InvariantCulture); return KeySpline.Parse((string)value, CultureInfo.InvariantCulture);
} }

21
src/Avalonia.Animation/Transition.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using Avalonia.Animation.Easings; using Avalonia.Animation.Easings;
namespace Avalonia.Animation namespace Avalonia.Animation
@ -8,7 +9,7 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
public abstract class Transition<T> : AvaloniaObject, ITransition public abstract class Transition<T> : AvaloniaObject, ITransition
{ {
private AvaloniaProperty _prop; private AvaloniaProperty? _prop;
/// <summary> /// <summary>
/// Gets or sets the duration of the transition. /// Gets or sets the duration of the transition.
@ -26,7 +27,8 @@ namespace Avalonia.Animation
public Easing Easing { get; set; } = new LinearEasing(); public Easing Easing { get; set; } = new LinearEasing();
/// <inheritdocs/> /// <inheritdocs/>
public AvaloniaProperty Property [DisallowNull]
public AvaloniaProperty? Property
{ {
get get
{ {
@ -42,16 +44,25 @@ namespace Avalonia.Animation
} }
} }
AvaloniaProperty ITransition.Property
{
get => Property ?? throw new InvalidOperationException("Transition has no property specified.");
set => Property = value;
}
/// <summary> /// <summary>
/// Apply interpolation to the property. /// Apply interpolation to the property.
/// </summary> /// </summary>
public abstract IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue); public abstract IObservable<T> DoTransition(IObservable<double> progress, T oldValue, T newValue);
/// <inheritdocs/> /// <inheritdocs/>
public virtual IDisposable Apply(Animatable control, IClock clock, object oldValue, object newValue) public virtual IDisposable Apply(Animatable control, IClock clock, object? oldValue, object? newValue)
{ {
var transition = DoTransition(new TransitionInstance(clock, Delay, Duration), (T)oldValue, (T)newValue); if (Property is null)
throw new InvalidOperationException("Transition has no property specified.");
var transition = DoTransition(new TransitionInstance(clock, Delay, Duration), (T)oldValue!, (T)newValue!);
return control.Bind<T>((AvaloniaProperty<T>)Property, transition, Data.BindingPriority.Animation); return control.Bind<T>((AvaloniaProperty<T>)Property, transition, Data.BindingPriority.Animation);
} }
} }
} }

6
src/Avalonia.Animation/TransitionInstance.cs

@ -10,11 +10,11 @@ namespace Avalonia.Animation
/// </summary> /// </summary>
internal class TransitionInstance : SingleSubscriberObservableBase<double>, IObserver<TimeSpan> internal class TransitionInstance : SingleSubscriberObservableBase<double>, IObserver<TimeSpan>
{ {
private IDisposable _timerSubscription; private IDisposable? _timerSubscription;
private TimeSpan _delay; private TimeSpan _delay;
private TimeSpan _duration; private TimeSpan _duration;
private readonly IClock _baseClock; private readonly IClock _baseClock;
private TransitionClock _clock; private TransitionClock? _clock;
public TransitionInstance(IClock clock, TimeSpan delay, TimeSpan duration) public TransitionInstance(IClock clock, TimeSpan delay, TimeSpan duration)
{ {
@ -67,7 +67,7 @@ namespace Avalonia.Animation
protected override void Unsubscribed() protected override void Unsubscribed()
{ {
_timerSubscription?.Dispose(); _timerSubscription?.Dispose();
_clock.PlayState = PlayState.Stop; _clock!.PlayState = PlayState.Stop;
} }
protected override void Subscribed() protected override void Subscribed()

2
src/Avalonia.Base/Threading/AvaloniaSynchronizationContext.cs

@ -30,7 +30,7 @@ namespace Avalonia.Threading
/// <inheritdoc/> /// <inheritdoc/>
public override void Post(SendOrPostCallback d, object? state) public override void Post(SendOrPostCallback d, object? state)
{ {
Dispatcher.UIThread.Post(() => d(state), DispatcherPriority.Send); Dispatcher.UIThread.Post(() => d(state), DispatcherPriority.Background);
} }
/// <inheritdoc/> /// <inheritdoc/>

3
src/Avalonia.Controls/ApiCompatBaseline.txt

@ -36,6 +36,7 @@ CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.WindowBase' does not i
InterfacesShouldHaveSameMembers : Interface member 'public System.EventHandler<Avalonia.Controls.ApplicationLifetimes.ShutdownRequestedEventArgs> Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.ShutdownRequested' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public System.EventHandler<Avalonia.Controls.ApplicationLifetimes.ShutdownRequestedEventArgs> Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.ShutdownRequested' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.add_ShutdownRequested(System.EventHandler<Avalonia.Controls.ApplicationLifetimes.ShutdownRequestedEventArgs>)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.add_ShutdownRequested(System.EventHandler<Avalonia.Controls.ApplicationLifetimes.ShutdownRequestedEventArgs>)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.remove_ShutdownRequested(System.EventHandler<Avalonia.Controls.ApplicationLifetimes.ShutdownRequestedEventArgs>)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.remove_ShutdownRequested(System.EventHandler<Avalonia.Controls.ApplicationLifetimes.ShutdownRequestedEventArgs>)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public System.Boolean Avalonia.Controls.ApplicationLifetimes.IClassicDesktopStyleApplicationLifetime.TryShutdown(System.Int32)' is present in the implementation but not in the contract.
CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Embedding.EmbeddableControlRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber<Avalonia.Controls.ResourcesChangedEventArgs>' in the implementation but it does in the contract. CannotRemoveBaseTypeOrInterface : Type 'Avalonia.Controls.Embedding.EmbeddableControlRoot' does not implement interface 'Avalonia.Utilities.IWeakSubscriber<Avalonia.Controls.ResourcesChangedEventArgs>' in the implementation but it does in the contract.
MembersMustExist : Member 'public System.Action<Avalonia.Size> Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.get()' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public System.Action<Avalonia.Size> Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.get()' does not exist in the implementation but it does exist in the contract.
MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.set(System.Action<Avalonia.Size>)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Controls.Embedding.Offscreen.OffscreenTopLevelImplBase.Resized.set(System.Action<Avalonia.Size>)' does not exist in the implementation but it does exist in the contract.
@ -62,4 +63,4 @@ InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platfor
MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract. MembersMustExist : Member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size)' does not exist in the implementation but it does exist in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public void Avalonia.Platform.IWindowImpl.Resize(Avalonia.Size, Avalonia.Platform.PlatformResizeReason)' is present in the implementation but not in the contract.
InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract. InterfacesShouldHaveSameMembers : Interface member 'public Avalonia.Platform.ITrayIconImpl Avalonia.Platform.IWindowingPlatform.CreateTrayIcon()' is present in the implementation but not in the contract.
Total Issues: 63 Total Issues: 64

96
src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs

@ -76,36 +76,21 @@ namespace Avalonia.Controls.ApplicationLifetimes
return; return;
if (ShutdownMode == ShutdownMode.OnLastWindowClose && _windows.Count == 0) if (ShutdownMode == ShutdownMode.OnLastWindowClose && _windows.Count == 0)
Shutdown(); TryShutdown();
else if (ShutdownMode == ShutdownMode.OnMainWindowClose && window == MainWindow) else if (ShutdownMode == ShutdownMode.OnMainWindowClose && ReferenceEquals(window, MainWindow))
Shutdown(); TryShutdown();
} }
public void Shutdown(int exitCode = 0) public void Shutdown(int exitCode = 0)
{ {
if (_isShuttingDown) DoShutdown(new ShutdownRequestedEventArgs(), true, exitCode);
throw new InvalidOperationException("Application is already shutting down."); }
_exitCode = exitCode;
_isShuttingDown = true;
try public bool TryShutdown(int exitCode = 0)
{ {
foreach (var w in Windows) return DoShutdown(new ShutdownRequestedEventArgs(), false, exitCode);
w.Close();
var e = new ControlledApplicationLifetimeExitEventArgs(exitCode);
Exit?.Invoke(this, e);
_exitCode = e.ApplicationExitCode;
}
finally
{
_cts?.Cancel();
_cts = null;
_isShuttingDown = false;
}
} }
public int Start(string[] args) public int Start(string[] args)
{ {
Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args)); Startup?.Invoke(this, new ControlledApplicationLifetimeStartupEventArgs(args));
@ -114,7 +99,10 @@ namespace Avalonia.Controls.ApplicationLifetimes
if(options != null && options.ProcessUrlActivationCommandLine && args.Length > 0) if(options != null && options.ProcessUrlActivationCommandLine && args.Length > 0)
{ {
((IApplicationPlatformEvents)Application.Current).RaiseUrlsOpened(args); if (Application.Current is IApplicationPlatformEvents events)
{
events.RaiseUrlsOpened(args);
}
} }
var lifetimeEvents = AvaloniaLocator.Current.GetService<IPlatformLifetimeEventsImpl>(); var lifetimeEvents = AvaloniaLocator.Current.GetService<IPlatformLifetimeEventsImpl>();
@ -145,23 +133,57 @@ namespace Avalonia.Controls.ApplicationLifetimes
if (_activeLifetime == this) if (_activeLifetime == this)
_activeLifetime = null; _activeLifetime = null;
} }
private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) private bool DoShutdown(ShutdownRequestedEventArgs e, bool force = false, int exitCode = 0)
{ {
ShutdownRequested?.Invoke(this, e); if (!force)
{
ShutdownRequested?.Invoke(this, e);
if (e.Cancel) if (e.Cancel)
return; return false;
if (_isShuttingDown)
throw new InvalidOperationException("Application is already shutting down.");
}
_exitCode = exitCode;
_isShuttingDown = true;
// When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel try
// shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their {
// owners. // When an OS shutdown request is received, try to close all non-owned windows. Windows can cancel
foreach (var w in Windows) // shutdown by setting e.Cancel = true in the Closing event. Owned windows will be shutdown by their
if (w.Owner is null) // owners.
w.Close(); foreach (var w in Windows)
if (Windows.Count > 0) {
e.Cancel = true; if (w.Owner is null)
{
w.Close();
}
}
if (!force && Windows.Count > 0)
{
e.Cancel = true;
return false;
}
var args = new ControlledApplicationLifetimeExitEventArgs(exitCode);
Exit?.Invoke(this, args);
_exitCode = args.ApplicationExitCode;
}
finally
{
_cts?.Cancel();
_cts = null;
_isShuttingDown = false;
}
return true;
} }
private void OnShutdownRequested(object sender, ShutdownRequestedEventArgs e) => DoShutdown(e);
} }
public class ClassicDesktopStyleApplicationLifetimeOptions public class ClassicDesktopStyleApplicationLifetimeOptions

6
src/Avalonia.Controls/ApplicationLifetimes/IClassicDesktopStyleApplicationLifetime.cs

@ -9,6 +9,12 @@ namespace Avalonia.Controls.ApplicationLifetimes
/// </summary> /// </summary>
public interface IClassicDesktopStyleApplicationLifetime : IControlledApplicationLifetime public interface IClassicDesktopStyleApplicationLifetime : IControlledApplicationLifetime
{ {
/// <summary>
/// Tries to Shutdown the application. <see cref="ShutdownRequested" /> event can be used to cancel the shutdown.
/// </summary>
/// <param name="exitCode">An integer exit code for an application. The default exit code is 0.</param>
bool TryShutdown(int exitCode = 0);
/// <summary> /// <summary>
/// Gets the arguments passed to the /// Gets the arguments passed to the
/// <see cref="ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime{T}(T, string[], ShutdownMode)"/> /// <see cref="ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime{T}(T, string[], ShutdownMode)"/>

2
src/Avalonia.Controls/LayoutTransformControl.cs

@ -18,7 +18,7 @@ namespace Avalonia.Controls
AvaloniaProperty.Register<LayoutTransformControl, ITransform>(nameof(LayoutTransform)); AvaloniaProperty.Register<LayoutTransformControl, ITransform>(nameof(LayoutTransform));
public static readonly StyledProperty<bool> UseRenderTransformProperty = public static readonly StyledProperty<bool> UseRenderTransformProperty =
AvaloniaProperty.Register<LayoutTransformControl, bool>(nameof(LayoutTransform)); AvaloniaProperty.Register<LayoutTransformControl, bool>(nameof(UseRenderTransform));
static LayoutTransformControl() static LayoutTransformControl()
{ {

2
src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs

@ -101,7 +101,7 @@ namespace Avalonia.Controls.Platform
root.Deactivated -= WindowDeactivated; root.Deactivated -= WindowDeactivated;
} }
if (_root is TopLevel tl) if (_root is TopLevel tl && tl.PlatformImpl != null)
tl.PlatformImpl.LostFocus -= TopLevelLostPlatformFocus; tl.PlatformImpl.LostFocus -= TopLevelLostPlatformFocus;
_inputManagerSubscription?.Dispose(); _inputManagerSubscription?.Dispose();

2
src/Avalonia.Controls/Primitives/PopupRoot.cs

@ -44,7 +44,7 @@ namespace Avalonia.Controls.Primitives
/// The dependency resolver to use. If null the default dependency resolver will be used. /// The dependency resolver to use. If null the default dependency resolver will be used.
/// </param> /// </param>
public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver dependencyResolver) public PopupRoot(TopLevel parent, IPopupImpl impl, IAvaloniaDependencyResolver dependencyResolver)
: base(impl, dependencyResolver) : base(ValidatingPopupImpl.Wrap(impl), dependencyResolver)
{ {
_parent = parent; _parent = parent;
} }

9
src/Avalonia.Controls/TopLevel.cs

@ -134,6 +134,8 @@ namespace Avalonia.Controls
"Could not create window implementation: maybe no windowing subsystem was initialized?"); "Could not create window implementation: maybe no windowing subsystem was initialized?");
} }
impl = ValidatingToplevelImpl.Wrap(impl);
PlatformImpl = impl; PlatformImpl = impl;
_actualTransparencyLevel = PlatformImpl.TransparencyLevel; _actualTransparencyLevel = PlatformImpl.TransparencyLevel;
@ -367,14 +369,15 @@ namespace Avalonia.Controls
Renderer?.Dispose(); Renderer?.Dispose();
Renderer = null; Renderer = null;
(this as IInputRoot).MouseDevice?.TopLevelClosed(this);
PlatformImpl = null;
var logicalArgs = new LogicalTreeAttachmentEventArgs(this, this, null); var logicalArgs = new LogicalTreeAttachmentEventArgs(this, this, null);
((ILogical)this).NotifyDetachedFromLogicalTree(logicalArgs); ((ILogical)this).NotifyDetachedFromLogicalTree(logicalArgs);
var visualArgs = new VisualTreeAttachmentEventArgs(this, this); var visualArgs = new VisualTreeAttachmentEventArgs(this, this);
OnDetachedFromVisualTreeCore(visualArgs); OnDetachedFromVisualTreeCore(visualArgs);
(this as IInputRoot).MouseDevice?.TopLevelClosed(this);
PlatformImpl = null;
OnClosed(EventArgs.Empty); OnClosed(EventArgs.Empty);
LayoutManager?.Dispose(); LayoutManager?.Dispose();

337
src/Avalonia.Controls/ValidatingToplevel.cs

@ -0,0 +1,337 @@
using System;
using System.Collections.Generic;
using Avalonia.Controls.Platform;
using Avalonia.Controls.Primitives.PopupPositioning;
using Avalonia.Input;
using Avalonia.Input.Raw;
using Avalonia.Input.TextInput;
using Avalonia.Platform;
using Avalonia.Rendering;
namespace Avalonia.Controls;
internal class ValidatingToplevelImpl : ITopLevelImpl, ITopLevelImplWithNativeControlHost,
ITopLevelImplWithNativeMenuExporter, ITopLevelImplWithTextInputMethod
{
private readonly ITopLevelImpl _impl;
private bool _disposed;
public ValidatingToplevelImpl(ITopLevelImpl impl)
{
_impl = impl ?? throw new InvalidOperationException(
"Could not create TopLevel implementation: maybe no windowing subsystem was initialized?");
}
public void Dispose()
{
_disposed = true;
_impl.Dispose();
}
protected void CheckDisposed()
{
if (_disposed)
throw new ObjectDisposedException(_impl.GetType().FullName);
}
protected ITopLevelImpl Inner
{
get
{
CheckDisposed();
return _impl;
}
}
public static ITopLevelImpl Wrap(ITopLevelImpl impl)
{
#if DEBUG
if (impl is ValidatingToplevelImpl)
return impl;
return new ValidatingToplevelImpl(impl);
#else
return impl;
#endif
}
public Size ClientSize => Inner.ClientSize;
public Size? FrameSize => Inner.FrameSize;
public double RenderScaling => Inner.RenderScaling;
public IEnumerable<object> Surfaces => Inner.Surfaces;
public Action<RawInputEventArgs> Input
{
get => Inner.Input;
set => Inner.Input = value;
}
public Action<Rect> Paint
{
get => Inner.Paint;
set => Inner.Paint = value;
}
public Action<Size, PlatformResizeReason> Resized
{
get => Inner.Resized;
set => Inner.Resized = value;
}
public Action<double> ScalingChanged
{
get => Inner.ScalingChanged;
set => Inner.ScalingChanged = value;
}
public Action<WindowTransparencyLevel> TransparencyLevelChanged
{
get => Inner.TransparencyLevelChanged;
set => Inner.TransparencyLevelChanged = value;
}
public IRenderer CreateRenderer(IRenderRoot root) => Inner.CreateRenderer(root);
public void Invalidate(Rect rect) => Inner.Invalidate(rect);
public void SetInputRoot(IInputRoot inputRoot) => Inner.SetInputRoot(inputRoot);
public Point PointToClient(PixelPoint point) => Inner.PointToClient(point);
public PixelPoint PointToScreen(Point point) => Inner.PointToScreen(point);
public void SetCursor(ICursorImpl cursor) => Inner.SetCursor(cursor);
public Action Closed
{
get => Inner.Closed;
set => Inner.Closed = value;
}
public Action LostFocus
{
get => Inner.LostFocus;
set => Inner.LostFocus = value;
}
// Exception: for some reason we are notifying platform mouse device from TopLevel.cs
public IMouseDevice MouseDevice => _impl.MouseDevice;
public IPopupImpl CreatePopup() => Inner.CreatePopup();
public void SetTransparencyLevelHint(WindowTransparencyLevel transparencyLevel) =>
Inner.SetTransparencyLevelHint(transparencyLevel);
public WindowTransparencyLevel TransparencyLevel => Inner.TransparencyLevel;
public AcrylicPlatformCompensationLevels AcrylicCompensationLevels => Inner.AcrylicCompensationLevels;
public INativeControlHostImpl NativeControlHost => (Inner as ITopLevelImplWithNativeControlHost)?.NativeControlHost;
public ITopLevelNativeMenuExporter NativeMenuExporter =>
(Inner as ITopLevelImplWithNativeMenuExporter)?.NativeMenuExporter;
public ITextInputMethodImpl TextInputMethod => (Inner as ITopLevelImplWithTextInputMethod)?.TextInputMethod;
}
internal class ValidatingWindowBaseImpl : ValidatingToplevelImpl, IWindowBaseImpl
{
private readonly IWindowBaseImpl _impl;
public ValidatingWindowBaseImpl(IWindowBaseImpl impl) : base(impl)
{
_impl = impl;
}
protected new IWindowBaseImpl Inner
{
get
{
CheckDisposed();
return _impl;
}
}
public static IWindowBaseImpl Wrap(IWindowBaseImpl impl)
{
#if DEBUG
if (impl is ValidatingToplevelImpl)
return impl;
return new ValidatingWindowBaseImpl(impl);
#else
return impl;
#endif
}
public void Show(bool activate, bool isDialog) => Inner.Show(activate, isDialog);
public void Hide() => Inner.Hide();
public double DesktopScaling => Inner.DesktopScaling;
public PixelPoint Position => Inner.Position;
public Action<PixelPoint> PositionChanged
{
get => Inner.PositionChanged;
set => Inner.PositionChanged = value;
}
public void Activate() => Inner.Activate();
public Action Deactivated
{
get => Inner.Deactivated;
set => Inner.Deactivated = value;
}
public Action Activated
{
get => Inner.Activated;
set => Inner.Deactivated = value;
}
public IPlatformHandle Handle => Inner.Handle;
public Size MaxAutoSizeHint => Inner.MaxAutoSizeHint;
public void SetTopmost(bool value) => Inner.SetTopmost(value);
public IScreenImpl Screen => Inner.Screen;
}
internal class ValidatingWindowImpl : ValidatingWindowBaseImpl, IWindowImpl
{
private readonly IWindowImpl _impl;
public ValidatingWindowImpl(IWindowImpl impl) : base(impl)
{
_impl = impl;
}
protected new IWindowImpl Inner
{
get
{
CheckDisposed();
return _impl;
}
}
public static IWindowImpl Wrap(IWindowImpl impl)
{
#if DEBUG
if (impl is ValidatingToplevelImpl)
return impl;
return new ValidatingWindowImpl(impl);
#else
return impl;
#endif
}
public WindowState WindowState
{
get => Inner.WindowState;
set => Inner.WindowState = value;
}
public Action<WindowState> WindowStateChanged
{
get => Inner.WindowStateChanged;
set => Inner.WindowStateChanged = value;
}
public void SetTitle(string title) => Inner.SetTitle(title);
public void SetParent(IWindowImpl parent)
{
//Workaround. SetParent will cast IWindowImpl to WindowImpl but ValidatingWindowImpl isn't actual WindowImpl so it will fail with InvalidCastException.
if (parent is ValidatingWindowImpl validatingToplevelImpl)
{
Inner.SetParent(validatingToplevelImpl.Inner);
}
else
{
Inner.SetParent(parent);
}
}
public void SetEnabled(bool enable) => Inner.SetEnabled(enable);
public Action GotInputWhenDisabled
{
get => Inner.GotInputWhenDisabled;
set => Inner.GotInputWhenDisabled = value;
}
public void SetSystemDecorations(SystemDecorations enabled) => Inner.SetSystemDecorations(enabled);
public void SetIcon(IWindowIconImpl icon) => Inner.SetIcon(icon);
public void ShowTaskbarIcon(bool value) => Inner.ShowTaskbarIcon(value);
public void CanResize(bool value) => Inner.CanResize(value);
public Func<bool> Closing
{
get => Inner.Closing;
set => Inner.Closing = value;
}
public bool IsClientAreaExtendedToDecorations => Inner.IsClientAreaExtendedToDecorations;
public Action<bool> ExtendClientAreaToDecorationsChanged
{
get => Inner.ExtendClientAreaToDecorationsChanged;
set => Inner.ExtendClientAreaToDecorationsChanged = value;
}
public bool NeedsManagedDecorations => Inner.NeedsManagedDecorations;
public Thickness ExtendedMargins => Inner.ExtendedMargins;
public Thickness OffScreenMargin => Inner.OffScreenMargin;
public void BeginMoveDrag(PointerPressedEventArgs e) => Inner.BeginMoveDrag(e);
public void BeginResizeDrag(WindowEdge edge, PointerPressedEventArgs e) => Inner.BeginResizeDrag(edge, e);
public void Resize(Size clientSize, PlatformResizeReason reason) =>
Inner.Resize(clientSize, reason);
public void Move(PixelPoint point) => Inner.Move(point);
public void SetMinMaxSize(Size minSize, Size maxSize) => Inner.SetMinMaxSize(minSize, maxSize);
public void SetExtendClientAreaToDecorationsHint(bool extendIntoClientAreaHint) =>
Inner.SetExtendClientAreaToDecorationsHint(extendIntoClientAreaHint);
public void SetExtendClientAreaChromeHints(ExtendClientAreaChromeHints hints) =>
Inner.SetExtendClientAreaChromeHints(hints);
public void SetExtendClientAreaTitleBarHeightHint(double titleBarHeight) =>
Inner.SetExtendClientAreaTitleBarHeightHint(titleBarHeight);
}
internal class ValidatingPopupImpl : ValidatingWindowBaseImpl, IPopupImpl
{
private readonly IPopupImpl _impl;
public ValidatingPopupImpl(IPopupImpl impl) : base(impl)
{
_impl = impl;
}
protected new IPopupImpl Inner
{
get
{
CheckDisposed();
return _impl;
}
}
public static IPopupImpl Wrap(IPopupImpl impl)
{
#if DEBUG
if (impl is ValidatingToplevelImpl)
return impl;
return new ValidatingPopupImpl(impl);
#else
return impl;
#endif
}
public IPopupPositioner PopupPositioner => Inner.PopupPositioner;
public void SetWindowManagerAddShadowHint(bool enabled) => Inner.SetWindowManagerAddShadowHint(enabled);
}

11
src/Avalonia.Controls/Window.cs

@ -237,13 +237,14 @@ namespace Avalonia.Controls
/// </summary> /// </summary>
/// <param name="impl">The window implementation.</param> /// <param name="impl">The window implementation.</param>
public Window(IWindowImpl impl) public Window(IWindowImpl impl)
: base(impl) : base(ValidatingWindowImpl.Wrap(impl))
{ {
impl.Closing = HandleClosing; var wrapped = (IWindowImpl)base.PlatformImpl!;
impl.GotInputWhenDisabled = OnGotInputWhenDisabled; wrapped.Closing = HandleClosing;
impl.WindowStateChanged = HandleWindowStateChanged; wrapped.GotInputWhenDisabled = OnGotInputWhenDisabled;
wrapped.WindowStateChanged = HandleWindowStateChanged;
_maxPlatformClientSize = PlatformImpl?.MaxAutoSizeHint ?? default(Size); _maxPlatformClientSize = PlatformImpl?.MaxAutoSizeHint ?? default(Size);
impl.ExtendClientAreaToDecorationsChanged = ExtendClientAreaToDecorationsChanged; wrapped.ExtendClientAreaToDecorationsChanged = ExtendClientAreaToDecorationsChanged;
this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x, PlatformResizeReason.Application)); this.GetObservable(ClientSizeProperty).Skip(1).Subscribe(x => PlatformImpl?.Resize(x, PlatformResizeReason.Application));
PlatformImpl?.ShowTaskbarIcon(ShowInTaskbar); PlatformImpl?.ShowTaskbarIcon(ShowInTaskbar);

9
src/Avalonia.Controls/WindowBase.cs

@ -57,12 +57,13 @@ namespace Avalonia.Controls
{ {
} }
public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(impl, dependencyResolver) public WindowBase(IWindowBaseImpl impl, IAvaloniaDependencyResolver dependencyResolver) : base(ValidatingWindowBaseImpl.Wrap(impl), dependencyResolver)
{ {
Screens = new Screens(PlatformImpl?.Screen); Screens = new Screens(PlatformImpl?.Screen);
impl.Activated = HandleActivated; var wrapped = PlatformImpl!;
impl.Deactivated = HandleDeactivated; wrapped.Activated = HandleActivated;
impl.PositionChanged = HandlePositionChanged; wrapped.Deactivated = HandleDeactivated;
wrapped.PositionChanged = HandlePositionChanged;
} }
/// <summary> /// <summary>

4
src/Avalonia.Diagnostics/Diagnostics/Views/MainWindow.xaml

@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:views="clr-namespace:Avalonia.Diagnostics.Views" xmlns:views="clr-namespace:Avalonia.Diagnostics.Views"
xmlns:diag="clr-namespace:Avalonia.Diagnostics" xmlns:diag="clr-namespace:Avalonia.Diagnostics"
xmlns:default="using:Avalonia.Themes.Default"
Title="Avalonia DevTools" Title="Avalonia DevTools"
x:Class="Avalonia.Diagnostics.Views.MainWindow"> x:Class="Avalonia.Diagnostics.Views.MainWindow">
<Window.DataTemplates> <Window.DataTemplates>
@ -9,8 +10,7 @@
</Window.DataTemplates> </Window.DataTemplates>
<Window.Styles> <Window.Styles>
<StyleInclude Source="resm:Avalonia.Themes.Default.DefaultTheme.xaml?assembly=Avalonia.Themes.Default"/> <default:SimpleTheme Mode="Light"/>
<StyleInclude Source="resm:Avalonia.Themes.Default.Accents.BaseLight.xaml?assembly=Avalonia.Themes.Default"/>
<StyleInclude Source="resm:Avalonia.Controls.DataGrid.Themes.Default.xaml?assembly=Avalonia.Controls.DataGrid"/> <StyleInclude Source="resm:Avalonia.Controls.DataGrid.Themes.Default.xaml?assembly=Avalonia.Controls.DataGrid"/>
<Style Selector="DataGrid ContextMenu"> <Style Selector="DataGrid ContextMenu">
<Setter Property="Foreground" Value="Black"/> <Setter Property="Foreground" Value="Black"/>

2
src/Avalonia.Dialogs/AboutAvaloniaDialog.xaml

@ -95,7 +95,7 @@
</StackPanel> </StackPanel>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" > <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" >
<TextBlock Text="Chat Room | " /> <TextBlock Text="Chat Room | " />
<Button Classes="Hyperlink" CommandParameter="https://gitter.im/AvaloniaUI/Avalonia/" /> <Button Classes="Hyperlink" CommandParameter="https://t.me/Avalonia" />
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
<StackPanel VerticalAlignment="Bottom" Margin="10"> <StackPanel VerticalAlignment="Bottom" Margin="10">

1
src/Avalonia.Dialogs/Avalonia.Dialogs.csproj

@ -5,6 +5,7 @@
<ItemGroup> <ItemGroup>
<AvaloniaResource Include="Assets\*" /> <AvaloniaResource Include="Assets\*" />
<AvaloniaResource Include="**/*.xaml" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />

6
src/Avalonia.Input/KeyBinding.cs

@ -35,9 +35,11 @@ namespace Avalonia.Input
{ {
if (Gesture?.Matches(args) == true) if (Gesture?.Matches(args) == true)
{ {
args.Handled = true; if (Command?.CanExecute(CommandParameter) == true)
if (Command?.CanExecute(CommandParameter) == true) {
args.Handled = true;
Command.Execute(CommandParameter); Command.Execute(CommandParameter);
}
} }
} }
} }

113
src/Avalonia.Native/AvaloniaNativeMenuExporter.cs

@ -70,74 +70,80 @@ namespace Avalonia.Native
var result = new NativeMenu(); var result = new NativeMenu();
var aboutItem = new NativeMenuItem("About Avalonia"); var aboutItem = new NativeMenuItem("About Avalonia");
aboutItem.Click += async (sender, e) =>
aboutItem.Click += async (_, _) =>
{ {
var dialog = new AboutAvaloniaDialog(); var dialog = new AboutAvaloniaDialog();
var mainWindow = (Application.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow; if (Application.Current is
{ ApplicationLifetime: IClassicDesktopStyleApplicationLifetime { MainWindow: { } mainWindow } })
await dialog.ShowDialog(mainWindow); {
await dialog.ShowDialog(mainWindow);
}
}; };
result.Add(aboutItem); result.Add(aboutItem);
var macOpts = AvaloniaLocator.Current.GetService<MacOSPlatformOptions>() ?? new MacOSPlatformOptions(); return result;
if (!macOpts.DisableDefaultApplicationMenuItems) }
{
result.Add(new NativeMenuItemSeparator());
var servicesMenu = new NativeMenuItem("Services"); private void PopulateStandardOSXMenuItems(NativeMenu appMenu)
servicesMenu.Menu = new NativeMenu {
{ appMenu.Add(new NativeMenuItemSeparator());
[MacOSNativeMenuCommands.IsServicesSubmenuProperty] = true
};
result.Add(servicesMenu);
result.Add(new NativeMenuItemSeparator()); var servicesMenu = new NativeMenuItem("Services");
servicesMenu.Menu = new NativeMenu { [MacOSNativeMenuCommands.IsServicesSubmenuProperty] = true };
var hideItem = new NativeMenuItem("Hide " + Application.Current.Name) appMenu.Add(servicesMenu);
{
Gesture = new KeyGesture(Key.H, KeyModifiers.Meta)
};
hideItem.Click += (sender, args) =>
{
_applicationCommands.HideApp();
};
result.Add(hideItem);
appMenu.Add(new NativeMenuItemSeparator());
var hideOthersItem = new NativeMenuItem("Hide Others") var hideItem = new NativeMenuItem("Hide " + (Application.Current?.Name ?? "Application"))
{ {
Gesture = new KeyGesture(Key.Q, KeyModifiers.Meta | KeyModifiers.Alt) Gesture = new KeyGesture(Key.H, KeyModifiers.Meta)
}; };
hideOthersItem.Click += (sender, args) =>
{
_applicationCommands.HideOthers();
};
result.Add(hideOthersItem);
hideItem.Click += (_, _) =>
{
_applicationCommands.HideApp();
};
var showAllItem = new NativeMenuItem("Show All"); appMenu.Add(hideItem);
showAllItem.Click += (sender, args) =>
{ var hideOthersItem = new NativeMenuItem("Hide Others")
_applicationCommands.ShowAll(); {
}; Gesture = new KeyGesture(Key.Q, KeyModifiers.Meta | KeyModifiers.Alt)
result.Add(showAllItem); };
hideOthersItem.Click += (_, _) =>
{
_applicationCommands.HideOthers();
};
appMenu.Add(hideOthersItem);
var showAllItem = new NativeMenuItem("Show All");
showAllItem.Click += (_, _) =>
{
_applicationCommands.ShowAll();
};
appMenu.Add(showAllItem);
result.Add(new NativeMenuItemSeparator()); appMenu.Add(new NativeMenuItemSeparator());
var quitItem = new NativeMenuItem("Quit") var quitItem = new NativeMenuItem("Quit") { Gesture = new KeyGesture(Key.Q, KeyModifiers.Meta) };
quitItem.Click += (_, _) =>
{
if (Application.Current is { ApplicationLifetime: IClassicDesktopStyleApplicationLifetime lifetime })
{ {
Gesture = new KeyGesture(Key.Q, KeyModifiers.Meta) lifetime.TryShutdown();
}; }
quitItem.Click += (sender, args) => else if(Application.Current is {ApplicationLifetime: IControlledApplicationLifetime controlledLifetime})
{ {
(Application.Current.ApplicationLifetime as IControlledApplicationLifetime)?.Shutdown(); controlledLifetime.Shutdown();
}; }
result.Add(quitItem); };
}
return result; appMenu.Add(quitItem);
} }
private void DoLayoutReset(bool forceUpdate = false) private void DoLayoutReset(bool forceUpdate = false)
@ -220,6 +226,13 @@ namespace Avalonia.Native
_nativeMenu.Initialize(this, appMenuHolder, ""); _nativeMenu.Initialize(this, appMenuHolder, "");
var macOpts = AvaloniaLocator.Current.GetService<MacOSPlatformOptions>();
if (macOpts == null || !macOpts.DisableDefaultApplicationMenuItems)
{
PopulateStandardOSXMenuItems(menu);
}
setMenu = true; setMenu = true;
} }

64
src/Avalonia.Themes.Default/Accents/Base.xaml

@ -0,0 +1,64 @@
<Style
xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Style.Resources>
<Color x:Key="ThemeAccentColor">#CC119EDA</Color>
<Color x:Key="ThemeAccentColor2">#99119EDA</Color>
<Color x:Key="ThemeAccentColor3">#66119EDA</Color>
<Color x:Key="ThemeAccentColor4">#33119EDA</Color>
<Color x:Key="ThemeForegroundLowColor">#FF808080</Color>
<Color x:Key="HighlightForegroundColor">#FFFFFFFF</Color>
<Color x:Key="ErrorColor">#FFFF0000</Color>
<Color x:Key="ErrorLowColor">#10FF0000</Color>
<SolidColorBrush x:Key="HighlightForegroundBrush" Color="{StaticResource HighlightForegroundColor}" />
<SolidColorBrush x:Key="ThemeForegroundLowBrush" Color="{StaticResource ThemeForegroundLowColor}" />
<SolidColorBrush x:Key="ThemeAccentBrush2" Color="{StaticResource ThemeAccentColor2}" />
<SolidColorBrush x:Key="ThemeAccentBrush3" Color="{StaticResource ThemeAccentColor3}" />
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{StaticResource ThemeAccentColor4}" />
<SolidColorBrush x:Key="ThemeAccentBrush" Color="{StaticResource ThemeAccentColor}" />
<SolidColorBrush x:Key="ErrorBrush" Color="{StaticResource ErrorColor}" />
<SolidColorBrush x:Key="ErrorLowBrush" Color="{StaticResource ErrorLowColor}" />
<SolidColorBrush
x:Key="NotificationCardBackgroundBrush"
Opacity="0.75"
Color="#444444" />
<SolidColorBrush
x:Key="NotificationCardInformationBackgroundBrush"
Opacity="0.75"
Color="#007ACC" />
<SolidColorBrush
x:Key="NotificationCardSuccessBackgroundBrush"
Opacity="0.75"
Color="#1F9E45" />
<SolidColorBrush
x:Key="NotificationCardWarningBackgroundBrush"
Opacity="0.75"
Color="#FDB328" />
<SolidColorBrush
x:Key="NotificationCardErrorBackgroundBrush"
Opacity="0.75"
Color="#BD202C" />
<SolidColorBrush x:Key="ThemeControlTransparentBrush" Color="Transparent" />
<SolidColorBrush
x:Key="DatePickerFlyoutPresenterHighlightFill"
Opacity="0.4"
Color="{StaticResource ThemeAccentColor}" />
<SolidColorBrush
x:Key="TimePickerFlyoutPresenterHighlightFill"
Opacity="0.4"
Color="{StaticResource ThemeAccentColor}" />
<Thickness x:Key="ThemeBorderThickness">1</Thickness>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>
<sys:Double x:Key="FontSizeSmall">10</sys:Double>
<sys:Double x:Key="FontSizeNormal">12</sys:Double>
<sys:Double x:Key="FontSizeLarge">16</sys:Double>
<sys:Double x:Key="ScrollBarThickness">18</sys:Double>
<sys:Double x:Key="ScrollBarThumbThickness">8</sys:Double>
<sys:Double x:Key="IconElementThemeHeight">20</sys:Double>
<sys:Double x:Key="IconElementThemeWidth">20</sys:Double>
</Style.Resources>
</Style>

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

@ -1,13 +1,9 @@
<Style xmlns="https://github.com/avaloniaui" <Style
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="https://github.com/avaloniaui"
xmlns:sys="clr-namespace:System;assembly=netstandard"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Style.Resources> <Style.Resources>
<Color x:Key="ThemeAccentColor">#CC119EDA</Color>
<Color x:Key="ThemeAccentColor2">#99119EDA</Color>
<Color x:Key="ThemeAccentColor3">#66119EDA</Color>
<Color x:Key="ThemeAccentColor4">#33119EDA</Color>
<Color x:Key="ThemeBackgroundColor">#FF282828</Color> <Color x:Key="ThemeBackgroundColor">#FF282828</Color>
<Color x:Key="ThemeBorderLowColor">#FF505050</Color> <Color x:Key="ThemeBorderLowColor">#FF505050</Color>
<Color x:Key="ThemeBorderMidColor">#FF808080</Color> <Color x:Key="ThemeBorderMidColor">#FF808080</Color>
@ -21,59 +17,22 @@
<Color x:Key="ThemeControlHighlightMidColor">#FF828282</Color> <Color x:Key="ThemeControlHighlightMidColor">#FF828282</Color>
<Color x:Key="ThemeControlHighlightHighColor">#FF505050</Color> <Color x:Key="ThemeControlHighlightHighColor">#FF505050</Color>
<Color x:Key="ThemeForegroundColor">#FFDEDEDE</Color> <Color x:Key="ThemeForegroundColor">#FFDEDEDE</Color>
<Color x:Key="ThemeForegroundLowColor">#FF808080</Color>
<Color x:Key="HighlightColor">#FF119EDA</Color> <Color x:Key="HighlightColor">#FF119EDA</Color>
<Color x:Key="HighlightForegroundColor">#FFFFFFFF</Color>
<Color x:Key="ErrorColor">#FFFF0000</Color>
<Color x:Key="ErrorLowColor">#10FF0000</Color>
<SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{DynamicResource ThemeBackgroundColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeBorderLowBrush" Color="{DynamicResource ThemeBorderLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeBorderMidBrush" Color="{DynamicResource ThemeBorderMidColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeBorderHighBrush" Color="{DynamicResource ThemeBorderHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlLowBrush" Color="{DynamicResource ThemeControlLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlMidBrush" Color="{DynamicResource ThemeControlMidColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlMidHighBrush" Color="{DynamicResource ThemeControlMidHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighBrush" Color="{DynamicResource ThemeControlHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlVeryHighBrush" Color="{DynamicResource ThemeControlVeryHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighlightLowBrush" Color="{DynamicResource ThemeControlHighlightLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighlightMidBrush" Color="{DynamicResource ThemeControlHighlightMidColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighlightHighBrush" Color="{DynamicResource ThemeControlHighlightHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{DynamicResource ThemeForegroundColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeForegroundLowBrush" Color="{DynamicResource ThemeForegroundLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="HighlightBrush" Color="{DynamicResource HighlightColor}"></SolidColorBrush>
<SolidColorBrush x:Key="HighlightForegroundBrush" Color="{DynamicResource HighlightForegroundColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush" Color="{DynamicResource ThemeAccentColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush2" Color="{DynamicResource ThemeAccentColor2}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush3" Color="{DynamicResource ThemeAccentColor3}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}"></SolidColorBrush>
<SolidColorBrush x:Key="ErrorBrush" Color="{DynamicResource ErrorColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ErrorLowBrush" Color="{DynamicResource ErrorLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="NotificationCardBackgroundBrush" Color="#444444" Opacity="0.75"/>
<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"/>
<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>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>
<sys:Double x:Key="FontSizeSmall">10</sys:Double>
<sys:Double x:Key="FontSizeNormal">12</sys:Double>
<sys:Double x:Key="FontSizeLarge">16</sys:Double>
<sys:Double x:Key="ScrollBarThickness">18</sys:Double> <SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{StaticResource ThemeBackgroundColor}" />
<sys:Double x:Key="ScrollBarThumbThickness">8</sys:Double> <SolidColorBrush x:Key="ThemeBorderLowBrush" Color="{StaticResource ThemeBorderLowColor}" />
<SolidColorBrush x:Key="ThemeBorderMidBrush" Color="{StaticResource ThemeBorderMidColor}" />
<SolidColorBrush x:Key="ThemeBorderHighBrush" Color="{StaticResource ThemeBorderHighColor}" />
<SolidColorBrush x:Key="ThemeControlLowBrush" Color="{StaticResource ThemeControlLowColor}" />
<SolidColorBrush x:Key="ThemeControlMidBrush" Color="{StaticResource ThemeControlMidColor}" />
<SolidColorBrush x:Key="ThemeControlMidHighBrush" Color="{StaticResource ThemeControlMidHighColor}" />
<SolidColorBrush x:Key="ThemeControlHighBrush" Color="{StaticResource ThemeControlHighColor}" />
<SolidColorBrush x:Key="ThemeControlVeryHighBrush" Color="{StaticResource ThemeControlVeryHighColor}" />
<SolidColorBrush x:Key="ThemeControlHighlightLowBrush" Color="{StaticResource ThemeControlHighlightLowColor}" />
<SolidColorBrush x:Key="ThemeControlHighlightMidBrush" Color="{StaticResource ThemeControlHighlightMidColor}" />
<SolidColorBrush x:Key="ThemeControlHighlightHighBrush" Color="{StaticResource ThemeControlHighlightHighColor}" />
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{StaticResource ThemeForegroundColor}" />
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" />
<sys:Double x:Key="IconElementThemeHeight">20</sys:Double>
<sys:Double x:Key="IconElementThemeWidth">20</sys:Double>
</Style.Resources> </Style.Resources>
</Style> </Style>

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

@ -1,82 +1,38 @@
<Style xmlns="https://github.com/avaloniaui" <Style
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="https://github.com/avaloniaui"
xmlns:sys="clr-namespace:System;assembly=netstandard"> xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=netstandard">
<Style.Resources> <Style.Resources>
<Color x:Key="ThemeAccentColor">#CC119EDA</Color>
<Color x:Key="ThemeAccentColor2">#99119EDA</Color>
<Color x:Key="ThemeAccentColor3">#66119EDA</Color>
<Color x:Key="ThemeAccentColor4">#33119EDA</Color>
<Color x:Key="ThemeBackgroundColor">#FFFFFFFF</Color> <Color x:Key="ThemeBackgroundColor">#FFFFFFFF</Color>
<Color x:Key="ThemeBorderLowColor">#FFAAAAAA</Color> <Color x:Key="ThemeBorderLowColor">#FFAAAAAA</Color>
<Color x:Key="ThemeBorderMidColor">#FF888888</Color> <Color x:Key="ThemeBorderMidColor">#FF888888</Color>
<Color x:Key="ThemeBorderHighColor">#FF333333</Color> <Color x:Key="ThemeBorderHighColor">#FF333333</Color>
<Color x:Key="ThemeControlLowColor">#FF868999</Color> <Color x:Key="ThemeControlLowColor">#FF868999</Color>
<Color x:Key="ThemeControlMidColor">#FFF5F5F5</Color> <Color x:Key="ThemeControlMidColor">#FFF5F5F5</Color>
<Color x:Key="ThemeControlMidHighColor">#FFC2C3C9</Color> <Color x:Key="ThemeControlMidHighColor">#FFC2C3C9</Color>
<Color x:Key="ThemeControlHighColor">#FF686868</Color> <Color x:Key="ThemeControlHighColor">#FF686868</Color>
<Color x:Key="ThemeControlVeryHighColor">#FF5B5B5B</Color> <Color x:Key="ThemeControlVeryHighColor">#FF5B5B5B</Color>
<Color x:Key="ThemeControlHighlightLowColor">#FFF0F0F0</Color> <Color x:Key="ThemeControlHighlightLowColor">#FFF0F0F0</Color>
<Color x:Key="ThemeControlHighlightMidColor">#FFD0D0D0</Color> <Color x:Key="ThemeControlHighlightMidColor">#FFD0D0D0</Color>
<Color x:Key="ThemeControlHighlightHighColor">#FF808080</Color> <Color x:Key="ThemeControlHighlightHighColor">#FF808080</Color>
<Color x:Key="ThemeForegroundColor">#FF000000</Color> <Color x:Key="ThemeForegroundColor">#FF000000</Color>
<Color x:Key="ThemeForegroundLowColor">#FF808080</Color>
<Color x:Key="HighlightColor">#FF086F9E</Color> <Color x:Key="HighlightColor">#FF086F9E</Color>
<Color x:Key="HighlightForegroundColor">#FFFFFFFF</Color>
<Color x:Key="ErrorColor">#FFFF0000</Color>
<Color x:Key="ErrorLowColor">#10FF0000</Color>
<SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{DynamicResource ThemeBackgroundColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeBorderLowBrush" Color="{DynamicResource ThemeBorderLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeBorderMidBrush" Color="{DynamicResource ThemeBorderMidColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeBorderHighBrush" Color="{DynamicResource ThemeBorderHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlLowBrush" Color="{DynamicResource ThemeControlLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlMidBrush" Color="{DynamicResource ThemeControlMidColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlMidHighBrush" Color="{DynamicResource ThemeControlMidHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighBrush" Color="{DynamicResource ThemeControlHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlVeryHighBrush" Color="{DynamicResource ThemeControlVeryHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighlightLowBrush" Color="{DynamicResource ThemeControlHighlightLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighlightMidBrush" Color="{DynamicResource ThemeControlHighlightMidColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeControlHighlightHighBrush" Color="{DynamicResource ThemeControlHighlightHighColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{DynamicResource ThemeForegroundColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeForegroundLowBrush" Color="{DynamicResource ThemeForegroundLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="HighlightBrush" Color="{DynamicResource HighlightColor}"></SolidColorBrush>
<SolidColorBrush x:Key="HighlightForegroundBrush" Color="{DynamicResource HighlightForegroundColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush" Color="{DynamicResource ThemeAccentColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush2" Color="{DynamicResource ThemeAccentColor2}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush3" Color="{DynamicResource ThemeAccentColor3}"></SolidColorBrush>
<SolidColorBrush x:Key="ThemeAccentBrush4" Color="{DynamicResource ThemeAccentColor4}"></SolidColorBrush>
<SolidColorBrush x:Key="ErrorBrush" Color="{DynamicResource ErrorColor}"></SolidColorBrush>
<SolidColorBrush x:Key="ErrorLowBrush" Color="{DynamicResource ErrorLowColor}"></SolidColorBrush>
<SolidColorBrush x:Key="NotificationCardBackgroundBrush" Color="#444444" Opacity="0.75"/>
<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"/>
<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>
<sys:Double x:Key="ThemeDisabledOpacity">0.5</sys:Double>
<sys:Double x:Key="FontSizeSmall">10</sys:Double>
<sys:Double x:Key="FontSizeNormal">12</sys:Double>
<sys:Double x:Key="FontSizeLarge">16</sys:Double>
<sys:Double x:Key="ScrollBarThickness">18</sys:Double>
<sys:Double x:Key="ScrollBarThumbThickness">8</sys:Double>
<sys:Double x:Key="IconElementThemeHeight">20</sys:Double> <SolidColorBrush x:Key="ThemeBackgroundBrush" Color="{StaticResource ThemeBackgroundColor}" />
<sys:Double x:Key="IconElementThemeWidth">20</sys:Double> <SolidColorBrush x:Key="ThemeBorderLowBrush" Color="{StaticResource ThemeBorderLowColor}" />
<SolidColorBrush x:Key="ThemeBorderMidBrush" Color="{StaticResource ThemeBorderMidColor}" />
<SolidColorBrush x:Key="ThemeBorderHighBrush" Color="{StaticResource ThemeBorderHighColor}" />
<SolidColorBrush x:Key="ThemeControlLowBrush" Color="{StaticResource ThemeControlLowColor}" />
<SolidColorBrush x:Key="ThemeControlMidBrush" Color="{StaticResource ThemeControlMidColor}" />
<SolidColorBrush x:Key="ThemeControlMidHighBrush" Color="{StaticResource ThemeControlMidHighColor}" />
<SolidColorBrush x:Key="ThemeControlHighBrush" Color="{StaticResource ThemeControlHighColor}" />
<SolidColorBrush x:Key="ThemeControlVeryHighBrush" Color="{StaticResource ThemeControlVeryHighColor}" />
<SolidColorBrush x:Key="ThemeControlHighlightLowBrush" Color="{StaticResource ThemeControlHighlightLowColor}" />
<SolidColorBrush x:Key="ThemeControlHighlightMidBrush" Color="{StaticResource ThemeControlHighlightMidColor}" />
<SolidColorBrush x:Key="ThemeControlHighlightHighBrush" Color="{StaticResource ThemeControlHighlightHighColor}" />
<SolidColorBrush x:Key="ThemeForegroundBrush" Color="{StaticResource ThemeForegroundColor}" />
<SolidColorBrush x:Key="HighlightBrush" Color="{StaticResource HighlightColor}" />
</Style.Resources> </Style.Resources>
</Style> </Style>

5
src/Avalonia.Themes.Default/Avalonia.Themes.Default.csproj

@ -13,10 +13,7 @@
<ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" /> <ProjectReference Include="..\Avalonia.Visuals\Avalonia.Visuals.csproj" />
<ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" /> <ProjectReference Include="..\Avalonia.Styling\Avalonia.Styling.csproj" />
<ProjectReference Include="..\Avalonia.Dialogs\Avalonia.Dialogs.csproj" /> <ProjectReference Include="..\Avalonia.Dialogs\Avalonia.Dialogs.csproj" />
<AvaloniaResource Include="DefaultTheme.xaml" /> <AvaloniaResource Include="**/*.xaml" />
<AvaloniaResource Include="Accents/*.xaml" />
<!-- Compatibility with old apps, probably need to replace with AvaloniaResource -->
<EmbeddedResource Include="**/*.xaml" />
</ItemGroup> </ItemGroup>
<Import Project="..\..\build\BuildTargets.targets" /> <Import Project="..\..\build\BuildTargets.targets" />
<Import Project="..\..\build\Rx.props" /> <Import Project="..\..\build\Rx.props" />

0
src/Avalonia.Themes.Default/AutoCompleteBox.xaml → src/Avalonia.Themes.Default/Controls/AutoCompleteBox.xaml

0
src/Avalonia.Themes.Default/Button.xaml → src/Avalonia.Themes.Default/Controls/Button.xaml

0
src/Avalonia.Themes.Default/ButtonSpinner.xaml → src/Avalonia.Themes.Default/Controls/ButtonSpinner.xaml

0
src/Avalonia.Themes.Default/Calendar.xaml → src/Avalonia.Themes.Default/Controls/Calendar.xaml

0
src/Avalonia.Themes.Default/CalendarButton.xaml → src/Avalonia.Themes.Default/Controls/CalendarButton.xaml

0
src/Avalonia.Themes.Default/CalendarDatePicker.xaml → src/Avalonia.Themes.Default/Controls/CalendarDatePicker.xaml

0
src/Avalonia.Themes.Default/CalendarDayButton.xaml → src/Avalonia.Themes.Default/Controls/CalendarDayButton.xaml

0
src/Avalonia.Themes.Default/CalendarItem.xaml → src/Avalonia.Themes.Default/Controls/CalendarItem.xaml

0
src/Avalonia.Themes.Default/CaptionButtons.xaml → src/Avalonia.Themes.Default/Controls/CaptionButtons.xaml

0
src/Avalonia.Themes.Default/Carousel.xaml → src/Avalonia.Themes.Default/Controls/Carousel.xaml

0
src/Avalonia.Themes.Default/CheckBox.xaml → src/Avalonia.Themes.Default/Controls/CheckBox.xaml

0
src/Avalonia.Themes.Default/ComboBox.xaml → src/Avalonia.Themes.Default/Controls/ComboBox.xaml

0
src/Avalonia.Themes.Default/ComboBoxItem.xaml → src/Avalonia.Themes.Default/Controls/ComboBoxItem.xaml

0
src/Avalonia.Themes.Default/ContentControl.xaml → src/Avalonia.Themes.Default/Controls/ContentControl.xaml

0
src/Avalonia.Themes.Default/ContextMenu.xaml → src/Avalonia.Themes.Default/Controls/ContextMenu.xaml

0
src/Avalonia.Themes.Default/DataValidationErrors.xaml → src/Avalonia.Themes.Default/Controls/DataValidationErrors.xaml

0
src/Avalonia.Themes.Default/DatePicker.xaml → src/Avalonia.Themes.Default/Controls/DatePicker.xaml

0
src/Avalonia.Themes.Default/EmbeddableControlRoot.xaml → src/Avalonia.Themes.Default/Controls/EmbeddableControlRoot.xaml

0
src/Avalonia.Themes.Default/Expander.xaml → src/Avalonia.Themes.Default/Controls/Expander.xaml

0
src/Avalonia.Themes.Default/FlyoutPresenter.xaml → src/Avalonia.Themes.Default/Controls/FlyoutPresenter.xaml

0
src/Avalonia.Themes.Default/FocusAdorner.xaml → src/Avalonia.Themes.Default/Controls/FocusAdorner.xaml

0
src/Avalonia.Themes.Default/GridSplitter.xaml → src/Avalonia.Themes.Default/Controls/GridSplitter.xaml

0
src/Avalonia.Themes.Default/ItemsControl.xaml → src/Avalonia.Themes.Default/Controls/ItemsControl.xaml

0
src/Avalonia.Themes.Default/Label.xaml → src/Avalonia.Themes.Default/Controls/Label.xaml

0
src/Avalonia.Themes.Default/ListBox.xaml → src/Avalonia.Themes.Default/Controls/ListBox.xaml

0
src/Avalonia.Themes.Default/ListBoxItem.xaml → src/Avalonia.Themes.Default/Controls/ListBoxItem.xaml

0
src/Avalonia.Themes.Default/ManagedFileChooser.xaml → src/Avalonia.Themes.Default/Controls/ManagedFileChooser.xaml

0
src/Avalonia.Themes.Default/Menu.xaml → src/Avalonia.Themes.Default/Controls/Menu.xaml

0
src/Avalonia.Themes.Default/MenuFlyoutPresenter.xaml → src/Avalonia.Themes.Default/Controls/MenuFlyoutPresenter.xaml

0
src/Avalonia.Themes.Default/MenuItem.xaml → src/Avalonia.Themes.Default/Controls/MenuItem.xaml

0
src/Avalonia.Themes.Default/NativeMenuBar.xaml → src/Avalonia.Themes.Default/Controls/NativeMenuBar.xaml

0
src/Avalonia.Themes.Default/NotificationCard.xaml → src/Avalonia.Themes.Default/Controls/NotificationCard.xaml

0
src/Avalonia.Themes.Default/NumericUpDown.xaml → src/Avalonia.Themes.Default/Controls/NumericUpDown.xaml

0
src/Avalonia.Themes.Default/OverlayPopupHost.xaml → src/Avalonia.Themes.Default/Controls/OverlayPopupHost.xaml

0
src/Avalonia.Themes.Default/PathIcon.xaml → src/Avalonia.Themes.Default/Controls/PathIcon.xaml

0
src/Avalonia.Themes.Default/PopupRoot.xaml → src/Avalonia.Themes.Default/Controls/PopupRoot.xaml

0
src/Avalonia.Themes.Default/ProgressBar.xaml → src/Avalonia.Themes.Default/Controls/ProgressBar.xaml

0
src/Avalonia.Themes.Default/RadioButton.xaml → src/Avalonia.Themes.Default/Controls/RadioButton.xaml

0
src/Avalonia.Themes.Default/RepeatButton.xaml → src/Avalonia.Themes.Default/Controls/RepeatButton.xaml

0
src/Avalonia.Themes.Default/ScrollBar.xaml → src/Avalonia.Themes.Default/Controls/ScrollBar.xaml

0
src/Avalonia.Themes.Default/ScrollViewer.xaml → src/Avalonia.Themes.Default/Controls/ScrollViewer.xaml

0
src/Avalonia.Themes.Default/Separator.xaml → src/Avalonia.Themes.Default/Controls/Separator.xaml

0
src/Avalonia.Themes.Default/Slider.xaml → src/Avalonia.Themes.Default/Controls/Slider.xaml

0
src/Avalonia.Themes.Default/SplitView.xaml → src/Avalonia.Themes.Default/Controls/SplitView.xaml

0
src/Avalonia.Themes.Default/TabControl.xaml → src/Avalonia.Themes.Default/Controls/TabControl.xaml

0
src/Avalonia.Themes.Default/TabItem.xaml → src/Avalonia.Themes.Default/Controls/TabItem.xaml

0
src/Avalonia.Themes.Default/TabStrip.xaml → src/Avalonia.Themes.Default/Controls/TabStrip.xaml

0
src/Avalonia.Themes.Default/TabStripItem.xaml → src/Avalonia.Themes.Default/Controls/TabStripItem.xaml

0
src/Avalonia.Themes.Default/TextBox.xaml → src/Avalonia.Themes.Default/Controls/TextBox.xaml

0
src/Avalonia.Themes.Default/TimePicker.xaml → src/Avalonia.Themes.Default/Controls/TimePicker.xaml

0
src/Avalonia.Themes.Default/TitleBar.xaml → src/Avalonia.Themes.Default/Controls/TitleBar.xaml

0
src/Avalonia.Themes.Default/ToggleButton.xaml → src/Avalonia.Themes.Default/Controls/ToggleButton.xaml

0
src/Avalonia.Themes.Default/ToggleSwitch.xaml → src/Avalonia.Themes.Default/Controls/ToggleSwitch.xaml

0
src/Avalonia.Themes.Default/ToolTip.xaml → src/Avalonia.Themes.Default/Controls/ToolTip.xaml

0
src/Avalonia.Themes.Default/TreeView.xaml → src/Avalonia.Themes.Default/Controls/TreeView.xaml

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

Loading…
Cancel
Save