diff --git a/GSS2.UI.Core/SectionPanel.cs b/GSS2.UI.Core/SectionPanel.cs index f1b5089..99db317 100644 --- a/GSS2.UI.Core/SectionPanel.cs +++ b/GSS2.UI.Core/SectionPanel.cs @@ -1,5 +1,6 @@ using System.Collections; using System.Collections.Specialized; +using System.Diagnostics; using Avalonia; using Avalonia.Animation; @@ -76,24 +77,35 @@ public class SectionPanel : Panel get => GetValue(ChildrenSourceProperty); set => SetValue(ChildrenSourceProperty, value); } - public static readonly StyledProperty ChildrenTemplateProperty = AvaloniaProperty.Register(nameof(ChildrenTemplate), null); + public static readonly StyledProperty ChildrenTemplateProperty = AvaloniaProperty.Register(nameof(ChildrenTemplate), null); public IDataTemplate? ChildrenTemplate { get => GetValue(ChildrenTemplateProperty); set => SetValue(ChildrenTemplateProperty, value); } + public static readonly StyledProperty IsScrollingProperty = AvaloniaProperty.Register(nameof(IsScrolling), false, defaultBindingMode: Avalonia.Data.BindingMode.OneWayToSource); + public bool IsScrolling + { + get => GetValue(IsScrollingProperty); + set => SetValue(IsScrollingProperty, value); + } + private readonly Dictionary _childIndeces = new Dictionary(); private bool _initialized = false; private int _previousIndex = 0; + private bool _isChangingIndex = false; public SectionPanel() : base() { CurrentIndexProperty.Changed.AddClassHandler((panel, ea) => { - CanScrollForward = Cyclic || CurrentIndex != Children.Count() - 1; - CanScrollBackward = Cyclic || CurrentIndex != 0; + if (panel != this) + return; + panel.CanScrollBackward = panel.Cyclic || panel.CurrentIndex != 0; + panel.CanScrollForward = panel.Cyclic || panel.CurrentIndex != panel.Children.Count() - 1; + _isChangingIndex = true; panel.InvalidateArrange(); }); ChildrenSourceProperty.Changed.AddClassHandler((panel, ea) => @@ -111,10 +123,11 @@ public class SectionPanel : Panel else controls = enumerable.Cast() .Where(ChildrenTemplate.Match) - .Select(i => + .Select((vm, i) => { var control = ChildrenTemplate.Build(i); - control?.DataContext = i; + control?.DataContext = vm; + control?.Name = $"Элемент {i}"; return control; }) .OfType(); @@ -127,7 +140,6 @@ public class SectionPanel : Panel _childIndeces.Clear(); foreach (var (i, child) in Children.Enumerate()) _childIndeces.Add(child, i); - _initialized = true; } } panel.InvalidateArrange(); @@ -157,19 +169,19 @@ public class SectionPanel : Panel controls = ea.NewItems.OfType(); else controls = ea.NewItems.Cast() - .Where(ChildrenTemplate.Match) - .Select(i => - { - var control = ChildrenTemplate.Build(i); - control?.DataContext = i; - return control; - }) - .OfType(); + .Where(ChildrenTemplate.Match) + .Select((vm, i) => + { + var control = ChildrenTemplate.Build(i); + control?.DataContext = vm; + control?.Name = $"Элемент {i}"; + return control; + }) + .OfType(); foreach (Control control in controls) Children.Insert(index++, control); - break; } @@ -232,10 +244,11 @@ public class SectionPanel : Panel else controls = ChildrenSource.Cast() .Where(ChildrenTemplate.Match) - .Select(i => + .Select((vm, i) => { var control = ChildrenTemplate.Build(i); - control?.DataContext = i; + control?.DataContext = vm; + control?.Name = $"Элемент {i}"; return control; }) .OfType(); @@ -261,8 +274,6 @@ public class SectionPanel : Panel return; } - Console.WriteLine($"{e.NewSize} {e.PreviousSize}"); - foreach (var (child, i) in _childIndeces) { var transform = child.RenderTransform as TranslateTransform; @@ -271,7 +282,6 @@ public class SectionPanel : Panel transform = new TranslateTransform(); child.RenderTransform = transform; } - Console.WriteLine($"{i} {transform}"); if (child.RenderTransformOrigin != RelativePoint.TopLeft) child.RenderTransformOrigin = RelativePoint.TopLeft; @@ -281,7 +291,6 @@ public class SectionPanel : Panel Orientation.Horizontal => transform.X += transform.X == 0 ? 0 : e.PreviousSize.Width - e.NewSize.Width, _ => 0 }; - Console.WriteLine($"{i} {transform}"); } base.OnSizeChanged(e); } @@ -300,18 +309,21 @@ public class SectionPanel : Panel _initialized = true; } - foreach (var (child, i) in _childIndeces) - { - var rect = Orientation switch + if (!_isChangingIndex) + foreach (var (child, i) in _childIndeces) { - Orientation.Vertical => new Rect(0, i * finalSize.Height, finalSize.Width, finalSize.Height), - Orientation.Horizontal => new Rect(i * finalSize.Width, 0, finalSize.Width, finalSize.Height), - _ => default - }; - child.Arrange(rect); - } + var rect = Orientation switch + { + Orientation.Vertical => new Rect(0, (i - _previousIndex) * finalSize.Height, finalSize.Width, finalSize.Height), + Orientation.Horizontal => new Rect((i - _previousIndex) * finalSize.Width, 0, finalSize.Width, finalSize.Height), + _ => default + }; + child.Arrange(rect); + } if (Children.Count() > 1) Dispatcher.UIThread.Post(async () => _ = ApplyOffset(finalSize, true), DispatcherPriority.Render); + + _isChangingIndex = false; return finalSize; } @@ -333,6 +345,7 @@ public class SectionPanel : Panel var newIndex = firstIndex - 1; var (child, _) = _childIndeces.MaxBy(ch => ch.Value); InstantTransform(child, -Children.Count(), size); + _childIndeces[child] = newIndex; } @@ -342,24 +355,23 @@ public class SectionPanel : Panel var newIndex = lastIndex + 1; var (child, _) = _childIndeces.MinBy(ch => ch.Value); InstantTransform(child, Children.Count(), size); + _childIndeces[child] = newIndex; } List animations = new List(); - foreach (var (i, child) in Children.Enumerate()) + double offset = Orientation switch { - double offset = Orientation switch - { - Orientation.Vertical => -indexSingleShift * size.Height, - Orientation.Horizontal => -indexSingleShift * size.Width, - _ => 0 - }; + Orientation.Vertical => -indexSingleShift * size.Height, + Orientation.Horizontal => -indexSingleShift * size.Width, + _ => 0 + }; + foreach (var (i, child) in Children.Enumerate()) if (!animate || !EnableAnimation) InstantTransform(child, offset); else animations.Add(AnimationTransform(child, offset, Math.Abs(indexShift))); - } if (animations.Count() > 0) await Task.WhenAll(animations); @@ -380,12 +392,14 @@ public class SectionPanel : Panel if (control.RenderTransformOrigin != RelativePoint.TopLeft) control.RenderTransformOrigin = RelativePoint.TopLeft; - if (Orientation is Orientation.Vertical) - transform.Y += offset * (size is null ? 1 : size.Value.Height); - else - transform.X += offset * (size is null ? 1 : size.Value.Width); + _ = Orientation switch + { + Orientation.Vertical => transform.Y += offset * (size is null ? 1 : size.Value.Height), + Orientation.Horizontal => transform.X += offset * (size is null ? 1 : size.Value.Width), + _ => throw new UnreachableException(), + }; } - private Task AnimationTransform(Control control, double offset, double speedRatio) + private Task AnimationTransform(Control control, double offset, double speedRatio, Size? size = null) { var transform = control.RenderTransform as TranslateTransform; if (transform is null) @@ -407,13 +421,18 @@ public class SectionPanel : Panel Cue = new Cue(1), Setters = { - Orientation is Orientation.Vertical ? - new Setter(TranslateTransform.YProperty, transform.Y + offset) : - new Setter(TranslateTransform.XProperty, transform.X + offset) + Orientation switch + { + Orientation.Vertical => new Setter(TranslateTransform.YProperty, transform.Y + offset * (size is null ? 1 : size.Value.Height)), + Orientation.Horizontal => new Setter(TranslateTransform.XProperty, transform.X + offset * (size is null ? 1 : size.Value.Width)), + _ => throw new UnreachableException(), + } } } } }; - return animation.RunAsync(control); + + IsScrolling = true; + return animation.RunAsync(control).ContinueWith(_ => Dispatcher.UIThread.Invoke(() => IsScrolling = false)); } } \ No newline at end of file diff --git a/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs b/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs index ed38f43..7b87c95 100644 --- a/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs +++ b/GSS2.UI.Core/ViewModels/AmineContentSeparatorCalibrationViewModel.cs @@ -33,7 +33,9 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase [ObservableProperty] private bool _isNewRecord = false; [ObservableProperty] private int _mainSectionsCurrentIndex = 0; - [ObservableProperty] private string _switchMainSectionButtonText = "К изображениям"; + [ObservableProperty] private bool _mainSectionCanScrollBackward = false; + [ObservableProperty] private bool _mainSectionCanScrollForward = true; + [ObservableProperty] private bool _mainSectionIsScrolling = true; [ObservableProperty] private Task? _captureImagesTask = null; @@ -43,6 +45,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase [ObservableProperty] private int _imagesSectionCurrentIndex = 0; [ObservableProperty] private bool _imagesSectionCanScrollForward = false; [ObservableProperty] private bool _imagesSectionCanScrollBackward = false; + [ObservableProperty] private bool _imagesSectionIsScrolling = true; public AmineContentSeparatorCalibrationViewModel(ILogger logger, AmineContentCalibrationContext context, IlluminatorService illuminatorService, CameraService cameraService, ImageStorageService imageStorageService) { @@ -121,7 +124,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase var deletedIsNewRecord = IsNewRecord; IsNewRecord = true; CreateRecord(); - + if (!deletedIsNewRecord) { Records.Remove(deletedRecord); @@ -155,14 +158,7 @@ public partial class AmineContentSeparatorCalibrationViewModel : ViewModelBase IsNewRecord = false; } - [RelayCommand] - private void SwitchMainSection() - { - MainSectionsCurrentIndex = MainSectionsCurrentIndex == 0 ? 1 : 0; - SwitchMainSectionButtonText = MainSectionsCurrentIndex == 0 ? - "К изображениям" : - "К информации"; - } + [RelayCommand] private void SwitchMainSection() => MainSectionsCurrentIndex = MainSectionsCurrentIndex == 0 ? 1 : 0; [RelayCommand] private void CaptureImage() diff --git a/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml b/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml index 267cd8a..41e4e30 100644 --- a/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml +++ b/GSS2.UI.Core/Views/AmineContentSeparatorCalibrationView.axaml @@ -146,8 +146,11 @@ Grid.ColumnSpan="3" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" + CanScrollBackward="{Binding MainSectionCanScrollBackward}" + CanScrollForward="{Binding MainSectionCanScrollForward}" ClipToBounds="True" CurrentIndex="{Binding MainSectionsCurrentIndex}" + IsScrolling="{Binding MainSectionIsScrolling}" Orientation="Vertical"> @@ -223,8 +226,16 @@ VerticalContentAlignment="Center" Classes="vertical" Command="{Binding ImagesSectionPreviousCommand}" - Content="◀" - IsEnabled="{Binding ImagesSectionCanScrollBackward}" /> + Content="◀"> + + + + + + + + + @@ -343,8 +355,16 @@ VerticalContentAlignment="Center" Classes="vertical" Command="{Binding ImagesSectionNextCommand}" - Content="▶" - IsEnabled="{Binding ImagesSectionCanScrollForward}" /> + Content="▶"> + + + + + + + + + @@ -418,7 +438,34 @@ Grid.Column="2" HorizontalAlignment="Stretch" Command="{Binding SwitchMainSectionCommand}" - Content="{Binding SwitchMainSectionButtonText}" /> + Content="К информации" + IsVisible="{Binding MainSectionsCurrentIndex, Converter={StaticResource EqualsConverter}, ConverterParameter=1}"> + + + + + + + + + + +