mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-29 07:16:33 +08:00
Refactor TextBlock
This commit is contained in:
@@ -3,6 +3,7 @@ using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
|
||||
@@ -105,10 +105,10 @@ public class Tag : TemplatedControl
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly StyledProperty<double> TagTextPaddingInlineProperty
|
||||
= AvaloniaProperty.Register<Tag, double>(nameof(TagTextPaddingInline));
|
||||
internal static readonly StyledProperty<Thickness> TagTextPaddingInlineProperty
|
||||
= AvaloniaProperty.Register<Tag, Thickness>(nameof(TagTextPaddingInline));
|
||||
|
||||
internal double TagTextPaddingInline
|
||||
internal Thickness TagTextPaddingInline
|
||||
{
|
||||
get => GetValue(TagTextPaddingInlineProperty);
|
||||
set => SetValue(TagTextPaddingInlineProperty, value);
|
||||
@@ -153,7 +153,6 @@ public class Tag : TemplatedControl
|
||||
|
||||
private void HandleTemplateApplied(INameScope scope)
|
||||
{
|
||||
_layoutPanel = scope.Find<Canvas>(TagTheme.MainContainerPart);
|
||||
_closeButton = scope.Find<IconButton>(TagTheme.CloseButtonPart);
|
||||
_textBlock = scope.Find<TextBlock>(TagTheme.TagTextLabelPart);
|
||||
_iconContentPresenter = scope.Find<ContentPresenter>(TagTheme.IconPart);
|
||||
@@ -167,72 +166,7 @@ public class Tag : TemplatedControl
|
||||
SetupTagIcon();
|
||||
SetupTokenBindings();
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
base.MeasureOverride(availableSize);
|
||||
var targetWidth = 0d;
|
||||
var targetHeight = 0d;
|
||||
if (_layoutPanel is not null)
|
||||
{
|
||||
foreach (var child in _layoutPanel.Children)
|
||||
{
|
||||
targetWidth += child.DesiredSize.Width;
|
||||
targetHeight = Math.Max(targetHeight, child.DesiredSize.Height);
|
||||
}
|
||||
}
|
||||
|
||||
if (Icon is not null)
|
||||
{
|
||||
targetWidth += TagTextPaddingInline;
|
||||
}
|
||||
|
||||
if (IsClosable && _closeButton is not null)
|
||||
{
|
||||
targetWidth += TagTextPaddingInline;
|
||||
}
|
||||
|
||||
targetWidth += Padding.Left + Padding.Right;
|
||||
return new Size(targetWidth, targetHeight);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
if (_closeButton is not null)
|
||||
{
|
||||
var offsetX = finalSize.Width - Padding.Right - _closeButton.DesiredSize.Width;
|
||||
var offsetY = (finalSize.Height - _closeButton.DesiredSize.Height) / 2;
|
||||
Canvas.SetLeft(_closeButton, offsetX);
|
||||
Canvas.SetTop(_closeButton, offsetY);
|
||||
}
|
||||
|
||||
// icon
|
||||
if (_iconContentPresenter is not null)
|
||||
{
|
||||
var offsetX = Padding.Left;
|
||||
var offsetY = (finalSize.Height - _iconContentPresenter.DesiredSize.Height) / 2;
|
||||
Canvas.SetLeft(_iconContentPresenter, offsetX);
|
||||
Canvas.SetTop(_iconContentPresenter, offsetY);
|
||||
}
|
||||
|
||||
// 文字
|
||||
if (_textBlock is not null)
|
||||
{
|
||||
var offsetX = Padding.Left;
|
||||
if (Icon is not null)
|
||||
{
|
||||
offsetX += Icon.DesiredSize.Width + TagTextPaddingInline;
|
||||
}
|
||||
|
||||
// 这个时候已经算好了
|
||||
var offsetY = (finalSize.Height - _textBlock.Height) / 2;
|
||||
Canvas.SetLeft(_textBlock, offsetX);
|
||||
Canvas.SetTop(_textBlock, offsetY);
|
||||
}
|
||||
|
||||
return base.ArrangeOverride(finalSize);
|
||||
}
|
||||
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
@@ -424,16 +358,4 @@ public class Tag : TemplatedControl
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
_borderRenderHelper.Render(context,
|
||||
Bounds.Size,
|
||||
BorderThickness,
|
||||
CornerRadius,
|
||||
BackgroundSizing,
|
||||
Background,
|
||||
BorderBrush,
|
||||
default);
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,8 @@ namespace AtomUI.Controls;
|
||||
[ControlThemeProvider]
|
||||
internal class TagTheme : BaseControlTheme
|
||||
{
|
||||
public const string MainContainerPart = "PART_MainContainer";
|
||||
public const string ElementsLayoutPart = "PART_ElementsLayout";
|
||||
public const string FramePart = "PART_Frame";
|
||||
public const string IconPart = "PART_Icon";
|
||||
public const string CloseButtonPart = "PART_CloseButton";
|
||||
public const string TagTextLabelPart = "PART_TagTextLabel";
|
||||
@@ -25,12 +26,13 @@ internal class TagTheme : BaseControlTheme
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
this.Add(TemplatedControl.BackgroundProperty, TagTokenKey.DefaultBg);
|
||||
this.Add(TemplatedControl.ForegroundProperty, TagTokenKey.DefaultColor);
|
||||
this.Add(TemplatedControl.FontSizeProperty, TagTokenKey.TagFontSize);
|
||||
this.Add(TemplatedControl.PaddingProperty, TagTokenKey.TagPadding);
|
||||
this.Add(TemplatedControl.BorderBrushProperty, SharedTokenKey.ColorBorder);
|
||||
this.Add(TemplatedControl.CornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
|
||||
this.Add(Tag.BackgroundProperty, TagTokenKey.DefaultBg);
|
||||
this.Add(Tag.ForegroundProperty, TagTokenKey.DefaultColor);
|
||||
this.Add(Tag.FontSizeProperty, TagTokenKey.TagFontSize);
|
||||
this.Add(Tag.PaddingProperty, TagTokenKey.TagPadding);
|
||||
this.Add(Tag.BorderBrushProperty, SharedTokenKey.ColorBorder);
|
||||
this.Add(Tag.CornerRadiusProperty, SharedTokenKey.BorderRadiusSM);
|
||||
this.Add(Tag.HeightProperty, TagTokenKey.TagLineHeight);
|
||||
this.Add(Tag.TagTextPaddingInlineProperty, TagTokenKey.TagTextPaddingInline);
|
||||
}
|
||||
|
||||
@@ -38,49 +40,70 @@ internal class TagTheme : BaseControlTheme
|
||||
{
|
||||
return new FuncControlTemplate<Tag>((tag, scope) =>
|
||||
{
|
||||
var layout = new Canvas
|
||||
var rootLayout = new Panel();
|
||||
|
||||
var frameDecorator = new Border()
|
||||
{
|
||||
Name = MainContainerPart
|
||||
Name = FramePart
|
||||
};
|
||||
CreateTemplateParentBinding(frameDecorator, Border.BackgroundProperty, Tag.BackgroundProperty);
|
||||
CreateTemplateParentBinding(frameDecorator, Border.BorderBrushProperty, Tag.BorderBrushProperty);
|
||||
CreateTemplateParentBinding(frameDecorator, Border.CornerRadiusProperty, Tag.CornerRadiusProperty);
|
||||
CreateTemplateParentBinding(frameDecorator, Border.BorderThicknessProperty, Tag.BorderThicknessProperty);
|
||||
|
||||
layout.RegisterInNameScope(scope);
|
||||
rootLayout.Children.Add(frameDecorator);
|
||||
|
||||
var elementsLayout = new Grid
|
||||
{
|
||||
Name = ElementsLayoutPart,
|
||||
ColumnDefinitions =
|
||||
{
|
||||
new ColumnDefinition(GridLength.Auto),
|
||||
new ColumnDefinition(GridLength.Star),
|
||||
new ColumnDefinition(GridLength.Auto)
|
||||
}
|
||||
};
|
||||
CreateTemplateParentBinding(elementsLayout, Grid.MarginProperty, Tag.PaddingProperty);
|
||||
elementsLayout.RegisterInNameScope(scope);
|
||||
rootLayout.Children.Add(elementsLayout);
|
||||
|
||||
var iconContentPresenter = new ContentPresenter()
|
||||
{
|
||||
Name = IconPart
|
||||
};
|
||||
Grid.SetColumn(iconContentPresenter, 0);
|
||||
iconContentPresenter.RegisterInNameScope(scope);
|
||||
CreateTemplateParentBinding(iconContentPresenter, ContentPresenter.ContentProperty, Tag.IconProperty);
|
||||
layout.Children.Add(iconContentPresenter);
|
||||
elementsLayout.Children.Add(iconContentPresenter);
|
||||
|
||||
var textBlock = new TextBlock
|
||||
{
|
||||
Name = TagTextLabelPart,
|
||||
VerticalAlignment = VerticalAlignment.Center
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
Grid.SetColumn(textBlock, 1);
|
||||
textBlock.RegisterInNameScope(scope);
|
||||
CreateTemplateParentBinding(textBlock, TextBlock.TextProperty, Tag.TagTextProperty);
|
||||
layout.Children.Add(textBlock);
|
||||
CreateTemplateParentBinding(textBlock, TextBlock.PaddingProperty, Tag.TagTextPaddingInlineProperty);
|
||||
elementsLayout.Children.Add(textBlock);
|
||||
|
||||
var closeBtn = new IconButton
|
||||
{
|
||||
Name = CloseButtonPart
|
||||
};
|
||||
closeBtn.RegisterInNameScope(scope);
|
||||
|
||||
Grid.SetColumn(closeBtn, 2);
|
||||
TokenResourceBinder.CreateTokenBinding(closeBtn, IconButton.IconWidthProperty,
|
||||
SharedTokenKey.IconSizeXS);
|
||||
TokenResourceBinder.CreateTokenBinding(closeBtn, IconButton.IconHeightProperty,
|
||||
SharedTokenKey.IconSizeXS);
|
||||
TokenResourceBinder.CreateTokenBinding(textBlock, Layoutable.HeightProperty,
|
||||
TagTokenKey.TagLineHeight);
|
||||
|
||||
CreateTemplateParentBinding(closeBtn, Visual.IsVisibleProperty, Tag.IsClosableProperty);
|
||||
CreateTemplateParentBinding(closeBtn, IconButton.IconProperty, Tag.CloseIconProperty);
|
||||
|
||||
layout.Children.Add(closeBtn);
|
||||
elementsLayout.Children.Add(closeBtn);
|
||||
|
||||
return layout;
|
||||
return rootLayout;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ internal class TagToken : AbstractControlDesignToken
|
||||
public double TagIconSize { get; set; }
|
||||
public double TagCloseIconSize { get; set; }
|
||||
public Thickness TagPadding { get; set; }
|
||||
public double TagTextPaddingInline { get; set; }
|
||||
public Thickness TagTextPaddingInline { get; set; }
|
||||
public Color TagBorderlessBg { get; set; }
|
||||
|
||||
public TagToken()
|
||||
@@ -40,11 +40,11 @@ internal class TagToken : AbstractControlDesignToken
|
||||
TagLineHeight = SharedToken.LineHeightSM * TagFontSize;
|
||||
TagCloseIconSize = SharedToken.IconSizeXS;
|
||||
TagIconSize = SharedToken.FontSizeIcon;
|
||||
TagPadding = new Thickness(8, 0); // Fixed padding.
|
||||
TagPadding = new Thickness(SharedToken.SizeXS, 0);
|
||||
// TODO 这个地方需要看看
|
||||
DefaultBg = ColorUtils.OnBackground(SharedToken.ColorFillQuaternary, SharedToken.ColorBgContainer);
|
||||
TagBorderlessBg = DefaultBg;
|
||||
DefaultColor = SharedToken.ColorText;
|
||||
TagTextPaddingInline = SharedToken.PaddingXXS;
|
||||
TagTextPaddingInline = new Thickness(SharedToken.PaddingXXS, 0);
|
||||
}
|
||||
}
|
||||
@@ -58,29 +58,28 @@ public class TextBlock : AvaloniaTextBlock
|
||||
protected override void RenderTextLayout(DrawingContext context, Point origin)
|
||||
{
|
||||
var textHeight = TextLayout.Height;
|
||||
var top = origin.Y;
|
||||
var left = TextLayout.OverhangLeading;
|
||||
var left = origin.X;
|
||||
var top = origin.Y;
|
||||
if (TextLayout.TextLines.Count == 1)
|
||||
{
|
||||
|
||||
if (Bounds.Height >= textHeight)
|
||||
{
|
||||
var scale = LayoutHelper.GetLayoutScale(this);
|
||||
var padding = LayoutHelper.RoundLayoutThickness(Padding, scale, scale);
|
||||
switch (VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Center:
|
||||
top += _textMetrics.Descent / 2;
|
||||
break;
|
||||
|
||||
case VerticalAlignment.Bottom:
|
||||
top += Bounds.Height - textHeight;
|
||||
top = (DesiredSize.Height - _textMetrics.LineHeight - padding.Top - padding.Bottom) / 2 - _textMetrics.Descent;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (HorizontalAlignment == HorizontalAlignment.Center)
|
||||
{
|
||||
left += (TextLayout.OverhangLeading + TextLayout.OverhangTrailing) / 2;
|
||||
}
|
||||
}
|
||||
TextLayout.Draw(context, origin + new Point(left, top));
|
||||
TextLayout.Draw(context, new Point(left, top));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user