From 115163963599c519f3d0ba2376f229538fb17d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9B=E5=B0=98=E7=A9=BA=E5=BF=A7?= Date: Tue, 12 Nov 2024 23:58:41 +0800 Subject: [PATCH 1/4] Add a new control AspectRatioLayout --- .../Pages/AspectRatioLayoutDemo.axaml | 28 ++ .../Pages/AspectRatioLayoutDemo.axaml.cs | 13 + .../AspectRatioLayoutDemoViewModel.cs | 5 + .../Ursa.Demo/ViewModels/MainViewViewModel.cs | 1 + demo/Ursa.Demo/ViewModels/MenuViewModel.cs | 2 + global.json | 2 +- .../AspectRatioLayout/AspectRatioLayout.cs | 262 ++++++++++++++++++ .../AspectRatioLayoutItem.cs | 17 ++ .../AspectRatioLayout/AspectRatioMode.cs | 9 + 9 files changed, 338 insertions(+), 1 deletion(-) create mode 100644 demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml create mode 100644 demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml.cs create mode 100644 demo/Ursa.Demo/ViewModels/AspectRatioLayoutDemoViewModel.cs create mode 100644 src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs create mode 100644 src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs create mode 100644 src/Ursa/Controls/AspectRatioLayout/AspectRatioMode.cs diff --git a/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml new file mode 100644 index 0000000..7d66922 --- /dev/null +++ b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml.cs b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml.cs new file mode 100644 index 0000000..c7fdad5 --- /dev/null +++ b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml.cs @@ -0,0 +1,13 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Ursa.Demo.Pages; + +public partial class AspectRatioLayoutDemo : UserControl +{ + public AspectRatioLayoutDemo() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/AspectRatioLayoutDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/AspectRatioLayoutDemoViewModel.cs new file mode 100644 index 0000000..bfd2b8a --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/AspectRatioLayoutDemoViewModel.cs @@ -0,0 +1,5 @@ +namespace Ursa.Demo.ViewModels; + +public class AspectRatioLayoutDemoViewModel : ViewModelBase +{ +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs index 24a21a6..3fc9e46 100644 --- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs @@ -77,6 +77,7 @@ public partial class MainViewViewModel : ViewModelBase MenuKeys.MenuKeyToolBar => new ToolBarDemoViewModel(), MenuKeys.MenuKeyTreeComboBox => new TreeComboBoxDemoViewModel(), MenuKeys.MenuKeyTwoTonePathIcon => new TwoTonePathIconDemoViewModel(), + MenuKeys.AspectRatioLayout => new AspectRatioLayoutDemoViewModel(), _ => throw new ArgumentOutOfRangeException(nameof(s), s, null) }; } diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs index e894420..7559eb7 100644 --- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs @@ -58,6 +58,7 @@ public class MenuViewModel : ViewModelBase new() { MenuHeader = "ToolBar", Key = MenuKeys.MenuKeyToolBar }, new() { MenuHeader = "TreeComboBox", Key = MenuKeys.MenuKeyTreeComboBox }, new() { MenuHeader = "TwoTonePathIcon", Key = MenuKeys.MenuKeyTwoTonePathIcon }, + new() { MenuHeader = "AspectRatioLayout", Key = MenuKeys.AspectRatioLayout ,Status = "WIP"}, }; } } @@ -111,4 +112,5 @@ public static class MenuKeys public const string MenuKeyToolBar = "ToolBar"; public const string MenuKeyTreeComboBox = "TreeComboBox"; public const string MenuKeyTwoTonePathIcon = "TwoTonePathIcon"; + public const string AspectRatioLayout = "AspectRatioLayout"; } \ No newline at end of file diff --git a/global.json b/global.json index b5b37b6..dad2db5 100644 --- a/global.json +++ b/global.json @@ -2,6 +2,6 @@ "sdk": { "version": "8.0.0", "rollForward": "latestMajor", - "allowPrerelease": false + "allowPrerelease": true } } \ No newline at end of file diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs new file mode 100644 index 0000000..e1f7da5 --- /dev/null +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs @@ -0,0 +1,262 @@ +using Avalonia; +using Avalonia.Animation; +using Avalonia.Animation.Easings; +using Avalonia.Controls; +using Avalonia.Metadata; +using Avalonia.Styling; + +namespace Ursa.Controls; + +public class AspectRatioLayout : TransitioningContentControl +{ + public static readonly StyledProperty> ItemsProperty = + AvaloniaProperty.Register>( + nameof(Items), new List()); + + public static readonly StyledProperty AspectRatioChangeAmbiguityProperty = + AvaloniaProperty.Register( + nameof(AspectRatioChangeAmbiguity), 0.2); + + public static readonly StyledProperty CurrentAspectRatioModeProperty = + AvaloniaProperty.Register( + nameof(CurrentAspectRatioMode)); + + public AspectRatioMode CurrentAspectRatioMode + { + get => GetValue(CurrentAspectRatioModeProperty); + set => SetValue(CurrentAspectRatioModeProperty, value); + } + + private readonly Queue _history = new(); + + static AspectRatioLayout() + { + PCrossFade pCrossFade = new() + { + Duration = TimeSpan.FromSeconds(0.55), + FadeInEasing = new QuadraticEaseInOut(), + FadeOutEasing = new QuadraticEaseInOut() + }; + PageTransitionProperty.OverrideDefaultValue(pCrossFade); + } + + protected override Type StyleKeyOverride => typeof(TransitioningContentControl); + + [Content] + public List Items + { + get => GetValue(ItemsProperty); + set => SetValue(ItemsProperty, value); + } + + public double AspectRatioChangeAmbiguity + { + get => GetValue(AspectRatioChangeAmbiguityProperty); + set => SetValue(AspectRatioChangeAmbiguityProperty, value); + } + + private void UpdataHistory(bool value) + { + _history.Enqueue(value); + while (_history.Count > 3) + _history.Dequeue(); + } + + private bool IsRightChanges() + { + //if (_history.Count < 3) return false; + return _history.All(x => x) || _history.All(x => !x); + } + + private AspectRatioMode GetScaleMode(Rect rect) + { + var scale = Math.Round(Math.Truncate(Math.Abs(rect.Width)) / Math.Truncate(Math.Abs(rect.Height)), 3); + var absA = Math.Abs(AspectRatioChangeAmbiguity); + var h = 1d + absA; + var v = 1d - absA; + if (scale >= h) return AspectRatioMode.HorizontalRectangle; + if (v < scale && scale < h) return AspectRatioMode.Square; + if (scale <= v) return AspectRatioMode.VerticalRectangle; + return AspectRatioMode.None; + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + if (change.Property == ItemsProperty || + change.Property == AspectRatioChangeAmbiguityProperty || + change.Property == BoundsProperty) + { + if (change.Property == BoundsProperty) + { + var o = (Rect)change.OldValue!; + var n = (Rect)change.NewValue!; + UpdataHistory(GetScaleMode(o) == GetScaleMode(n)); + if (!IsRightChanges()) return; + CurrentAspectRatioMode = GetScaleMode(n); + } + + var c = Items.FirstOrDefault(x => x.AcceptAspectRatioMode == GetScaleMode(Bounds)); + if (c == null) + { + if (Items.Count == 0) return; + c = Items.First(); + } + + Content = c; + } + } + + private class PCrossFade : IPageTransition + { + private readonly Animation _fadeInAnimation; + private readonly Animation _fadeOutAnimation; + + /// + /// Initializes a new instance of the class. + /// + public PCrossFade() + : this(TimeSpan.Zero) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The duration of the animation. + public PCrossFade(TimeSpan duration) + { + _fadeOutAnimation = new Animation + { + Children = + { + new KeyFrame + { + Setters = + { + new Setter + { + Property = OpacityProperty, + Value = 1d + } + }, + Cue = new Cue(0d) + }, + new KeyFrame + { + Setters = + { + new Setter + { + Property = OpacityProperty, + Value = 0d + } + }, + Cue = new Cue(1d) + } + } + }; + _fadeInAnimation = new Animation + { + Children = + { + new KeyFrame + { + Setters = + { + new Setter + { + Property = OpacityProperty, + Value = 0d + } + }, + Cue = new Cue(0d) + }, + new KeyFrame + { + Setters = + { + new Setter + { + Property = OpacityProperty, + Value = 1d + } + }, + Cue = new Cue(1d) + } + } + }; + _fadeInAnimation.FillMode = FillMode.Both; + _fadeOutAnimation.FillMode = FillMode.Both; + _fadeOutAnimation.Duration = _fadeInAnimation.Duration = duration; + } + + /// + /// Gets the duration of the animation. + /// + public TimeSpan Duration + { + get => _fadeOutAnimation.Duration; + set => _fadeOutAnimation.Duration = _fadeInAnimation.Duration = value; + } + + /// + /// Gets or sets element entrance easing. + /// + public Easing FadeInEasing + { + get => _fadeInAnimation.Easing; + set => _fadeInAnimation.Easing = value; + } + + /// + /// Gets or sets element exit easing. + /// + public Easing FadeOutEasing + { + get => _fadeOutAnimation.Easing; + set => _fadeOutAnimation.Easing = value; + } + + /// + /// Starts the animation. + /// + /// + /// The control that is being transitioned away from. May be null. + /// + /// + /// The control that is being transitioned to. May be null. + /// + /// + /// Unused for cross-fades. + /// + /// allowed cancel transition + /// + /// A that tracks the progress of the animation. + /// + Task IPageTransition.Start(Visual? from, Visual? to, bool forward, CancellationToken cancellationToken) + { + return Start(from, to, cancellationToken); + } + + /// + public async Task Start(Visual? from, Visual? to, CancellationToken cancellationToken) + { + if (cancellationToken.IsCancellationRequested) return; + + var tasks = new List(); + + if (from != null) tasks.Add(_fadeOutAnimation.RunAsync(from, cancellationToken)); + + if (to != null) + { + to.IsVisible = true; + tasks.Add(_fadeInAnimation.RunAsync(to, cancellationToken)); + } + + await Task.WhenAll(tasks); + + if (from != null && !cancellationToken.IsCancellationRequested) from.IsVisible = false; + } + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs new file mode 100644 index 0000000..e4cf639 --- /dev/null +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs @@ -0,0 +1,17 @@ +using Avalonia; +using Avalonia.Controls; + +namespace Ursa.Controls; + +public class AspectRatioLayoutItem : ContentControl +{ + public static readonly StyledProperty AcceptScaleModeProperty = + AvaloniaProperty.Register( + nameof(AcceptAspectRatioMode)); + + public AspectRatioMode AcceptAspectRatioMode + { + get => GetValue(AcceptScaleModeProperty); + set => SetValue(AcceptScaleModeProperty, value); + } +} \ No newline at end of file diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioMode.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioMode.cs new file mode 100644 index 0000000..4617c74 --- /dev/null +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioMode.cs @@ -0,0 +1,9 @@ +namespace Ursa.Controls; + +public enum AspectRatioMode +{ + None, + Square, + HorizontalRectangle, + VerticalRectangle +} \ No newline at end of file From 60ba488219b195b493bde077448b0ab82cd26f32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9B=E5=B0=98=E7=A9=BA=E5=BF=A7?= Date: Wed, 13 Nov 2024 06:14:08 +0800 Subject: [PATCH 2/4] fix:Go to AspectRatioLayout demo and go to another and go back, the demo will crash. --- .../AspectRatioLayout/AspectRatioLayout.cs | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs index e1f7da5..86a372f 100644 --- a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs @@ -11,7 +11,7 @@ public class AspectRatioLayout : TransitioningContentControl { public static readonly StyledProperty> ItemsProperty = AvaloniaProperty.Register>( - nameof(Items), new List()); + nameof(Items)); public static readonly StyledProperty AspectRatioChangeAmbiguityProperty = AvaloniaProperty.Register( @@ -21,12 +21,6 @@ public class AspectRatioLayout : TransitioningContentControl AvaloniaProperty.Register( nameof(CurrentAspectRatioMode)); - public AspectRatioMode CurrentAspectRatioMode - { - get => GetValue(CurrentAspectRatioModeProperty); - set => SetValue(CurrentAspectRatioModeProperty, value); - } - private readonly Queue _history = new(); static AspectRatioLayout() @@ -40,6 +34,17 @@ public class AspectRatioLayout : TransitioningContentControl PageTransitionProperty.OverrideDefaultValue(pCrossFade); } + public AspectRatioLayout() + { + Items = new List(); + } + + public AspectRatioMode CurrentAspectRatioMode + { + get => GetValue(CurrentAspectRatioModeProperty); + set => SetValue(CurrentAspectRatioModeProperty, value); + } + protected override Type StyleKeyOverride => typeof(TransitioningContentControl); [Content] From 4bfaab3f3d27567451b2fb256c27016dcf208362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9B=E5=B0=98=E7=A9=BA=E5=BF=A7?= Date: Wed, 13 Nov 2024 19:14:12 +0800 Subject: [PATCH 3/4] Feature: Added a Range selection mode by aspect ratio value. --- .../Pages/AspectRatioLayoutDemo.axaml | 59 +++++++++++++++++-- .../AspectRatioLayout/AspectRatioLayout.cs | 29 ++++++++- .../AspectRatioLayoutItem.cs | 53 +++++++++++++++++ 3 files changed, 134 insertions(+), 7 deletions(-) diff --git a/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml index 7d66922..77691d5 100644 --- a/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml +++ b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml @@ -8,12 +8,18 @@ - + Grid.Row="0"> + + + - + @@ -23,6 +29,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs index 86a372f..b73cb69 100644 --- a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs @@ -45,6 +45,16 @@ public class AspectRatioLayout : TransitioningContentControl set => SetValue(CurrentAspectRatioModeProperty, value); } + public static readonly StyledProperty AspectRatioValueProperty = + AvaloniaProperty.Register( + nameof(AspectRatioValue)); + + public double AspectRatioValue + { + get => GetValue(AspectRatioValueProperty); + set => SetValue(AspectRatioValueProperty, value); + } + protected override Type StyleKeyOverride => typeof(TransitioningContentControl); [Content] @@ -73,9 +83,14 @@ public class AspectRatioLayout : TransitioningContentControl return _history.All(x => x) || _history.All(x => !x); } + private double GetAspectRatio(Rect rect) + { + return Math.Round(Math.Truncate(Math.Abs(rect.Width)) / Math.Truncate(Math.Abs(rect.Height)), 3); + } + private AspectRatioMode GetScaleMode(Rect rect) { - var scale = Math.Round(Math.Truncate(Math.Abs(rect.Width)) / Math.Truncate(Math.Abs(rect.Height)), 3); + var scale = GetAspectRatio(rect); var absA = Math.Abs(AspectRatioChangeAmbiguity); var h = 1d + absA; var v = 1d - absA; @@ -96,12 +111,20 @@ public class AspectRatioLayout : TransitioningContentControl { var o = (Rect)change.OldValue!; var n = (Rect)change.NewValue!; - UpdataHistory(GetScaleMode(o) == GetScaleMode(n)); + UpdataHistory(GetAspectRatio(o) <= GetAspectRatio(n)); if (!IsRightChanges()) return; CurrentAspectRatioMode = GetScaleMode(n); } - var c = Items.FirstOrDefault(x => x.AcceptAspectRatioMode == GetScaleMode(Bounds)); + AspectRatioValue = GetAspectRatio(Bounds); + var c = + Items + .Where(x => x.IsUseAspectRatioRange) + .FirstOrDefault(x => + x.StartAspectRatioValue <= AspectRatioValue + && AspectRatioValue <= x.EndAspectRatioValue); + + c ??= Items.FirstOrDefault(x => x.AcceptAspectRatioMode == GetScaleMode(Bounds)); if (c == null) { if (Items.Count == 0) return; diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs index e4cf639..0f80564 100644 --- a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs @@ -9,9 +9,62 @@ public class AspectRatioLayoutItem : ContentControl AvaloniaProperty.Register( nameof(AcceptAspectRatioMode)); + public static readonly StyledProperty StartAspectRatioValueProperty = + AvaloniaProperty.Register( + nameof(StartAspectRatioValue), defaultValue: double.NaN); + + public double StartAspectRatioValue + { + get => GetValue(StartAspectRatioValueProperty); + set => SetValue(StartAspectRatioValueProperty, value); + } + + public static readonly StyledProperty EndAspectRatioValueProperty = + AvaloniaProperty.Register( + nameof(EndAspectRatioValue), defaultValue: double.NaN); + + public double EndAspectRatioValue + { + get => GetValue(EndAspectRatioValueProperty); + set => SetValue(EndAspectRatioValueProperty, value); + } + + + private bool _isUseAspectRatioRange; + + public static readonly DirectProperty IsUseAspectRatioRangeProperty = + AvaloniaProperty.RegisterDirect( + nameof(IsUseAspectRatioRange), o => o.IsUseAspectRatioRange); + + public bool IsUseAspectRatioRange + { + get => _isUseAspectRatioRange; + private set => SetAndRaise(IsUseAspectRatioRangeProperty, ref _isUseAspectRatioRange, value); + } + public AspectRatioMode AcceptAspectRatioMode { get => GetValue(AcceptScaleModeProperty); set => SetValue(AcceptScaleModeProperty, value); } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + if (change.Property == StartAspectRatioValueProperty || + change.Property == EndAspectRatioValueProperty) + { + UpdataIsUseAspectRatioRange(); + } + } + + private void UpdataIsUseAspectRatioRange() + { + if (double.IsNaN(StartAspectRatioValue) + || double.IsNaN(EndAspectRatioValue) + || StartAspectRatioValue > EndAspectRatioValue) + IsUseAspectRatioRange = false; + else + IsUseAspectRatioRange = true; + } } \ No newline at end of file From 06ba9af1d01b1c48692525e9d5e46d78a1dbfb30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9B=E5=B0=98=E7=A9=BA=E5=BF=A7?= Date: Wed, 13 Nov 2024 20:19:44 +0800 Subject: [PATCH 4/4] 1.rename AspectRatioChangeAmbiguity to AspectRatioTolerance 2.CurrentAspectRatioModeProperty to DirectProperty. 3.Fix misspelling: Updata -> Update 4.IsUseAspectRatioRange to an internal CLR property. --- .../Pages/AspectRatioLayoutDemo.axaml | 4 +-- .../AspectRatioLayout/AspectRatioLayout.cs | 28 ++++++++------- .../AspectRatioLayoutItem.cs | 36 +++---------------- 3 files changed, 21 insertions(+), 47 deletions(-) diff --git a/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml index 77691d5..c56ec69 100644 --- a/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml +++ b/demo/Ursa.Demo/Pages/AspectRatioLayoutDemo.axaml @@ -9,8 +9,8 @@ RowDefinitions="Auto,*"> - + diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs index b73cb69..5608232 100644 --- a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayout.cs @@ -13,13 +13,15 @@ public class AspectRatioLayout : TransitioningContentControl AvaloniaProperty.Register>( nameof(Items)); - public static readonly StyledProperty AspectRatioChangeAmbiguityProperty = + public static readonly StyledProperty AspectRatioToleranceProperty = AvaloniaProperty.Register( - nameof(AspectRatioChangeAmbiguity), 0.2); + nameof(AspectRatioTolerance), 0.2); - public static readonly StyledProperty CurrentAspectRatioModeProperty = - AvaloniaProperty.Register( - nameof(CurrentAspectRatioMode)); + private AspectRatioMode _currentAspectRatioMode; + + public static readonly DirectProperty CurrentAspectRatioModeProperty = + AvaloniaProperty.RegisterDirect( + nameof(CurrentAspectRatioMode), o => o.CurrentAspectRatioMode); private readonly Queue _history = new(); @@ -42,7 +44,7 @@ public class AspectRatioLayout : TransitioningContentControl public AspectRatioMode CurrentAspectRatioMode { get => GetValue(CurrentAspectRatioModeProperty); - set => SetValue(CurrentAspectRatioModeProperty, value); + set => SetAndRaise(CurrentAspectRatioModeProperty, ref _currentAspectRatioMode, value); } public static readonly StyledProperty AspectRatioValueProperty = @@ -64,13 +66,13 @@ public class AspectRatioLayout : TransitioningContentControl set => SetValue(ItemsProperty, value); } - public double AspectRatioChangeAmbiguity + public double AspectRatioTolerance { - get => GetValue(AspectRatioChangeAmbiguityProperty); - set => SetValue(AspectRatioChangeAmbiguityProperty, value); + get => GetValue(AspectRatioToleranceProperty); + set => SetValue(AspectRatioToleranceProperty, value); } - private void UpdataHistory(bool value) + private void UpdateHistory(bool value) { _history.Enqueue(value); while (_history.Count > 3) @@ -91,7 +93,7 @@ public class AspectRatioLayout : TransitioningContentControl private AspectRatioMode GetScaleMode(Rect rect) { var scale = GetAspectRatio(rect); - var absA = Math.Abs(AspectRatioChangeAmbiguity); + var absA = Math.Abs(AspectRatioTolerance); var h = 1d + absA; var v = 1d - absA; if (scale >= h) return AspectRatioMode.HorizontalRectangle; @@ -104,14 +106,14 @@ public class AspectRatioLayout : TransitioningContentControl { base.OnPropertyChanged(change); if (change.Property == ItemsProperty || - change.Property == AspectRatioChangeAmbiguityProperty || + change.Property == AspectRatioToleranceProperty || change.Property == BoundsProperty) { if (change.Property == BoundsProperty) { var o = (Rect)change.OldValue!; var n = (Rect)change.NewValue!; - UpdataHistory(GetAspectRatio(o) <= GetAspectRatio(n)); + UpdateHistory(GetAspectRatio(o) <= GetAspectRatio(n)); if (!IsRightChanges()) return; CurrentAspectRatioMode = GetScaleMode(n); } diff --git a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs index 0f80564..b941fa8 100644 --- a/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs +++ b/src/Ursa/Controls/AspectRatioLayout/AspectRatioLayoutItem.cs @@ -29,42 +29,14 @@ public class AspectRatioLayoutItem : ContentControl set => SetValue(EndAspectRatioValueProperty, value); } - - private bool _isUseAspectRatioRange; - - public static readonly DirectProperty IsUseAspectRatioRangeProperty = - AvaloniaProperty.RegisterDirect( - nameof(IsUseAspectRatioRange), o => o.IsUseAspectRatioRange); - - public bool IsUseAspectRatioRange - { - get => _isUseAspectRatioRange; - private set => SetAndRaise(IsUseAspectRatioRangeProperty, ref _isUseAspectRatioRange, value); - } + public bool IsUseAspectRatioRange => + !double.IsNaN(StartAspectRatioValue) + && !double.IsNaN(EndAspectRatioValue) + && !(StartAspectRatioValue > EndAspectRatioValue); public AspectRatioMode AcceptAspectRatioMode { get => GetValue(AcceptScaleModeProperty); set => SetValue(AcceptScaleModeProperty, value); } - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) - { - base.OnPropertyChanged(change); - if (change.Property == StartAspectRatioValueProperty || - change.Property == EndAspectRatioValueProperty) - { - UpdataIsUseAspectRatioRange(); - } - } - - private void UpdataIsUseAspectRatioRange() - { - if (double.IsNaN(StartAspectRatioValue) - || double.IsNaN(EndAspectRatioValue) - || StartAspectRatioValue > EndAspectRatioValue) - IsUseAspectRatioRange = false; - else - IsUseAspectRatioRange = true; - } } \ No newline at end of file