Changed behavior to accept keyboard overrides, added keyboard mouse state validator and indirect rules to allow keyboard and mouse navigation

This commit is contained in:
Ano-sys
2026-04-03 02:22:57 +02:00
parent 162df64596
commit d25e8238f2
4 changed files with 213 additions and 75 deletions
+72 -61
View File
@@ -29,6 +29,12 @@ public static class CardHoverEffectBehavior
typeof(CardHoverEffectBehavior),
0.99);
public static readonly AttachedProperty<bool> SuppressPointerHoverProperty =
AvaloniaProperty.RegisterAttached<Control, bool>(
"SuppressPointerHover",
typeof(CardHoverEffectBehavior),
false);
static CardHoverEffectBehavior()
{
IsEnabledProperty.Changed.AddClassHandler<Control>(OnIsEnabledChanged);
@@ -43,10 +49,64 @@ public static class CardHoverEffectBehavior
public static double GetScaleFactor(AvaloniaObject obj) => obj.GetValue(ScaleFactorProperty);
public static void SetScaleFactor(AvaloniaObject obj, double value) => obj.SetValue(ScaleFactorProperty, value);
public static bool GetSuppressPointerHover(AvaloniaObject obj) => obj.GetValue(SuppressPointerHoverProperty);
public static void SetSuppressPointerHover(AvaloniaObject obj, bool value) => obj.SetValue(SuppressPointerHoverProperty, value);
public static void ApplyHover(Control element)
{
element.ZIndex = 10;
var visual = ElementComposition.GetElementVisual(element);
var compositor = visual?.Compositor;
if (visual is null || compositor is null) return;
var scaleFactor = (float)GetScaleFactor(element);
var width = (float)element.Bounds.Width;
var height = (float)element.Bounds.Height;
if (width <= 0 || height <= 0) return;
visual.CenterPoint = new Vector3(width / 2f, height / 2f, 0f);
var scaleAnimation = compositor.CreateVector3KeyFrameAnimation();
scaleAnimation.InsertKeyFrame(1.0f, new Vector3(scaleFactor, scaleFactor, 1f));
scaleAnimation.Duration = _animationDuration;
var orientationAnimation = compositor.CreateQuaternionKeyFrameAnimation();
orientationAnimation.InsertKeyFrame(1.0f, Quaternion.Identity);
orientationAnimation.Duration = _animationDuration;
visual.StartAnimation("Scale", scaleAnimation);
visual.StartAnimation(nameof(visual.Orientation), orientationAnimation);
}
public static void ResetHover(Control element)
{
element.ZIndex = 0;
var visual = ElementComposition.GetElementVisual(element);
var compositor = visual?.Compositor;
if (visual is null || compositor is null) return;
var scaleAnimation = compositor.CreateVector3KeyFrameAnimation();
scaleAnimation.InsertKeyFrame(1.0f, new Vector3(1f, 1f, 1f));
scaleAnimation.Duration = _animationDuration;
var orientationAnimation = compositor.CreateQuaternionKeyFrameAnimation();
orientationAnimation.InsertKeyFrame(1.0f, Quaternion.Identity);
orientationAnimation.Duration = _animationDuration;
visual.StartAnimation("Scale", scaleAnimation);
visual.StartAnimation(nameof(visual.Orientation), orientationAnimation);
}
private static void OnIsEnabledChanged(Control c, AvaloniaPropertyChangedEventArgs e)
{
if (e.NewValue is not bool enabled)
return;
if (e.NewValue is not bool enabled) return;
if (enabled)
{
@@ -64,55 +124,30 @@ public static class CardHoverEffectBehavior
private static void Element_PointerEntered(object? sender, PointerEventArgs e)
{
if (sender is not Control element)
return;
if (sender is not Control element || GetSuppressPointerHover(element)) return;
ApplyHover(element);
}
element.ZIndex = 10;
var visual = ElementComposition.GetElementVisual(element);
var compositor = visual?.Compositor;
if (visual is null || compositor is null)
return;
var scaleFactor = (float)GetScaleFactor(element);
var width = (float)element.Bounds.Width;
var height = (float)element.Bounds.Height;
if (width <= 0 || height <= 0)
return;
visual.CenterPoint = new Vector3(width / 2f, height / 2f, 0f);
var scaleAnimation = compositor.CreateVector3KeyFrameAnimation();
scaleAnimation.InsertKeyFrame(1.0f, new Vector3(scaleFactor, scaleFactor, 1f));
scaleAnimation.Duration = _animationDuration;
var orientationAnimation = compositor.CreateQuaternionKeyFrameAnimation();
orientationAnimation.InsertKeyFrame(1.0f, Quaternion.Identity);
orientationAnimation.Duration = _animationDuration;
visual.StartAnimation("Scale", scaleAnimation);
visual.StartAnimation(nameof(visual.Orientation), orientationAnimation);
private static void Element_PointerExited(object? sender, PointerEventArgs e)
{
if (sender is not Control element || GetSuppressPointerHover(element)) return;
ResetHover(element);
}
private static void Element_PointerMoved(object? sender, PointerEventArgs e)
{
if (sender is not Control element)
return;
if (sender is not Control element || GetSuppressPointerHover(element)) return;
var visual = ElementComposition.GetElementVisual(element);
if (visual is null)
return;
if (visual is null) return;
var maxRotationAngle = (float)GetMaxRotationAngle(element);
var width = element.Bounds.Width;
var height = element.Bounds.Height;
if (width <= 0 || height <= 0)
return;
if (width <= 0 || height <= 0) return;
var position = e.GetPosition(element);
var centerX = width / 2.0;
@@ -132,28 +167,4 @@ public static class CardHoverEffectBehavior
visual.Orientation = qy * qx;
}
private static void Element_PointerExited(object? sender, PointerEventArgs e)
{
if (sender is not Control element)
return;
element.ZIndex = 0;
var visual = ElementComposition.GetElementVisual(element);
var compositor = visual?.Compositor;
if (visual is null || compositor is null)
return;
var scaleAnimation = compositor.CreateVector3KeyFrameAnimation();
scaleAnimation.InsertKeyFrame(1.0f, new Vector3(1f, 1f, 1f));
scaleAnimation.Duration = _animationDuration;
var orientationAnimation = compositor.CreateQuaternionKeyFrameAnimation();
orientationAnimation.InsertKeyFrame(1.0f, Quaternion.Identity);
orientationAnimation.Duration = _animationDuration;
visual.StartAnimation("Scale", scaleAnimation);
visual.StartAnimation(nameof(visual.Orientation), orientationAnimation);
}
}