123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- using Avalonia;
- using Avalonia.Animation;
- using Avalonia.Animation.Easings;
- using Avalonia.Controls;
- using Avalonia.Controls.Primitives;
- using Avalonia.Controls.Templates;
- using Avalonia.Data;
- using Avalonia.LogicalTree;
- using Avalonia.Markup.Xaml;
- using Avalonia.Styling;
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.Linq;
- using System.Threading;
- using System.Threading.Tasks;
- namespace SukiUI.Controls;
- public class SettingsLayoutItem
- {
- public string Header { get; set; }
- public Control Content { get; set; }
- }
- public partial class SettingsLayout : UserControl
- {
- public SettingsLayout()
- {
- InitializeComponent();
- }
- protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
- {
- base.OnApplyTemplate(e);
- UpdateItems();
- }
- protected override void OnDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
- {
- }
- private void InitializeComponent()
- {
- AvaloniaXamlLoader.Load(this);
- }
- private ObservableCollection<SettingsLayoutItem> _items;
- public static readonly DirectProperty<SettingsLayout, ObservableCollection<SettingsLayoutItem>> StepsProperty =
- AvaloniaProperty.RegisterDirect<SettingsLayout, ObservableCollection<SettingsLayoutItem>>(nameof(Items),
- l => l.Items,
- (numpicker, v) => { numpicker.Items = v; }, defaultBindingMode: BindingMode.TwoWay,
- enableDataValidation: true);
- public ObservableCollection<SettingsLayoutItem> Items
- {
- get { return _items; }
- set { SetAndRaise(StepsProperty, ref _items, value); }
- }
- private void UpdateItems()
- {
- if (Items is null)
- {
- return;
- }
- var stackSummary = (StackPanel)this.GetTemplateChildren().First(n => n.Name == "StackSummary");
- var myScroll = (ScrollViewer)this.GetTemplateChildren().First(n => n.Name == "MyScroll");
- if (myScroll.Content is not StackPanel stackItems)
- return;
- stackItems.Children.Clear();
- stackSummary.Children.Clear();
- var radios = new List<RadioButton>();
- var borders = new List<Border>();
- stackItems.Children.Add(new Border() { Height = 8 });
- foreach (var settingsLayoutItem in Items)
- {
- var border = new Border
- {
- Child = new GroupBox()
- {
- Margin = new Thickness(10, 20),
- Header = new TextBlock() { Text = settingsLayoutItem.Header },
- Content = new Border()
- {
- Margin = new Thickness(35, 12),
- Child = settingsLayoutItem.Content
- }
- }
- };
- borders.Add(border);
- stackItems.Children.Add(border);
- var summaryButton = new RadioButton()
- {
- Content = new TextBlock() { Text = settingsLayoutItem.Header, FontSize = 17 },
- Classes = { "MenuChip" }
- };
- summaryButton.Click += async (sender, args) =>
- {
- if (isAnimatingScroll)
- return;
- var x = border.TranslatePoint(new Point(), stackItems);
- if (x.HasValue)
- await AnimateScroll(x.Value.Y); // myScroll.Offset = new Vector(0, x.Value.Y);
- };
- radios.Add(summaryButton);
- stackSummary.Children.Add(summaryButton);
- }
- stackSummary.Children.Add(new Border() { Height = 300 });
- myScroll.ScrollChanged += (sender, args) =>
- {
- if (isAnimatingScroll)
- return;
- var OffsetY = myScroll.Offset.Y;
- var l = borders.Select(b => Math.Abs(b.TranslatePoint(new Point(), stackItems).Value.Y - OffsetY)).ToList();
- radios[l.IndexOf(l.Min())].IsChecked = true;
- };
- }
- private Mutex mut = new Mutex();
- private double LastDesiredSize = -1;
- private async void DockPanel_SizeChanged(object sender, SizeChangedEventArgs e)
- {
- var stack = this.GetTemplateChildren().First(n => n.Name == "StackSummary");
- var desiredSize = e.NewSize.Width > 1100 ? 400 : 0;
- if (LastDesiredSize == desiredSize)
- return;
- LastDesiredSize = desiredSize;
- if (stack.Width != desiredSize && (stack.Width == 0 || stack.Width == 400))
- stack.Animate<double>(WidthProperty, stack.Width, desiredSize, TimeSpan.FromMilliseconds(800));
- }
- private bool isAnimatingWidth = false;
- private bool isAnimatingMargin = false;
- private bool isAnimatingScroll = false;
- private async Task AnimateScroll(double desiredScroll)
- {
- isAnimatingScroll = true;
- var myscroll = (ScrollViewer)this.GetTemplateChildren().First(n => n.Name == "MyScroll");
- var animationTask = new Animation
- {
- Duration = TimeSpan.FromMilliseconds(800),
- FillMode = FillMode.Forward,
- Easing = new CubicEaseInOut(),
- IterationCount = new IterationCount(1),
- PlaybackDirection = PlaybackDirection.Normal,
- Children =
- {
- new KeyFrame()
- {
- Setters = { new Setter { Property = ScrollViewer.OffsetProperty, Value = myscroll.Offset } },
- KeyTime = TimeSpan.FromSeconds(0)
- },
- new KeyFrame()
- {
- Setters =
- {
- new Setter
- {
- Property = ScrollViewer.OffsetProperty,
- Value = new Vector(myscroll.Offset.X, desiredScroll - 30)
- }
- },
- KeyTime = TimeSpan.FromMilliseconds(800)
- }
- }
- }.RunAsync(myscroll);
- var abortTask = Task.Run(async () =>
- {
- await Task.Delay(1000);
- isAnimatingScroll = false;
- });
- await Task.WhenAll(animationTask, abortTask);
- }
- }
|