重构SearchEdit

重构SearchEdit
This commit is contained in:
polarboy 2024-08-16 20:54:43 +08:00
parent a88f0e1cda
commit 069bdd3f8f
8 changed files with 261 additions and 202 deletions

View File

@ -107,33 +107,33 @@
</StackPanel>
</showcase:ShowCaseItem>
<!-- <showcase:ShowCaseItem -->
<!-- Title="Search box" -->
<!-- Description="Example of creating a search box by grouping a standard input with a search button."> -->
<!-- <StackPanel Orientation="Vertical" Spacing="10" Margin="0, 0, 20, 0"> -->
<!-- <atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left"/> -->
<!-- <atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left" SearchButtonText="Search"/> -->
<!-- -->
<!-- <atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left" SearchButtonStyle="Primary" SearchButtonText="Search"/> -->
<!-- <atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left" SearchButtonStyle="Primary" SearchButtonText="Search"/> -->
<!-- -->
<!-- <atom:SearchEdit Watermark="input search text" -->
<!-- Width="400" -->
<!-- HorizontalAlignment="Left" -->
<!-- SearchButtonStyle="Primary" -->
<!-- SearchButtonText="Search" -->
<!-- IsEnableClearButton="True" -->
<!-- SizeType="Large"/> -->
<!-- <atom:SearchEdit Watermark="input search text" -->
<!-- Width="400" -->
<!-- HorizontalAlignment="Left" -->
<!-- SearchButtonStyle="Primary" -->
<!-- SearchButtonText="搜索一下" -->
<!-- InnerRightContent="{atom:IconProvider Kind=AudioOutlined, NormalFilledColor=#1677ff, Width=16, Height=16}" -->
<!-- IsEnableClearButton="True" -->
<!-- SizeType="Large"/> -->
<!-- </StackPanel> -->
<!-- </showcase:ShowCaseItem> -->
<showcase:ShowCaseItem
Title="Search box"
Description="Example of creating a search box by grouping a standard input with a search button.">
<StackPanel Orientation="Vertical" Spacing="10" Margin="0, 0, 20, 0">
<atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left"/>
<atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left" SearchButtonText="Search"/>
<atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left" SearchButtonStyle="Primary" SearchButtonText="Search"/>
<atom:SearchEdit Watermark="input search text" Width="400" HorizontalAlignment="Left" SearchButtonStyle="Primary" SearchButtonText="Search"/>
<atom:SearchEdit Watermark="input search text"
Width="400"
HorizontalAlignment="Left"
SearchButtonStyle="Primary"
SearchButtonText="Search"
IsEnableClearButton="True"
SizeType="Large"/>
<atom:SearchEdit Watermark="input search text"
Width="400"
HorizontalAlignment="Left"
SearchButtonStyle="Primary"
SearchButtonText="搜索一下"
InnerRightContent="{atom:IconProvider Kind=AudioOutlined, NormalFilledColor=#1677ff, Width=16, Height=16}"
IsEnableClearButton="True"
SizeType="Large"/>
</StackPanel>
</showcase:ShowCaseItem>
</showcase:ShowCasePanel>
</UserControl>

View File

@ -180,13 +180,33 @@ public class AddOnDecoratedBox : ContentControl
}
if (change.Property == LeftAddOnProperty || change.Property == RightAddOnProperty) {
if (change.OldValue is Control oldControl) {
UIStructureUtils.SetTemplateParent(oldControl, null);
if (change.NewValue is PathIcon icon) {
SetupIconTypeAddOnSize(icon);
}
}
if (change.NewValue is Control newControl) {
UIStructureUtils.SetTemplateParent(newControl, this);
if (change.Property == SizeTypeProperty) {
if (LeftAddOn is PathIcon leftIconAddOn) {
SetupIconTypeAddOnSize(leftIconAddOn);
}
if (RightAddOn is PathIcon rightIconAddOn) {
SetupIconTypeAddOnSize(rightIconAddOn);
}
}
}
private void SetupIconTypeAddOnSize(PathIcon icon)
{
if (SizeType == SizeType.Large) {
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.WidthProperty, GlobalResourceKey.IconSizeLG);
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.HeightProperty, GlobalResourceKey.IconSizeLG);
} else if (SizeType == SizeType.Middle) {
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.WidthProperty, GlobalResourceKey.IconSize);
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.HeightProperty, GlobalResourceKey.IconSize);
} else {
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.WidthProperty, GlobalResourceKey.IconSizeSM);
TokenResourceBinder.CreateGlobalTokenBinding(icon, PathIcon.HeightProperty, GlobalResourceKey.IconSizeSM);
}
}

View File

