diff --git a/src/Avalonia.Controls/MenuItem.cs b/src/Avalonia.Controls/MenuItem.cs
index 3d8ab3ae48..7d4fef009d 100644
--- a/src/Avalonia.Controls/MenuItem.cs
+++ b/src/Avalonia.Controls/MenuItem.cs
@@ -101,7 +101,7 @@ namespace Avalonia.Controls
private ICommand? _command;
private bool _commandCanExecute = true;
- private Popup _popup;
+ private Popup? _popup;
///
/// Initializes static members of the class.
@@ -145,7 +145,7 @@ namespace Avalonia.Controls
{
var parent = x as Control;
return parent?.GetObservable(DefinitionBase.PrivateSharedSizeScopeProperty) ??
- Observable.Return(null);
+ Observable.Return(null);
});
this.Bind(DefinitionBase.PrivateSharedSizeScopeProperty, parentSharedSizeScope);
diff --git a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
index 6d6398bcda..a54d1ce308 100644
--- a/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
+++ b/src/Avalonia.Controls/Platform/DefaultMenuInteractionHandler.cs
@@ -148,6 +148,7 @@ namespace Avalonia.Controls.Platform
{
case Key.Up:
case Key.Down:
+ {
if (item?.IsTopLevel == true)
{
if (item.HasSubMenu && !item.IsSubMenuOpen)
@@ -161,8 +162,10 @@ namespace Avalonia.Controls.Platform
goto default;
}
break;
+ }
case Key.Left:
+ {
if (item?.Parent is IMenuItem parent && !parent.IsTopLevel && parent.IsSubMenuOpen)
{
parent.Close();
@@ -174,8 +177,10 @@ namespace Avalonia.Controls.Platform
goto default;
}
break;
+ }
case Key.Right:
+ {
if (item != null && !item.IsTopLevel && item.HasSubMenu)
{
Open(item, true);
@@ -186,8 +191,10 @@ namespace Avalonia.Controls.Platform
goto default;
}
break;
+ }
case Key.Enter:
+ {
if (item != null)
{
if (!item.HasSubMenu)
@@ -202,12 +209,14 @@ namespace Avalonia.Controls.Platform
e.Handled = true;
}
break;
+ }
case Key.Escape:
- if (item?.Parent != null)
+ {
+ if (item?.Parent is IMenuElement parent)
{
- item.Parent.Close();
- item.Parent.Focus();
+ parent.Close();
+ parent.Focus();
}
else
{
@@ -216,8 +225,10 @@ namespace Avalonia.Controls.Platform
e.Handled = true;
break;
+ }
default:
+ {
var direction = e.Key.ToNavigationDirection();
if (direction.HasValue)
@@ -246,6 +257,7 @@ namespace Avalonia.Controls.Platform
}
break;
+ }
}
if (!e.Handled && item?.Parent is IMenuItem parentItem)
diff --git a/src/Avalonia.Visuals/Animation/CompositePageTransition.cs b/src/Avalonia.Visuals/Animation/CompositePageTransition.cs
new file mode 100644
index 0000000000..9489914c97
--- /dev/null
+++ b/src/Avalonia.Visuals/Animation/CompositePageTransition.cs
@@ -0,0 +1,61 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using Avalonia.Metadata;
+
+namespace Avalonia.Animation
+{
+ ///
+ /// Defines a composite page transition that can be used to combine multiple transitions.
+ ///
+ ///
+ ///
+ /// Instantiate the in XAML and initialize the
+ /// property in order to have many animations triggered at once.
+ /// For example, you can combine and .
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// ]]>
+ ///
+ ///
+ ///
+ public class CompositePageTransition : IPageTransition
+ {
+ ///
+ /// Gets or sets the transitions to be executed. Can be defined from XAML.
+ ///
+ [Content]
+ public List PageTransitions { get; set; } = new List();
+
+ ///
+ /// Starts the animation.
+ ///
+ ///
+ /// The control that is being transitioned away from. May be null.
+ ///
+ ///
+ /// The control that is being transitioned to. May be null.
+ ///
+ ///
+ /// Defines the direction of the transition.
+ ///
+ ///
+ /// A that tracks the progress of the animation.
+ ///
+ public Task Start(Visual from, Visual to, bool forward)
+ {
+ var transitionTasks = PageTransitions
+ .Select(transition => transition.Start(from, to, forward))
+ .ToList();
+ return Task.WhenAll(transitionTasks);
+ }
+ }
+}
diff --git a/src/Avalonia.Visuals/Animation/CrossFade.cs b/src/Avalonia.Visuals/Animation/CrossFade.cs
index 640f401418..0615b854da 100644
--- a/src/Avalonia.Visuals/Animation/CrossFade.cs
+++ b/src/Avalonia.Visuals/Animation/CrossFade.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Avalonia.Animation.Easings;
using Avalonia.Styling;
using Avalonia.VisualTree;
@@ -74,14 +75,26 @@ namespace Avalonia.Animation
///
public TimeSpan Duration
{
- get
- {
- return _fadeOutAnimation.Duration;
- }
- set
- {
- _fadeOutAnimation.Duration = _fadeInAnimation.Duration = value;
- }
+ get => _fadeOutAnimation.Duration;
+ set => _fadeOutAnimation.Duration = _fadeInAnimation.Duration = value;
+ }
+
+ ///
+ /// Gets or sets element entrance easing.
+ ///
+ public Easing FadeInEasing
+ {
+ get => _fadeInAnimation.Easing;
+ set => _fadeInAnimation.Easing = value;
+ }
+
+ ///
+ /// Gets or sets element exit easing.
+ ///
+ public Easing FadeOutEasing
+ {
+ get => _fadeOutAnimation.Easing;
+ set => _fadeOutAnimation.Easing = value;
}
///
diff --git a/src/Avalonia.Visuals/Animation/PageSlide.cs b/src/Avalonia.Visuals/Animation/PageSlide.cs
index 501c8c0ba4..dd5d598e12 100644
--- a/src/Avalonia.Visuals/Animation/PageSlide.cs
+++ b/src/Avalonia.Visuals/Animation/PageSlide.cs
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
+using Avalonia.Animation.Easings;
using Avalonia.Media;
using Avalonia.Styling;
using Avalonia.VisualTree;
@@ -48,6 +49,16 @@ namespace Avalonia.Animation
/// Gets the duration of the animation.
///
public SlideAxis Orientation { get; set; }
+
+ ///
+ /// Gets or sets element entrance easing.
+ ///
+ public Easing SlideInEasing { get; set; } = new LinearEasing();
+
+ ///
+ /// Gets or sets element exit easing.
+ ///
+ public Easing SlideOutEasing { get; set; } = new LinearEasing();
///
/// Starts the animation.
@@ -75,18 +86,12 @@ namespace Avalonia.Animation
{
var animation = new Animation
{
- Children =
+ Easing = SlideOutEasing,
+ Children =
{
new KeyFrame
{
- Setters =
- {
- new Setter
- {
- Property = translateProperty,
- Value = 0d
- }
- },
+ Setters = { new Setter { Property = translateProperty, Value = 0d } },
Cue = new Cue(0d)
},
new KeyFrame
@@ -100,10 +105,10 @@ namespace Avalonia.Animation
}
},
Cue = new Cue(1d)
- }
- }
+ }
+ },
+ Duration = Duration
};
- animation.Duration = Duration;
tasks.Add(animation.RunAsync(from));
}
@@ -112,9 +117,9 @@ namespace Avalonia.Animation
to.IsVisible = true;
var animation = new Animation
{
+ Easing = SlideInEasing,
Children =
{
-
new KeyFrame
{
Setters =
@@ -129,19 +134,12 @@ namespace Avalonia.Animation
},
new KeyFrame
{
- Setters =
- {
- new Setter
- {
- Property = translateProperty,
- Value = 0d
- }
- },
+ Setters = { new Setter { Property = translateProperty, Value = 0d } },
Cue = new Cue(1d)
}
- }
+ },
+ Duration = Duration
};
- animation.Duration = Duration;
tasks.Add(animation.RunAsync(to));
}