From a2fa1eefef15ce30a6034d3dbbc5ce0c552f4d75 Mon Sep 17 00:00:00 2001 From: CHINBOY Date: Tue, 1 Jul 2025 12:14:46 +0800 Subject: [PATCH] Add Motion support for DataGridRowExpander --- .../Column/DataGridDetailExpanderColumn.cs | 6 +- .../Column/DataGridRowExpander.cs | 105 +++++++++++++++++- .../Themes/DataGridRowExpander.axaml | 29 +++-- 3 files changed, 129 insertions(+), 11 deletions(-) diff --git a/src/AtomUI.Controls.DataGrid/Column/DataGridDetailExpanderColumn.cs b/src/AtomUI.Controls.DataGrid/Column/DataGridDetailExpanderColumn.cs index 192d3506e..16c33add0 100644 --- a/src/AtomUI.Controls.DataGrid/Column/DataGridDetailExpanderColumn.cs +++ b/src/AtomUI.Controls.DataGrid/Column/DataGridDetailExpanderColumn.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using Avalonia.Controls; using Avalonia.Interactivity; @@ -18,7 +19,10 @@ public sealed class DataGridDetailExpanderColumn : DataGridColumn protected override Control GenerateElement(DataGridCell cell, object dataItem) { - return new DataGridRowExpander(); + Debug.Assert(OwningGrid != null); + var expander = new DataGridRowExpander(); + expander[!DataGridColumnHeader.IsMotionEnabledProperty] = OwningGrid[!DataGrid.IsMotionEnabledProperty]; + return expander; } protected override object? PrepareCellForEdit(Control editingElement, RoutedEventArgs editingEventArgs) diff --git a/src/AtomUI.Controls.DataGrid/Column/DataGridRowExpander.cs b/src/AtomUI.Controls.DataGrid/Column/DataGridRowExpander.cs index 3ac2882c5..dadb59271 100644 --- a/src/AtomUI.Controls.DataGrid/Column/DataGridRowExpander.cs +++ b/src/AtomUI.Controls.DataGrid/Column/DataGridRowExpander.cs @@ -1,13 +1,17 @@ using System.Reactive.Disposables; +using AtomUI.Animations; +using AtomUI.Controls.Utils; using AtomUI.Theme; using AtomUI.Theme.Data; using AtomUI.Theme.Styling; using Avalonia; +using Avalonia.Animation; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Controls.Shapes; using Avalonia.Data; using Avalonia.Rendering; +using Avalonia.VisualTree; namespace AtomUI.Controls; @@ -15,25 +19,35 @@ internal class DataGridRowExpander : ToggleButton, IResourceBindingManager, ICustomHitTest { - internal static readonly DirectProperty IndicatorThicknessProperty = AvaloniaProperty.RegisterDirect( nameof(IndicatorThickness), o => o.IndicatorThickness, (o, v) => o.IndicatorThickness = v); - + + internal static readonly StyledProperty IsMotionEnabledProperty = + MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner(); + internal double IndicatorThickness { get => _indicatorThickness; set => SetAndRaise(IndicatorThicknessProperty, ref _indicatorThickness, value); } + private double _indicatorThickness; - + + internal bool IsMotionEnabled + { + get => GetValue(IsMotionEnabledProperty); + set => SetValue(IsMotionEnabledProperty, value); + } + private CompositeDisposable? _resourceBindingsDisposable; CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable; private Rectangle? _horizontalIndicator; private Rectangle? _verticalIndicator; + private Border? _frame; protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) { @@ -45,6 +59,31 @@ internal class DataGridRowExpander : ToggleButton, new RenderScaleAwareThicknessConfigure(this))); } + protected override Size ArrangeOverride(Size finalSize) + { + var size = base.ArrangeOverride(finalSize); + var delta = IndicatorThickness / 2; + if (_verticalIndicator != null) + { + var indicatorSize = _verticalIndicator.DesiredSize; + var x = (finalSize.Width - indicatorSize.Width) / 2 - delta; + var y = (finalSize.Height - indicatorSize.Height) / 2 - delta; + Canvas.SetLeft(_verticalIndicator, x); + Canvas.SetTop(_verticalIndicator, y); + } + + if (_horizontalIndicator != null) + { + var indicatorSize = _horizontalIndicator.DesiredSize; + var x = (finalSize.Width - indicatorSize.Width) / 2 - delta; + var y = (finalSize.Height - indicatorSize.Height) / 2 - delta; + Canvas.SetLeft(_horizontalIndicator, x); + Canvas.SetTop(_horizontalIndicator, y); + } + + return size; + } + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); @@ -52,6 +91,14 @@ internal class DataGridRowExpander : ToggleButton, { IndicatorThickness = BorderThickness.Left; } + + if (this.IsAttachedToVisualTree()) + { + if (change.Property == IsMotionEnabledProperty) + { + ConfigureTransitions(); + } + } } protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) @@ -65,10 +112,62 @@ internal class DataGridRowExpander : ToggleButton, base.OnApplyTemplate(e); _verticalIndicator = e.NameScope.Find(DataGridRowExpanderThemeConstants.VerticalIndicatorPart); _horizontalIndicator = e.NameScope.Find(DataGridRowExpanderThemeConstants.HorizontalIndicatorPart); + _frame = e.NameScope.Find(DataGridRowExpanderThemeConstants.FramePart); + ConfigureTransitions(); } public bool HitTest(Point point) { return true; } + + private void ConfigureTransitions() + { + if (IsMotionEnabled) + { + if (_frame != null) + { + _frame.Transitions = new Transitions() + { + TransitionUtils.CreateTransition(Border.BorderBrushProperty) + }; + } + + if (_verticalIndicator != null) + { + _verticalIndicator.Transitions = new Transitions() + { + TransitionUtils.CreateTransition(Rectangle.FillProperty), + TransitionUtils.CreateTransition(Visual.RenderTransformProperty) + }; + } + + if (_horizontalIndicator != null) + { + _horizontalIndicator.Transitions = new Transitions() + { + TransitionUtils.CreateTransition(Rectangle.FillProperty), + TransitionUtils.CreateTransition(Visual.RenderTransformProperty) + }; + } + } + else + { + if (_frame != null) + { + _frame.Transitions?.Clear(); + _frame.Transitions = null; + } + if (_verticalIndicator != null) + { + _verticalIndicator.Transitions?.Clear(); + _verticalIndicator.Transitions = null; + } + if (_horizontalIndicator != null) + { + _horizontalIndicator.Transitions?.Clear(); + _horizontalIndicator.Transitions = null; + } + } + } } \ No newline at end of file diff --git a/src/AtomUI.Controls.DataGrid/Themes/DataGridRowExpander.axaml b/src/AtomUI.Controls.DataGrid/Themes/DataGridRowExpander.axaml index d88b9486f..c36f87d68 100644 --- a/src/AtomUI.Controls.DataGrid/Themes/DataGridRowExpander.axaml +++ b/src/AtomUI.Controls.DataGrid/Themes/DataGridRowExpander.axaml @@ -7,30 +7,33 @@ - + - + + + + + + + + \ No newline at end of file