@ -27,6 +27,7 @@ internal class AddOnDecoratedBoxTheme : BaseControlTheme
public const int ActivatedZIndex = 2000;
public AddOnDecoratedBoxTheme() : base(typeof(AddOnDecoratedBox)) { }
protected AddOnDecoratedBoxTheme(Type targetType) : base(targetType) { }
protected override IControlTemplate BuildControlTemplate()
{
@ -185,15 +186,6 @@ internal class AddOnDecoratedBoxTheme : BaseControlTheme
largeStyle.Add(addOnStyle);
}
{
// 左右 AddOn icon 的大小
var addOnContentIconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart).Descendant().OfType<PathIcon>(),
selector.Nesting().Template().Name(RightAddOnPart).Descendant().OfType<PathIcon>()));
addOnContentIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSizeLG);
addOnContentIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSizeLG);
largeStyle.Add(addOnContentIconStyle);
}
largeStyle.Add(AddOnDecoratedBox.FontSizeProperty, AddOnDecoratedBoxResourceKey.FontSizeLG);
largeStyle.Add(AddOnDecoratedBox.MinHeightProperty, GlobalResourceKey.FontHeightLG);
largeStyle.Add(AddOnDecoratedBox.CornerRadiusProperty, GlobalResourceKey.BorderRadiusLG);
@ -215,15 +207,6 @@ internal class AddOnDecoratedBoxTheme : BaseControlTheme
middleStyle.Add(addOnStyle);
}
{
// 左右 AddOn icon 的大小
var addOnContentIconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart).Descendant().OfType<PathIcon>(),
selector.Nesting().Template().Name(RightAddOnPart).Descendant().OfType<PathIcon>()));
addOnContentIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSize);
addOnContentIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSize);
middleStyle.Add(addOnContentIconStyle);
}
middleStyle.Add(AddOnDecoratedBox.FontSizeProperty, AddOnDecoratedBoxResourceKey.FontSize);
middleStyle.Add(AddOnDecoratedBox.MinHeightProperty, GlobalResourceKey.FontHeight);
middleStyle.Add(AddOnDecoratedBox.CornerRadiusProperty, GlobalResourceKey.BorderRadius);
@ -245,15 +228,6 @@ internal class AddOnDecoratedBoxTheme : BaseControlTheme
smallStyle.Add(addOnStyle);
}
{
// 左右 AddOn icon 的大小
var addOnContentIconStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(LeftAddOnPart).Descendant().OfType<PathIcon>(),
selector.Nesting().Template().Name(RightAddOnPart).Descendant().OfType<PathIcon>()));
addOnContentIconStyle.Add(PathIcon.WidthProperty, GlobalResourceKey.IconSizeSM);
addOnContentIconStyle.Add(PathIcon.HeightProperty, GlobalResourceKey.IconSizeSM);
smallStyle.Add(addOnContentIconStyle);
}
smallStyle.Add(AddOnDecoratedBox.FontSizeProperty, AddOnDecoratedBoxResourceKey.FontSizeSM);
smallStyle.Add(AddOnDecoratedBox.MinHeightProperty, GlobalResourceKey.FontHeightSM);
smallStyle.Add(AddOnDecoratedBox.CornerRadiusProperty, GlobalResourceKey.BorderRadiusSM);

View File

@ -27,6 +27,16 @@ internal class LineEditTheme : BaseControlTheme
protected override IControlTemplate BuildControlTemplate()
{
return new FuncControlTemplate<LineEdit>((lineEdit, scope) =>
{
var decoratedBox = BuildAddOnDecoratedBox(lineEdit, scope);
var lineEditKernel = BuildLineEditKernel(lineEdit, scope);
decoratedBox.Content = lineEditKernel;
lineEditKernel.RegisterInNameScope(scope);
return decoratedBox;
});
}
protected virtual AddOnDecoratedBox BuildAddOnDecoratedBox(LineEdit lineEdit, INameScope scope)
{
var decoratedBox = new AddOnDecoratedBox()
{
@ -39,11 +49,7 @@ internal class LineEditTheme : BaseControlTheme
CreateTemplateParentBinding(decoratedBox, AddOnDecoratedBox.LeftAddOnProperty, LineEdit.LeftAddOnProperty);
CreateTemplateParentBinding(decoratedBox, AddOnDecoratedBox.RightAddOnProperty, LineEdit.RightAddOnProperty);
decoratedBox.RegisterInNameScope(scope);
var lineEditKernel = BuildLineEditKernel(lineEdit, scope);
decoratedBox.Content = lineEditKernel;
lineEditKernel.RegisterInNameScope(scope);
return decoratedBox;
});
}
protected virtual LineEditInnerBox BuildLineEditKernel(LineEdit lineEdit, INameScope scope)

View File

