Multi-Platform Package Manager for Stable Diffusion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

107 lines
3.5 KiB

using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Rendering.Composition;
namespace StabilityMatrix.Avalonia.Animations;
public class ItemsRepeaterArrangeAnimation : AvaloniaObject
{
public static readonly AttachedProperty<bool> EnableItemsArrangeAnimationProperty =
AvaloniaProperty.RegisterAttached<ItemsRepeater, bool>(
"EnableItemsArrangeAnimation",
typeof(ItemsRepeaterArrangeAnimation)
);
static ItemsRepeaterArrangeAnimation()
{
EnableItemsArrangeAnimationProperty.Changed.AddClassHandler<ItemsRepeater>(
OnEnableItemsArrangeAnimationChanged
);
}
private static void OnEnableItemsArrangeAnimationChanged(
ItemsRepeater itemsRepeater,
AvaloniaPropertyChangedEventArgs eventArgs
)
{
if (eventArgs.NewValue is true)
{
itemsRepeater.ElementPrepared += OnElementPrepared;
itemsRepeater.ElementIndexChanged += OnElementIndexChanged;
}
else
{
// itemsRepeater.Opened -= OnOpened;
}
}
private static void CreateAnimation(Visual item)
{
var compositionVisual =
ElementComposition.GetElementVisual(item) ?? throw new NullReferenceException();
if (compositionVisual.ImplicitAnimations is { } animations && animations.HasKey("Offset"))
{
return;
}
var compositor = compositionVisual.Compositor;
var offsetAnimation = compositor.CreateVector3KeyFrameAnimation();
offsetAnimation.Target = "Offset";
// Using the "this.FinalValue" to indicate the last value of the Offset property
offsetAnimation.InsertExpressionKeyFrame(1.0f, "this.FinalValue");
offsetAnimation.Duration = TimeSpan.FromMilliseconds(150);
// Create a new implicit animation collection and bind the offset animation
var implicitAnimationCollection = compositor.CreateImplicitAnimationCollection();
implicitAnimationCollection["Offset"] = offsetAnimation;
compositionVisual.ImplicitAnimations = implicitAnimationCollection;
}
private static void OnElementPrepared(object? sender, ItemsRepeaterElementPreparedEventArgs e)
{
if (
sender is not ItemsRepeater itemsRepeater
|| !GetEnableItemsArrangeAnimation(itemsRepeater)
)
return;
CreateAnimation(itemsRepeater);
}
private static void OnElementIndexChanged(
object? sender,
ItemsRepeaterElementIndexChangedEventArgs e
)
{
if (
sender is not ItemsRepeater itemsRepeater
|| !GetEnableItemsArrangeAnimation(itemsRepeater)
)
return;
CreateAnimation(itemsRepeater);
}
/*private static void OnOpened(object sender, EventArgs e)
{
if (sender is not WindowBase windowBase || !GetEnableScaleShowAnimation(windowBase))
return;
// Here we explicitly animate the "Scale" property
// The implementation is the same as `Offset` at the beginning, but just with the Scale property
windowBase.StartWindowScaleAnimation();
}*/
public static bool GetEnableItemsArrangeAnimation(ItemsRepeater element)
{
return element.GetValue(EnableItemsArrangeAnimationProperty);
}
public static void SetEnableItemsArrangeAnimation(ItemsRepeater element, bool value)
{
element.SetValue(EnableItemsArrangeAnimationProperty, value);
}
}