using Avalonia; using Avalonia.Animation; using Avalonia.Animation.Easings; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Input; using Avalonia.Media; using Avalonia.VisualTree; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Windows.Input; namespace LANCommander.Launcher.Controls; public class CarouselControl : TemplatedControl { public static readonly StyledProperty ItemsSourceProperty = AvaloniaProperty.Register(nameof(ItemsSource)); public static readonly StyledProperty ItemWidthProperty = AvaloniaProperty.Register(nameof(ItemWidth), 200); public static readonly StyledProperty GapProperty = AvaloniaProperty.Register(nameof(Gap), 10); public static readonly StyledProperty VisibleItemsProperty = AvaloniaProperty.Register(nameof(VisibleItems), 3); public static readonly StyledProperty SelectedIndexProperty = AvaloniaProperty.Register(nameof(SelectedIndex), 0); public static readonly StyledProperty TitleProperty = AvaloniaProperty.Register(nameof(Title)); public static readonly StyledProperty ItemTemplateProperty = AvaloniaProperty.Register(nameof(ItemTemplate)); public static readonly StyledProperty SeeAllCommandProperty = AvaloniaProperty.Register(nameof(SeeAllCommand)); public static readonly StyledProperty IsInfiniteProperty = AvaloniaProperty.Register(nameof(IsInfinite), false); public static readonly StyledProperty WrapItemsProperty = AvaloniaProperty.Register(nameof(WrapItems), false); public static readonly StyledProperty ItemOverflowProperty = AvaloniaProperty.Register(nameof(ItemOverflow), 0); public IEnumerable? ItemsSource { get => GetValue(ItemsSourceProperty); set => SetValue(ItemsSourceProperty, value); } public double ItemWidth { get => GetValue(ItemWidthProperty); set => SetValue(ItemWidthProperty, value); } public double Gap { get => GetValue(GapProperty); set => SetValue(GapProperty, value); } public int VisibleItems { get => GetValue(VisibleItemsProperty); set => SetValue(VisibleItemsProperty, value); } public int SelectedIndex { get => GetValue(SelectedIndexProperty); set => SetValue(SelectedIndexProperty, value); } public string? Title { get => GetValue(TitleProperty); set => SetValue(TitleProperty, value); } public IDataTemplate? ItemTemplate { get => GetValue(ItemTemplateProperty); set => SetValue(ItemTemplateProperty, value); } public ICommand? SeeAllCommand { get => GetValue(SeeAllCommandProperty); set => SetValue(SeeAllCommandProperty, value); } public bool IsInfinite { get => GetValue(IsInfiniteProperty); set => SetValue(IsInfiniteProperty, value); } public bool WrapItems { get => GetValue(WrapItemsProperty); set => SetValue(WrapItemsProperty, value); } public double ItemOverflow { get => GetValue(ItemOverflowProperty); set => SetValue(ItemOverflowProperty, value); } private Control? _itemsContainer; private Control? _clipPanel; private ItemsControl? _itemsControl; private Button? _leftButton; private Button? _rightButton; private Transitions? _transitions; private RectangleGeometry? _clipGeometry; private int _virtualIndex = 0; static CarouselControl() { ItemsSourceProperty.Changed.AddClassHandler((c, _) => c.RebuildInternalSource()); WrapItemsProperty.Changed.AddClassHandler((c, _) => { c.RebuildInternalSource(); c.UpdateClipGeometry(); }); ItemOverflowProperty.Changed.AddClassHandler((c, _) => c.ApplyItemOverflow()); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); _itemsContainer = e.NameScope.Find("PART_ItemsContainer"); _clipPanel = e.NameScope.Find("PART_ClipPanel"); _itemsControl = e.NameScope.Find("PART_ItemsControl"); _leftButton = e.NameScope.Find