@ -1,53 +1,48 @@
// using Avalonia;
//
// namespace AtomUI.Controls;
//
// public enum SearchEditButtonStyle
// {
// Default,
// Primary
// }
//
// public class SearchEdit : LineEdit
// {
// #region 公共属性定义
//
// public static readonly StyledProperty<SearchEditButtonStyle> SearchButtonStyleProperty =
// AvaloniaProperty.Register<SearchEdit, SearchEditButtonStyle>(nameof(SearchButtonStyle), SearchEditButtonStyle.Default);
//
// public static readonly StyledProperty<string> SearchButtonTextProperty =
// AvaloniaProperty.Register<SearchEdit, string>(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;
// }
// }
using AtomUI.Theme.Data;
using AtomUI.Theme.Styling;
using AtomUI.Utils;
using Avalonia;
using Avalonia.Controls.Primitives;
using Avalonia.Data;
namespace AtomUI.Controls;
public enum SearchEditButtonStyle
{
Default,
Primary
}
public class SearchEdit : LineEdit
{
#region
public static readonly StyledProperty<SearchEditButtonStyle> SearchButtonStyleProperty =
AvaloniaProperty.Register<SearchEdit, SearchEditButtonStyle>(nameof(SearchButtonStyle), SearchEditButtonStyle.Default);
public static readonly StyledProperty<string> SearchButtonTextProperty =
AvaloniaProperty.Register<SearchEdit, string>(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 OnApplyTemplate(TemplateAppliedEventArgs e)
{
base.OnApplyTemplate(e);
TokenResourceBinder.CreateGlobalResourceBinding(this, BorderThicknessProperty, GlobalResourceKey.BorderThickness,
BindingPriority.Template,
new RenderScaleAwareThicknessConfigure(this));
}
}

View File

@ -0,0 +1,28 @@
using Avalonia;
namespace AtomUI.Controls;
public class SearchEditDecoratedBox : AddOnDecoratedBox
{
#region
public static readonly StyledProperty<SearchEditButtonStyle> SearchButtonStyleProperty =
SearchEdit.SearchButtonStyleProperty.AddOwner<SearchEditDecoratedBox>();
public static readonly StyledProperty<string> SearchButtonTextProperty =
SearchEdit.SearchButtonTextProperty.AddOwner<SearchEditDecoratedBox>();
public SearchEditButtonStyle SearchButtonStyle
{
get => GetValue(SearchButtonStyleProperty);
set => SetValue(SearchButtonStyleProperty, value);
}
public object? SearchButtonText
{
get => GetValue(SearchButtonTextProperty);
set => SetValue(SearchButtonTextProperty, value);
}
#endregion
}

View File

@ -0,0 +1,81 @@
using AtomUI.Theme.Styling;
using Avalonia.Controls;
using Avalonia.Controls.Templates;
using Avalonia.Styling;
namespace AtomUI.Controls;
[ControlThemeProvider]
internal class SearchEditDecoratedBoxTheme : AddOnDecoratedBoxTheme
{
public SearchEditDecoratedBoxTheme() : base(typeof(SearchEditDecoratedBox))
{
}
protected override void BuildRightAddOn(Grid layout, INameScope scope)
{
var searchIcon = new PathIcon()
{
Kind = "SearchOutlined"
};
var searchButton = new Button()
{
Name = RightAddOnPart,
Focusable = false,
Icon = searchIcon,
};
searchButton.RegisterInNameScope(scope);
CreateTemplateParentBinding(searchButton, Button.TextProperty, SearchEditDecoratedBox.SearchButtonTextProperty);
CreateTemplateParentBinding(searchButton, Button.SizeTypeProperty, SearchEditDecoratedBox.SizeTypeProperty);
CreateTemplateParentBinding(searchButton, Button.BorderThicknessProperty, SearchEditDecoratedBox.RightAddOnBorderThicknessProperty);
CreateTemplateParentBinding(searchButton, Button.CornerRadiusProperty, SearchEditDecoratedBox.RightAddOnCornerRadiusProperty);
layout.Children.Add(searchButton);
Grid.SetColumn(searchButton, 2);
}
protected override void BuildStyles()
{
base.BuildStyles();
var decoratorStyle = new Style(selector => selector.Nesting().Template().Name(InnerBoxDecoratorPart));
decoratorStyle.Add(Border.ZIndexProperty, NormalZIndex);
Add(decoratorStyle);
var decoratorHoverOrFocusStyle = new Style(selector => Selectors.Or(selector.Nesting().Template().Name(InnerBoxDecoratorPart).Class(StdPseudoClass.FocusWithIn),
selector.Nesting().Template().Name(InnerBoxDecoratorPart).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);
}
}

View File

@ -1,85 +1,40 @@
using AtomUI.Theme.Styling;
using AtomUI.Data;
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);
// }
// }
[ControlThemeProvider]
internal class SearchEditTheme : LineEditTheme
{
public SearchEditTheme() : base(typeof(SearchEdit)) { }
protected override AddOnDecoratedBox BuildAddOnDecoratedBox(LineEdit lineEdit, INameScope scope)
{
var decoratedBox = new SearchEditDecoratedBox()
{
Name = DecoratedBoxPart,
Focusable = true
};
decoratedBox.RegisterInNameScope(scope);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.StyleVariantProperty, SearchEdit.StyleVariantProperty);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.SizeTypeProperty, SearchEdit.SizeTypeProperty);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.StatusProperty, SearchEdit.StatusProperty);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.LeftAddOnProperty, SearchEdit.LeftAddOnProperty);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.RightAddOnBorderThicknessProperty, SearchEdit.BorderThicknessProperty);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.SearchButtonStyleProperty, SearchEdit.SearchButtonStyleProperty);
CreateTemplateParentBinding(decoratedBox, SearchEditDecoratedBox.SearchButtonTextProperty, SearchEdit.SearchButtonTextProperty);
return decoratedBox;
}
protected override void BuildStyles()
{
base.BuildStyles();
}
}