diff --git a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs index c34cd48da..07e5a784f 100644 --- a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs +++ b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.ControlThemeRegisterGenerator/ControlThemeRegister.g.cs @@ -95,6 +95,7 @@ ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SegmentedItemTheme()); ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SegmentedTheme()); ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SeparatorTheme()); + ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SimplePaginationTheme()); ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SliderTheme()); ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SliderThumbTheme()); ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.SplitButtonTheme()); diff --git a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs index b9b144444..287f70fd2 100644 --- a/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs +++ b/src/AtomUI.Controls/GeneratedFiles/AtomUI.Generator/AtomUI.Generator.TokenResourceKeyGenerator/TokenResourceConst.g.cs @@ -520,7 +520,6 @@ namespace AtomUI.Theme.Styling public static readonly TokenResourceKey PaginationLayoutSpacing = new TokenResourceKey("Pagination.PaginationLayoutSpacing"); public static readonly TokenResourceKey PaginationMiniQuickJumperInputWidth = new TokenResourceKey("Pagination.PaginationMiniQuickJumperInputWidth"); public static readonly TokenResourceKey PaginationQuickJumperInputWidth = new TokenResourceKey("Pagination.PaginationQuickJumperInputWidth"); - public static readonly TokenResourceKey PaginationSlashMarginInline = new TokenResourceKey("Pagination.PaginationSlashMarginInline"); } public static class PopupConfirmTokenKey diff --git a/src/AtomUI.Controls/Pagination/AbstractPagination.cs b/src/AtomUI.Controls/Pagination/AbstractPagination.cs new file mode 100644 index 000000000..9ad9d9f52 --- /dev/null +++ b/src/AtomUI.Controls/Pagination/AbstractPagination.cs @@ -0,0 +1,160 @@ +using System.Reactive.Disposables; +using AtomUI.Theme; +using AtomUI.Theme.Utils; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.VisualTree; + +namespace AtomUI.Controls; + +public abstract class AbstractPagination : TemplatedControl, + ISizeTypeAware, + IMotionAwareControl, + IResourceBindingManager +{ + public const int DefaultPageSize = 10; + public const int DefaultCurrentPage = 1; + + #region 公共属性定义 + + public static readonly StyledProperty AlignProperty = + AvaloniaProperty.Register(nameof(PaginationAlign)); + + public static readonly StyledProperty SizeTypeProperty = + SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner(); + + public static readonly DirectProperty CurrentPageProperty = + AvaloniaProperty.RegisterDirect(nameof(CurrentPage), + o => o.CurrentPage, + (o, v) => o.CurrentPage = v, + unsetValue: DefaultCurrentPage); + + public static readonly DirectProperty PageSizeProperty = + AvaloniaProperty.RegisterDirect(nameof(PageSize), + o => o.PageSize, + (o, v) => o.PageSize = v, + unsetValue: DefaultPageSize, + enableDataValidation:true); + + public static readonly DirectProperty TotalProperty = + AvaloniaProperty.RegisterDirect(nameof(Total), + o => o.Total, + (o, v) => o.Total = v); + + public static readonly StyledProperty IsMotionEnabledProperty + = WaveSpiritAwareControlProperty.IsMotionEnabledProperty.AddOwner(); + + public PaginationAlign Align + { + get => GetValue(AlignProperty); + set => SetValue(AlignProperty, value); + } + + public SizeType SizeType + { + get => GetValue(SizeTypeProperty); + set => SetValue(SizeTypeProperty, value); + } + + private protected int _currentPage = DefaultCurrentPage; + public int CurrentPage + { + get => _currentPage; + set => SetAndRaise(CurrentPageProperty, ref _currentPage, value); + } + + private protected int _pageSize = DefaultPageSize; + public int PageSize + { + get => _pageSize; + set + { + if (!new[] { 10, 20, 50, 100 }.Contains(value)) + { + throw new ArgumentException("PageSize only allow: 10, 20, 50, 100"); + } + SetAndRaise(PageSizeProperty, ref _pageSize, value); + } + } + + private protected long _total; + public long Total + { + get => _total; + set => SetAndRaise(TotalProperty, ref _total, value); + } + + public bool IsMotionEnabled + { + get => GetValue(IsMotionEnabledProperty); + set => SetValue(IsMotionEnabledProperty, value); + } + + #endregion + + #region 公共事件定义 + public event EventHandler? CurrentPageChanged; + #endregion + + #region 内部属性定义 + Control IMotionAwareControl.PropertyBindTarget => this; + CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable; + private CompositeDisposable? _resourceBindingsDisposable; + #endregion + + static AbstractPagination() + { + AffectsMeasure(SizeTypeProperty); + } + + public AbstractPagination() + { + this.BindMotionProperties(); + } + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + { + base.OnPropertyChanged(change); + if (this.IsAttachedToVisualTree()) + { + if (change.Property == TotalProperty || + change.Property == PageSizeProperty || + change.Property == CurrentPageProperty) + { + HandlePageConditionChanged(); + } + } + } + + protected void HandlePageConditionChanged() + { + var total = Math.Max(0, Total); + var pageSize = PageSize <= 0 ? DefaultPageSize : PageSize; + var pageCount = (int)Math.Ceiling(total / (double)pageSize); + var currentPage = Math.Max(1, Math.Min(CurrentPage, pageCount)); + _currentPage = currentPage; + NotifyPageConditionChanged(currentPage, pageCount, pageSize, total); + } + + protected virtual void NotifyPageConditionChanged(int currentPage, int pageCount, int pageSize, long total) + { + } + + protected void EmitCurrentPageChanged(int currentPage, int pageCount, int pageSize) + { + CurrentPageChanged?.Invoke(this, new PageChangedArgs(currentPage, pageCount, pageSize)); + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + _resourceBindingsDisposable = new CompositeDisposable(); + } + + protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnDetachedFromVisualTree(e); + this.DisposeTokenBindings(); + } +} \ No newline at end of file diff --git a/src/AtomUI.Controls/Pagination/Pagination.cs b/src/AtomUI.Controls/Pagination/Pagination.cs index fe56b8307..d3c560655 100644 --- a/src/AtomUI.Controls/Pagination/Pagination.cs +++ b/src/AtomUI.Controls/Pagination/Pagination.cs @@ -23,42 +23,13 @@ public enum PaginationAlign End } -public class Pagination : TemplatedControl, - ISizeTypeAware, - IMotionAwareControl, - IControlSharedTokenResourcesHost, - IResourceBindingManager +public class Pagination : AbstractPagination, + IControlSharedTokenResourcesHost { - public const int DefaultPageSize = 10; - public const int DefaultCurrentPage = 1; internal const int MaxNavItemCount = 11; #region 公共属性定义 - public static readonly StyledProperty AlignProperty = - AvaloniaProperty.Register(nameof(PaginationAlign)); - - public static readonly StyledProperty SizeTypeProperty = - SizeTypeAwareControlProperty.SizeTypeProperty.AddOwner(); - - public static readonly DirectProperty CurrentPageProperty = - AvaloniaProperty.RegisterDirect(nameof(CurrentPage), - o => o.CurrentPage, - (o, v) => o.CurrentPage = v, - unsetValue: DefaultCurrentPage); - - public static readonly DirectProperty PageSizeProperty = - AvaloniaProperty.RegisterDirect(nameof(PageSize), - o => o.PageSize, - (o, v) => o.PageSize = v, - unsetValue: DefaultPageSize, - enableDataValidation:true); - - public static readonly DirectProperty TotalProperty = - AvaloniaProperty.RegisterDirect(nameof(Total), - o => o.Total, - (o, v) => o.Total = v); - public static readonly DirectProperty HideOnSinglePageProperty = AvaloniaProperty.RegisterDirect(nameof(HideOnSinglePage), o => o.HideOnSinglePage, @@ -82,49 +53,6 @@ public class Pagination : TemplatedControl, public static readonly StyledProperty TotalInfoTemplateProperty = AvaloniaProperty.Register(nameof(TotalInfoTemplate)); - public static readonly StyledProperty IsMotionEnabledProperty - = WaveSpiritAwareControlProperty.IsMotionEnabledProperty.AddOwner(); - - public SizeType SizeType - { - get => GetValue(SizeTypeProperty); - set => SetValue(SizeTypeProperty, value); - } - - public PaginationAlign Align - { - get => GetValue(AlignProperty); - set => SetValue(AlignProperty, value); - } - - private int _currentPage = DefaultCurrentPage; - public int CurrentPage - { - get => _currentPage; - set => SetAndRaise(CurrentPageProperty, ref _currentPage, value); - } - - private int _pageSize = DefaultPageSize; - public int PageSize - { - get => _pageSize; - set - { - if (!new[] { 10, 20, 50, 100 }.Contains(value)) - { - throw new ArgumentException("PageSize only allow: 10, 20, 50, 100"); - } - SetAndRaise(PageSizeProperty, ref _pageSize, value); - } - } - - private long _total; - public long Total - { - get => _total; - set => SetAndRaise(TotalProperty, ref _total, value); - } - private bool _hideOnSinglePage; public bool HideOnSinglePage { @@ -159,15 +87,6 @@ public class Pagination : TemplatedControl, set => SetValue(TotalInfoTemplateProperty, value); } - public bool IsMotionEnabled - { - get => GetValue(IsMotionEnabledProperty); - set => SetValue(IsMotionEnabledProperty, value); - } - #endregion - - #region 公共事件定义 - public event EventHandler? CurrentPageChanged; #endregion #region 内部属性定义 @@ -220,11 +139,8 @@ public class Pagination : TemplatedControl, set => SetAndRaise(TotalInfoTextProperty, ref _totalInfoText, value); } - Control IMotionAwareControl.PropertyBindTarget => this; Control IControlSharedTokenResourcesHost.HostControl => this; string IControlSharedTokenResourcesHost.TokenId => PaginationToken.ID; - CompositeDisposable? IResourceBindingManager.ResourceBindingsDisposable => _resourceBindingsDisposable; - private CompositeDisposable? _resourceBindingsDisposable; #endregion private PaginationNav? _paginationNav; @@ -233,15 +149,9 @@ public class Pagination : TemplatedControl, private int _nextPushItemIndex = 1; private int _selectedNavItemIndex = -1; - static Pagination() - { - AffectsMeasure