From fed4c18c157100276b62428e2c7b42d3d42d5f43 Mon Sep 17 00:00:00 2001 From: polarboy Date: Wed, 7 Aug 2024 19:50:41 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E6=90=9C=E7=B4=A2=E7=B1=BB?= =?UTF-8?q?=E5=9E=8B=E7=9A=84=E8=BE=93=E5=85=A5=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 完成搜索类型的输入框 --- .../ShowCase/LineEditShowCase.axaml | 28 ++++++ src/AtomUI.Controls/Buttons/Button.cs | 11 +++ src/AtomUI.Controls/Input/LineEdit.cs | 22 +++-- src/AtomUI.Controls/Input/LineEditTheme.cs | 37 +++++++- src/AtomUI.Controls/Input/SearchEdit.cs | 55 +++++++++++- src/AtomUI.Controls/Input/SearchEditTheme.cs | 85 +++++++++++++++++++ 6 files changed, 230 insertions(+), 8 deletions(-) create mode 100644 src/AtomUI.Controls/Input/SearchEditTheme.cs diff --git a/samples/AtomUI.Demo.Desktop/ShowCase/LineEditShowCase.axaml b/samples/AtomUI.Demo.Desktop/ShowCase/LineEditShowCase.axaml index 9d35873..e75654e 100644 --- a/samples/AtomUI.Demo.Desktop/ShowCase/LineEditShowCase.axaml +++ b/samples/AtomUI.Demo.Desktop/ShowCase/LineEditShowCase.axaml @@ -104,5 +104,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/AtomUI.Controls/Buttons/Button.cs b/src/AtomUI.Controls/Buttons/Button.cs index 4c877da..dd7e661 100644 --- a/src/AtomUI.Controls/Buttons/Button.cs +++ b/src/AtomUI.Controls/Buttons/Button.cs @@ -1,4 +1,5 @@ using AtomUI.Controls.Utils; +using AtomUI.Data; using AtomUI.Icon; using AtomUI.Media; using AtomUI.Theme.Data; @@ -62,6 +63,9 @@ public class Button : AvaloniaButton, ISizeTypeAware, IControlCustomStyle, IWave public static readonly StyledProperty TextProperty = AvaloniaProperty.Register(nameof(Text)); + + public static readonly StyledProperty IsIconVisibleProperty + = AvaloniaProperty.Register(nameof (IsIconVisible), true); public ButtonType ButtonType { @@ -104,6 +108,12 @@ public class Button : AvaloniaButton, ISizeTypeAware, IControlCustomStyle, IWave get => GetValue(TextProperty); set => SetValue(TextProperty, value); } + + public bool IsIconVisible + { + get => GetValue(IsIconVisibleProperty); + set => SetValue(IsIconVisibleProperty, value); + } #endregion @@ -347,6 +357,7 @@ public class Button : AvaloniaButton, ISizeTypeAware, IControlCustomStyle, IWave if (Icon is not null) { if (_stackPanel is not null) { UIStructureUtils.SetTemplateParent(Icon, this); + BindUtils.RelayBind(this, IsIconVisibleProperty, Icon, PathIcon.IsVisibleProperty); _stackPanel.Children.Insert(0, Icon); } } diff --git a/src/AtomUI.Controls/Input/LineEdit.cs b/src/AtomUI.Controls/Input/LineEdit.cs index 742ef94..66fe49d 100644 --- a/src/AtomUI.Controls/Input/LineEdit.cs +++ b/src/AtomUI.Controls/Input/LineEdit.cs @@ -29,6 +29,7 @@ public class LineEdit : TextBox { public const string ErrorPC = ":error"; public const string WarningPC = ":warning"; + #region 功能属性定义 public static readonly StyledProperty LeftAddOnProperty = @@ -172,9 +173,9 @@ public class LineEdit : TextBox #endregion - private ContentPresenter? _leftAddOnPresenter; - private ContentPresenter? _rightAddOnPresenter; - private Border? _lineEditKernelDecorator; + protected Control? _leftAddOnPresenter; + protected Control? _rightAddOnPresenter; + protected Border? _lineEditKernelDecorator; static LineEdit() @@ -188,8 +189,8 @@ public class LineEdit : TextBox base.OnApplyTemplate(e); TokenResourceBinder.CreateGlobalResourceBinding(this, BorderThicknessProperty, GlobalResourceKey.BorderThickness, BindingPriority.Template, new RenderScaleAwareThicknessConfigure(this)); - _leftAddOnPresenter = e.NameScope.Find(LineEditTheme.LeftAddOnPart); - _rightAddOnPresenter = e.NameScope.Find(LineEditTheme.RightAddOnPart); + _leftAddOnPresenter = e.NameScope.Find(LineEditTheme.LeftAddOnPart); + _rightAddOnPresenter = e.NameScope.Find(LineEditTheme.RightAddOnPart); _lineEditKernelDecorator = e.NameScope.Find(LineEditTheme.LineEditKernelDecoratorPart); SetupEditKernelCornerRadius(); SetupEffectiveShowClearButton(); @@ -221,7 +222,9 @@ public class LineEdit : TextBox } if (change.Property == InnerLeftContentProperty || - change.Property == InnerRightContentProperty) { + change.Property == InnerRightContentProperty || + change.Property == LeftAddOnProperty || + change.Property == RightAddOnProperty) { if (change.OldValue is Control oldControl) { UIStructureUtils.SetTemplateParent(oldControl, null); } @@ -255,6 +258,13 @@ public class LineEdit : TextBox LeftAddOnBorderThickness = new Thickness(top: topThickness, right:0, bottom:bottomThickness, left: leftThickness); RightAddOnBorderThickness = new Thickness(top: topThickness, right:rightThickness, bottom:bottomThickness, left: 0); + + NotifyAddOnBorderInfoCalculated(); + } + + protected virtual void NotifyAddOnBorderInfoCalculated() + { + } private void SetupEditKernelCornerRadius() diff --git a/src/AtomUI.Controls/Input/LineEditTheme.cs b/src/AtomUI.Controls/Input/LineEditTheme.cs index 59752e3..d061320 100644 --- a/src/AtomUI.Controls/Input/LineEditTheme.cs +++ b/src/AtomUI.Controls/Input/LineEditTheme.cs @@ -32,6 +32,10 @@ internal class LineEditTheme : BaseControlTheme public const string LineEditKernelPart = "PART_LineEditKernel"; public const string LineEditKernelDecoratorPart = "PART_LineEditKernelDecorator"; + public const int NormalZIndex = 1000; + public const int ActivatedZIndex = 2000; + + public LineEditTheme(Type targetType) : base(targetType) { } public LineEditTheme() : base(typeof(LineEdit)) { } protected override IControlTemplate? BuildControlTemplate() @@ -108,7 +112,6 @@ internal class LineEditTheme : BaseControlTheme var kernelLayout = new LineEditKernel() { Name = LineEditKernelPart, - ZIndex = 1000, Cursor = new Cursor(StandardCursorType.Ibeam) }; @@ -356,6 +359,10 @@ internal class LineEditTheme : BaseControlTheme var commonStyle = new Style(selector => selector.Nesting()); commonStyle.Add(LineEdit.ForegroundProperty, GlobalResourceKey.ColorText); + var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(LineEditKernelDecoratorPart)); + decoratorStyle.Add(Border.ZIndexProperty, NormalZIndex); + commonStyle.Add(decoratorStyle); + // 输入框左右小组件的 margin 设置 var leftInnerContentStyle = new Style(selector => selector.Nesting().Template().Name(LeftInnerContentPart)); leftInnerContentStyle.Add(ContentPresenter.PaddingProperty, LineEditResourceKey.LeftInnerAddOnMargin); @@ -397,6 +404,15 @@ internal class LineEditTheme : BaseControlTheme addOnStyle.Add(ContentPresenter.PaddingProperty, LineEditResourceKey.PaddingLG); largeStyle.Add(addOnStyle); } + + { + // 左右 AddOn icon 的大小 + var addOnContentIconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart).Descendant().OfType(), + selector.Nesting().Template().Name(RightAddOnPart).Descendant().OfType())); + addOnContentIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSizeLG); + addOnContentIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSizeLG); + largeStyle.Add(addOnContentIconStyle); + } largeStyle.Add(LineEdit.FontSizeProperty, LineEditResourceKey.InputFontSizeLG); largeStyle.Add(LineEdit.LineHeightProperty, GlobalResourceKey.FontHeightLG); @@ -418,6 +434,15 @@ internal class LineEditTheme : BaseControlTheme addOnStyle.Add(ContentPresenter.PaddingProperty, LineEditResourceKey.Padding); middleStyle.Add(addOnStyle); } + + { + // 左右 AddOn icon 的大小 + var addOnContentIconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart).Descendant().OfType(), + selector.Nesting().Template().Name(RightAddOnPart).Descendant().OfType())); + addOnContentIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSize); + addOnContentIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSize); + middleStyle.Add(addOnContentIconStyle); + } middleStyle.Add(LineEdit.FontSizeProperty, LineEditResourceKey.InputFontSize); middleStyle.Add(LineEdit.LineHeightProperty, GlobalResourceKey.FontHeight); @@ -439,6 +464,16 @@ internal class LineEditTheme : BaseControlTheme addOnStyle.Add(ContentPresenter.PaddingProperty, LineEditResourceKey.PaddingSM); smallStyle.Add(addOnStyle); } + + { + // 左右 AddOn icon 的大小 + var addOnContentIconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart).Descendant().OfType(), + selector.Nesting().Template().Name(RightAddOnPart).Descendant().OfType())); + addOnContentIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSizeSM); + addOnContentIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSizeSM); + smallStyle.Add(addOnContentIconStyle); + } + smallStyle.Add(LineEdit.FontSizeProperty, LineEditResourceKey.InputFontSizeSM); smallStyle.Add(LineEdit.LineHeightProperty, GlobalResourceKey.FontHeightSM); smallStyle.Add(LineEdit.CornerRadiusProperty, GlobalResourceKey.BorderRadiusSM); diff --git a/src/AtomUI.Controls/Input/SearchEdit.cs b/src/AtomUI.Controls/Input/SearchEdit.cs index 89ba6bb..8b2308c 100644 --- a/src/AtomUI.Controls/Input/SearchEdit.cs +++ b/src/AtomUI.Controls/Input/SearchEdit.cs @@ -1,6 +1,59 @@ -namespace AtomUI.Controls; +using AtomUI.Theme.Data; +using AtomUI.Theme.Styling; +using AtomUI.Utils; +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Primitives; +using Avalonia.Data; + +namespace AtomUI.Controls; + +public enum SearchEditButtonStyle +{ + Default, + Primary +} public class SearchEdit : LineEdit { + #region 公共属性定义 + public static readonly StyledProperty SearchButtonStyleProperty = + AvaloniaProperty.Register(nameof(SearchButtonStyle), SearchEditButtonStyle.Default); + + public static readonly StyledProperty SearchButtonTextProperty = + AvaloniaProperty.Register(nameof(SearchButtonText)); + + public SearchEditButtonStyle SearchButtonStyle + { + get => GetValue(SearchButtonStyleProperty); + set => SetValue(SearchButtonStyleProperty, value); + } + + public object? SearchButtonText + { + get => GetValue(SearchButtonTextProperty); + set => SetValue(SearchButtonTextProperty, value); + } + #endregion + + private Rect? _originRect; + + protected override void NotifyAddOnBorderInfoCalculated() + { + RightAddOnBorderThickness = BorderThickness; + } + + protected override Size ArrangeOverride(Size finalSize) + { + var size = base.ArrangeOverride(finalSize); + if (_originRect is null) { + _originRect = _rightAddOnPresenter?.Bounds; + } + if (_rightAddOnPresenter is not null && _originRect.HasValue) { + _rightAddOnPresenter.Arrange(_originRect.Value.Inflate(new Thickness(1, 0, 0, 0))); + } + + return size; + } } \ No newline at end of file diff --git a/src/AtomUI.Controls/Input/SearchEditTheme.cs b/src/AtomUI.Controls/Input/SearchEditTheme.cs new file mode 100644 index 0000000..766fae5 --- /dev/null +++ b/src/AtomUI.Controls/Input/SearchEditTheme.cs @@ -0,0 +1,85 @@ +using AtomUI.Theme.Styling; +using AtomUI.Utils; +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using Avalonia.Styling; + +namespace AtomUI.Controls; + +[ControlThemeProvider] +internal class SearchEditTheme : LineEditTheme +{ + public SearchEditTheme() : base(typeof(SearchEdit)) { } + + protected override void BuildRightAddOn(Grid layout, INameScope scope) + { + var searchIcon = new PathIcon() + { + Kind = "SearchOutlined" + }; + TokenResourceBinder.CreateGlobalTokenBinding(searchIcon, PathIcon.NormalFilledBrushProperty, GlobalResourceKey.ColorIcon); + var rightAddOnContentPresenter = new Button() + { + Name = RightAddOnPart, + Focusable = false, + Icon = searchIcon + }; + CreateTemplateParentBinding(rightAddOnContentPresenter, Button.ContentProperty, + SearchEdit.RightAddOnProperty); + CreateTemplateParentBinding(rightAddOnContentPresenter, Button.BorderThicknessProperty, + SearchEdit.RightAddOnBorderThicknessProperty); + CreateTemplateParentBinding(rightAddOnContentPresenter, Button.CornerRadiusProperty, + SearchEdit.RightAddOnCornerRadiusProperty); + CreateTemplateParentBinding(rightAddOnContentPresenter, Button.TextProperty, + SearchEdit.SearchButtonTextProperty); + CreateTemplateParentBinding(rightAddOnContentPresenter, Button.SizeTypeProperty, + SearchEdit.SizeTypeProperty); + + rightAddOnContentPresenter.RegisterInNameScope(scope); + layout.Children.Add(rightAddOnContentPresenter); + Grid.SetColumn(rightAddOnContentPresenter, 2); + } + + protected override void BuildStyles() + { + base.BuildStyles(); + + var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(LineEditKernelDecoratorPart)); + decoratorStyle.Add(Border.ZIndexProperty, NormalZIndex); + Add(decoratorStyle); + + var decoratorHoverOrFocusStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LineEditKernelDecoratorPart).Class(StdPseudoClass.FocusWithIn), + selector.Nesting().Template().Name(LineEditKernelDecoratorPart).Class(StdPseudoClass.PointerOver))); + decoratorHoverOrFocusStyle.Add(Border.ZIndexProperty, ActivatedZIndex); + Add(decoratorHoverOrFocusStyle); + + var searchButtonStyle = new Style(selector => selector.Nesting().Template().Name(RightAddOnPart)); + searchButtonStyle.Add(Border.ZIndexProperty, NormalZIndex); + Add(searchButtonStyle); + + var searchButtonStyleHoverOrFocusStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(RightAddOnPart).Class(StdPseudoClass.Pressed), + selector.Nesting().Template().Name(RightAddOnPart).Class(StdPseudoClass.PointerOver))); + searchButtonStyleHoverOrFocusStyle.Add(Border.ZIndexProperty, ActivatedZIndex); + Add(searchButtonStyleHoverOrFocusStyle); + + // Icon button + var iconSearchButtonStyle = new Style(selector => selector.Nesting().PropertyEquals(SearchEdit.SearchButtonStyleProperty, SearchEditButtonStyle.Default)); + { + var buttonStyle = new Style(selector => selector.Nesting().Template().Name(RightAddOnPart)); + buttonStyle.Add(Button.IsIconVisibleProperty, true); + buttonStyle.Add(Button.ButtonTypeProperty, ButtonType.Default); + iconSearchButtonStyle.Add(buttonStyle); + } + Add(iconSearchButtonStyle); + + // primary button + var primarySearchButtonStyle = new Style(selector => selector.Nesting().PropertyEquals(SearchEdit.SearchButtonStyleProperty, SearchEditButtonStyle.Primary)); + { + var buttonStyle = new Style(selector => selector.Nesting().Template().Name(RightAddOnPart)); + buttonStyle.Add(Button.IsIconVisibleProperty, false); + buttonStyle.Add(Button.ButtonTypeProperty, ButtonType.Primary); + primarySearchButtonStyle.Add(buttonStyle); + } + Add(primarySearchButtonStyle); + } +} \ No newline at end of file