mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-23 09:48:48 +08:00
Refactor breadcrumb
This commit is contained in:
@@ -1,53 +1,43 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections.Specialized;
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class Breadcrumb : ItemsControl, IControlSharedTokenResourcesHost, IMotionAwareControl
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<IEnumerable?> ParamsProperty =
|
||||
AvaloniaProperty.Register<Breadcrumb, IEnumerable?>(
|
||||
nameof(Params));
|
||||
|
||||
public static readonly StyledProperty<double> IconSizeProperty =
|
||||
AvaloniaProperty.Register<Breadcrumb, double>(nameof(IconSize), defaultValue: 16);
|
||||
|
||||
public static readonly StyledProperty<string?> SeparatorProperty =
|
||||
AvaloniaProperty.Register<Breadcrumb, string?>(
|
||||
public static readonly StyledProperty<object?> SeparatorProperty =
|
||||
AvaloniaProperty.Register<Breadcrumb, object?>(
|
||||
nameof(Separator),
|
||||
defaultValue: "/"
|
||||
);
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate?> SeparatorTemplateProperty =
|
||||
AvaloniaProperty.Register<Breadcrumb, IDataTemplate?>(nameof (SeparatorTemplate));
|
||||
|
||||
public static readonly StyledProperty<bool> IsMotionEnabledProperty =
|
||||
MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner<Breadcrumb>();
|
||||
|
||||
public IEnumerable? Params
|
||||
{
|
||||
get => GetValue(ParamsProperty);
|
||||
set => SetValue(ParamsProperty, value);
|
||||
}
|
||||
|
||||
public double IconSize
|
||||
{
|
||||
get => GetValue(IconSizeProperty);
|
||||
set => SetValue(IconSizeProperty, value);
|
||||
}
|
||||
|
||||
public string? Separator
|
||||
[DependsOn("ContentTemplate")]
|
||||
public object? Separator
|
||||
{
|
||||
get => GetValue(SeparatorProperty);
|
||||
set => SetValue(SeparatorProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public IDataTemplate? SeparatorTemplate
|
||||
{
|
||||
get => GetValue(SeparatorTemplateProperty);
|
||||
set => SetValue(SeparatorTemplateProperty, value);
|
||||
}
|
||||
|
||||
public bool IsMotionEnabled
|
||||
{
|
||||
get => GetValue(IsMotionEnabledProperty);
|
||||
@@ -56,47 +46,62 @@ public class Breadcrumb : ItemsControl, IControlSharedTokenResourcesHost, IMotio
|
||||
|
||||
#endregion
|
||||
|
||||
#region 公共事件定义
|
||||
|
||||
public event EventHandler<BreadcrumbNavigateEventArgs>? NavigateRequest;
|
||||
|
||||
#endregion
|
||||
|
||||
Control IMotionAwareControl.PropertyBindTarget => this;
|
||||
Control IControlSharedTokenResourcesHost.HostControl => this;
|
||||
string IControlSharedTokenResourcesHost.TokenId => BreadcrumbToken.ID;
|
||||
|
||||
public Breadcrumb()
|
||||
{
|
||||
Items.CollectionChanged += OnItemsCollectionChanged;
|
||||
Items.CollectionChanged += HandleItemsCollectionChanged;
|
||||
this.RegisterResources();
|
||||
this.BindMotionProperties();
|
||||
}
|
||||
|
||||
private void OnItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
private void HandleItemsCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
// parse a property from axaml is async in Avalonia. So use Dispatcher.UIThread to make sure object property has a value
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
if (Items.Count > 0)
|
||||
{
|
||||
this._processChildItems();
|
||||
}, DispatcherPriority.Background);
|
||||
}
|
||||
|
||||
private void _processChildItems()
|
||||
{
|
||||
if (Items != null && Items.Count > 0)
|
||||
{
|
||||
var lastChildItem = Items[Items.Count - 1];
|
||||
foreach (var childItem in Items)
|
||||
for (int i = 0; i < ItemCount; i++)
|
||||
{
|
||||
if (childItem is BreadcrumbItem breadcrumbItem)
|
||||
var item = Items[i];
|
||||
if (item is BreadcrumbItem breadcrumbItem)
|
||||
{
|
||||
breadcrumbItem.IsLast = false;
|
||||
breadcrumbItem.EffectiveSeparator = ((breadcrumbItem.Separator ?? this.Separator)) ?? "/";
|
||||
breadcrumbItem.Content = breadcrumbItem.Value != null ? breadcrumbItem.Value.ToString() : breadcrumbItem.Content ;
|
||||
breadcrumbItem.IsLast = (i == ItemCount - 1);
|
||||
}
|
||||
}
|
||||
if (lastChildItem is BreadcrumbItem lastBreadcrumbItem)
|
||||
{
|
||||
lastBreadcrumbItem.IsLast = true;
|
||||
lastBreadcrumbItem.EffectiveSeparator = lastBreadcrumbItem.IsLast
|
||||
? string.Empty
|
||||
: ((lastBreadcrumbItem.Separator ?? this.Separator)) ?? string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
var breadcrumbItem = new BreadcrumbItem();
|
||||
// 避免破环 BreadcrumbItem 自行指定的分割符
|
||||
BindUtils.RelayBind(this, SeparatorProperty, breadcrumbItem, BreadcrumbItem.SeparatorProperty, BindingMode.Default, BindingPriority.Template);
|
||||
BindUtils.RelayBind(this, SeparatorTemplateProperty, breadcrumbItem, BreadcrumbItem.SeparatorTemplateProperty, BindingMode.Default, BindingPriority.Template);
|
||||
return breadcrumbItem;
|
||||
}
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
return NeedsContainer<BreadcrumbItem>(item, out recycleKey);
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(container, item, index);
|
||||
if (container is BreadcrumbItem breadcrumbItem)
|
||||
{
|
||||
breadcrumbItem[!BreadcrumbItem.IsMotionEnabledProperty] = this[!IsMotionEnabledProperty];
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyNavigateRequest(BreadcrumbItem breadcrumbItem)
|
||||
{
|
||||
NavigateRequest?.Invoke(this, new BreadcrumbNavigateEventArgs(breadcrumbItem));
|
||||
}
|
||||
}
|
||||
@@ -1,68 +1,77 @@
|
||||
using AtomUI.Animations;
|
||||
using System.Diagnostics;
|
||||
using AtomUI.Animations;
|
||||
using AtomUI.Controls.Utils;
|
||||
using AtomUI.IconPkg;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Mixins;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Animation;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.LogicalTree;
|
||||
using Avalonia.Metadata;
|
||||
using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[PseudoClasses(StdPseudoClass.Pressed, StdPseudoClass.Selected, BreadcrumbPseudoClass.HasIcon, BreadcrumbPseudoClass.IsLast)]
|
||||
public class BreadcrumbItem : ContentControl, ISelectable
|
||||
using AvaloniaButton = Avalonia.Controls.Button;
|
||||
|
||||
[PseudoClasses(StdPseudoClass.Pressed, BreadcrumbPseudoClass.HasIcon, BreadcrumbPseudoClass.IsLast)]
|
||||
public class BreadcrumbItem : AvaloniaButton
|
||||
{
|
||||
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<string?> SeparatorProperty =
|
||||
AvaloniaProperty.Register<BreadcrumbItem, string?>(nameof(Separator));
|
||||
public static readonly StyledProperty<Icon?> IconProperty =
|
||||
AvaloniaProperty.Register<BreadcrumbItem, Icon?>(nameof(Icon));
|
||||
|
||||
public static readonly StyledProperty<string?> ValueProperty =
|
||||
AvaloniaProperty.Register<BreadcrumbItem, string?>(nameof(Value));
|
||||
public static readonly StyledProperty<object?> NavigateContextProperty =
|
||||
AvaloniaProperty.Register<BreadcrumbItem, object?>(nameof(NavigateContext));
|
||||
|
||||
public static readonly StyledProperty<bool> IsSelectedProperty =
|
||||
SelectingItemsControl.IsSelectedProperty.AddOwner<BreadcrumbItem>();
|
||||
|
||||
public static readonly StyledProperty<Icon?> IconProperty
|
||||
= AvaloniaProperty.Register<BreadcrumbItem, Icon?>(nameof(Icon));
|
||||
public static readonly StyledProperty<Uri?> NavigateUriProperty =
|
||||
AvaloniaProperty.Register<BreadcrumbItem, Uri?>(
|
||||
nameof(NavigateUri),
|
||||
defaultValue: null);
|
||||
|
||||
public string? Separator
|
||||
public static readonly StyledProperty<object?> SeparatorProperty =
|
||||
Breadcrumb.SeparatorProperty.AddOwner<BreadcrumbItem>();
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate?> SeparatorTemplateProperty =
|
||||
Breadcrumb.SeparatorTemplateProperty.AddOwner<BreadcrumbItem>();
|
||||
|
||||
public object? NavigateContext
|
||||
{
|
||||
get => GetValue(SeparatorProperty);
|
||||
set => SetValue(SeparatorProperty, value);
|
||||
}
|
||||
|
||||
public string? Value
|
||||
{
|
||||
get => GetValue(ValueProperty);
|
||||
set => SetValue(ValueProperty, value);
|
||||
get => GetValue(NavigateContextProperty);
|
||||
set => SetValue(NavigateContextProperty, value);
|
||||
}
|
||||
|
||||
public bool IsSelected
|
||||
{
|
||||
get => GetValue(IsSelectedProperty);
|
||||
set => SetValue(IsSelectedProperty, value);
|
||||
}
|
||||
|
||||
public Icon? Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
set => SetValue(IconProperty, value);
|
||||
}
|
||||
|
||||
public Uri? NavigateUri
|
||||
{
|
||||
get => GetValue(NavigateUriProperty);
|
||||
set => SetValue(NavigateUriProperty, value);
|
||||
}
|
||||
|
||||
[DependsOn("ContentTemplate")]
|
||||
public object? Separator
|
||||
{
|
||||
get => GetValue(SeparatorProperty);
|
||||
set => SetValue(SeparatorProperty, value);
|
||||
}
|
||||
|
||||
public IDataTemplate? SeparatorTemplate
|
||||
{
|
||||
get => GetValue(SeparatorTemplateProperty);
|
||||
set => SetValue(SeparatorTemplateProperty, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly DirectProperty<BreadcrumbItem, string> EffectiveSeparatorProperty =
|
||||
AvaloniaProperty.RegisterDirect<BreadcrumbItem, string>(
|
||||
nameof(EffectiveSeparator),
|
||||
o => o.EffectiveSeparator,
|
||||
(o, v) => o.EffectiveSeparator = v);
|
||||
|
||||
internal static readonly StyledProperty<bool> IsMotionEnabledProperty =
|
||||
MotionAwareControlProperty.IsMotionEnabledProperty.AddOwner<BreadcrumbItem>();
|
||||
|
||||
@@ -72,13 +81,12 @@ public class BreadcrumbItem : ContentControl, ISelectable
|
||||
o => o.IsLast,
|
||||
(o, v) => o.IsLast = v);
|
||||
|
||||
private string _effectiveSeparator = string.Empty;
|
||||
internal string EffectiveSeparator
|
||||
{
|
||||
get => _effectiveSeparator;
|
||||
set => SetAndRaise(EffectiveSeparatorProperty, ref _effectiveSeparator, value);
|
||||
}
|
||||
|
||||
internal static readonly DirectProperty<BreadcrumbItem, bool> IsNavigateResponsiveProperty =
|
||||
AvaloniaProperty.RegisterDirect<BreadcrumbItem, bool>(
|
||||
nameof(IsNavigateResponsive),
|
||||
o => o.IsNavigateResponsive,
|
||||
(o, v) => o.IsNavigateResponsive = v);
|
||||
|
||||
internal bool IsMotionEnabled
|
||||
{
|
||||
get => GetValue(IsMotionEnabledProperty);
|
||||
@@ -92,21 +100,34 @@ public class BreadcrumbItem : ContentControl, ISelectable
|
||||
set => SetAndRaise(IsLastProperty, ref _isLast, value);
|
||||
}
|
||||
|
||||
private bool _isNavigateResponsive;
|
||||
internal bool IsNavigateResponsive
|
||||
{
|
||||
get => _isNavigateResponsive;
|
||||
set => SetAndRaise(IsNavigateResponsiveProperty, ref _isNavigateResponsive, value);
|
||||
}
|
||||
#endregion
|
||||
|
||||
static BreadcrumbItem()
|
||||
protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
|
||||
{
|
||||
AffectsRender<BreadcrumbItem>(BackgroundProperty);
|
||||
base.OnAttachedToLogicalTree(e);
|
||||
Debug.Assert(Parent is Breadcrumb, "BreadcrumbItem's Parent must be Breadcrumb Control.");
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == IconProperty || change.Property == IsLastProperty)
|
||||
if (change.Property == IconProperty ||
|
||||
change.Property == IsLastProperty)
|
||||
{
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
else if (change.Property == NavigateUriProperty ||
|
||||
change.Property == NavigateContextProperty)
|
||||
{
|
||||
IsNavigateResponsive = NavigateUri != null || NavigateContext != null;
|
||||
}
|
||||
|
||||
if (this.IsAttachedToVisualTree())
|
||||
{
|
||||
@@ -116,6 +137,13 @@ public class BreadcrumbItem : ContentControl, ISelectable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
ConfigureTransitions();
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
private void ConfigureTransitions()
|
||||
{
|
||||
@@ -123,6 +151,7 @@ public class BreadcrumbItem : ContentControl, ISelectable
|
||||
{
|
||||
Transitions = new Transitions
|
||||
{
|
||||
TransitionUtils.CreateTransition<SolidColorBrushTransition>(ForegroundProperty),
|
||||
TransitionUtils.CreateTransition<SolidColorBrushTransition>(BackgroundProperty)
|
||||
};
|
||||
}
|
||||
@@ -137,4 +166,24 @@ public class BreadcrumbItem : ContentControl, ISelectable
|
||||
PseudoClasses.Set(BreadcrumbPseudoClass.HasIcon, Icon is not null);
|
||||
PseudoClasses.Set(BreadcrumbPseudoClass.IsLast, IsLast);
|
||||
}
|
||||
|
||||
protected override void OnClick()
|
||||
{
|
||||
base.OnClick();
|
||||
if (IsNavigateResponsive)
|
||||
{
|
||||
if (Parent is Breadcrumb breadcrumb)
|
||||
{
|
||||
breadcrumb.NotifyNavigateRequest(this);
|
||||
}
|
||||
Uri? uri = NavigateUri;
|
||||
if (uri is not null)
|
||||
{
|
||||
Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
await TopLevel.GetTopLevel(this)!.Launcher.LaunchUriAsync(uri);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class BreadcrumbNavigateEventArgs : EventArgs
|
||||
{
|
||||
public BreadcrumbItem BreadcrumbItem { get; }
|
||||
|
||||
public BreadcrumbNavigateEventArgs(BreadcrumbItem breadcrumbItem)
|
||||
{
|
||||
BreadcrumbItem = breadcrumbItem;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
internal class BreadcrumbStackPanel : Panel
|
||||
{
|
||||
protected override Size MeasureOverride(Size availableSize)
|
||||
{
|
||||
var targetHeight = 0d;
|
||||
var targetWidth = 0d;
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (child is BreadcrumbItem box)
|
||||
{
|
||||
box.Measure(availableSize);
|
||||
targetWidth += box.DesiredSize.Width;
|
||||
targetHeight = Math.Max(targetHeight, box.DesiredSize.Height);
|
||||
}
|
||||
}
|
||||
|
||||
return new Size(targetWidth, targetHeight);
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
var previousChildSize = 0.0;
|
||||
var offsetX = 0d;
|
||||
var offsetY = 0d;
|
||||
foreach (var child in Children)
|
||||
{
|
||||
if (child is BreadcrumbItem box)
|
||||
{
|
||||
previousChildSize = box.DesiredSize.Width;
|
||||
box.Arrange(new Rect(new Point(offsetX, offsetY), box.DesiredSize));
|
||||
offsetX += previousChildSize;
|
||||
}
|
||||
}
|
||||
return finalSize;
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace AtomUI.Controls;
|
||||
internal class BreadcrumbToken : AbstractControlDesignToken
|
||||
{
|
||||
public const string ID = "Breadcrumb";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 图标大小
|
||||
/// </summary>
|
||||
@@ -18,37 +18,27 @@ internal class BreadcrumbToken : AbstractControlDesignToken
|
||||
/// 面包屑项文字颜色
|
||||
/// </summary>
|
||||
public Color ItemColor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 最后一项文字颜色
|
||||
/// </summary>
|
||||
public Color LastItemColor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 链接文字颜色
|
||||
/// </summary>
|
||||
public Color LinkColor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 链接文字悬浮颜色
|
||||
/// </summary>
|
||||
public Color LinkHoverColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 非最后一个面包屑导航的颜色
|
||||
/// </summary>
|
||||
public Color PrevLinkColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 链接文字悬浮背景颜色
|
||||
/// </summary>
|
||||
public Color LinkHoverBgColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// BreadcrumbItem之间的margin
|
||||
/// </summary>
|
||||
public Thickness BreadcrumbItemContentMargin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// BreadcrumbItem外面Border的Padding
|
||||
/// </summary>
|
||||
@@ -58,31 +48,29 @@ internal class BreadcrumbToken : AbstractControlDesignToken
|
||||
/// 分隔符颜色
|
||||
/// </summary>
|
||||
public Color SeparatorColor { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 分隔符外间距
|
||||
/// </summary>
|
||||
public Thickness SeparatorMargin { get; set; }
|
||||
|
||||
|
||||
public BreadcrumbToken()
|
||||
: base(ID)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
protected internal override void CalculateFromAlias()
|
||||
{
|
||||
base.CalculateFromAlias();
|
||||
IconSize = SharedToken.IconSize;
|
||||
var universalColor = SharedToken.ColorText;
|
||||
ItemColor = universalColor;
|
||||
LastItemColor = universalColor;
|
||||
LinkColor = universalColor;
|
||||
PrevLinkColor = SharedToken.ColorTextDisabled;
|
||||
IconSize = SharedToken.IconSize;
|
||||
ItemColor = SharedToken.ColorTextDescription;
|
||||
LastItemColor = SharedToken.ColorText;
|
||||
LinkColor = SharedToken.ColorTextDescription;
|
||||
LinkHoverColor = SharedToken.ColorText;
|
||||
LinkHoverBgColor = SharedToken.ColorBgTextHover;
|
||||
SeparatorColor = universalColor;
|
||||
SeparatorMargin = SharedToken.MarginMD;
|
||||
BreadcrumbItemContentMargin = new Thickness(SharedToken.UniformlyPaddingXXS, 0, 0, 0);
|
||||
BreadcrumbItemContentPadding = new Thickness(SharedToken.UniformlyPaddingXXS, SharedToken.UniformlyPaddingXXS, SharedToken.UniformlyPaddingXXS, SharedToken.UniformlyPaddingXXS);
|
||||
SeparatorColor = SharedToken.ColorTextDescription;
|
||||
SeparatorMargin = new Thickness(SharedToken.UniformlyMarginXXS, 0);
|
||||
BreadcrumbItemContentPadding = new Thickness(SharedToken.UniformlyPaddingXXS, SharedToken.UniformlyPaddingXXS,
|
||||
SharedToken.UniformlyPaddingXXS, SharedToken.UniformlyPaddingXXS);
|
||||
}
|
||||
}
|
||||
@@ -2,91 +2,69 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:atom="https://atomui.net">
|
||||
<atom:BoolToThicknessConverter x:Key="BoolToThicknessConverter" />
|
||||
<atom:StringToTextBlockConverter x:Key="StringToTextBlockConverter" VerticalAlignment="Center" />
|
||||
<ControlTheme x:Key="{x:Type atom:BreadcrumbItem}" TargetType="atom:BreadcrumbItem">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<StackPanel Name="ROOTLayout"
|
||||
Background="{TemplateBinding Background}"
|
||||
Orientation="Horizontal"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<Border Name="BorderItemPart"
|
||||
Background="Transparent"
|
||||
<StackPanel Name="RootLayout" Orientation="Horizontal">
|
||||
<Border Name="ContentInfoFrame"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<StackPanel Name="StackPanelItemPart"
|
||||
Orientation="Horizontal"
|
||||
Background="Transparent"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Center">
|
||||
<atom:IconPresenter Name="PART_IconPresenter"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
Background="{TemplateBinding Background}">
|
||||
<StackPanel Orientation="Horizontal" Spacing="{DynamicResource {x:Static atom:SharedTokenKey.SpacingXXS}}">
|
||||
<atom:IconPresenter Name="IconPresenter"
|
||||
Icon="{TemplateBinding Icon}"
|
||||
NormalFilledBrush="{DynamicResource {x:Static atom:BreadcrumbTokenKey.PrevLinkColor}}"
|
||||
IsVisible="{TemplateBinding Icon, Converter={x:Static ObjectConverters.IsNotNull}}" />
|
||||
<ContentPresenter Name="PART_Content"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Content="{TemplateBinding Content, Converter={StaticResource StringToTextBlockConverter}}"
|
||||
IsVisible="{TemplateBinding Content, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<Border Name="BorderSeparatorPart"
|
||||
Padding="{TemplateBinding Padding}">
|
||||
<StackPanel>
|
||||
<ContentPresenter Name="PART_Seprator"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static atom:SharedTokenKey.ColorTextDisabled}}"
|
||||
Content="{TemplateBinding EffectiveSeparator}"
|
||||
IsVisible="{TemplateBinding EffectiveSeparator, Converter={x:Static ObjectConverters.IsNotNull}}"
|
||||
<ContentPresenter Name="Content"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</StackPanel>
|
||||
</Border>
|
||||
<ContentPresenter Name="Separator"
|
||||
HorizontalContentAlignment="Center"
|
||||
VerticalContentAlignment="Center"
|
||||
Foreground="{DynamicResource {x:Static atom:BreadcrumbTokenKey.SeparatorColor}}"
|
||||
Content="{TemplateBinding Separator}"
|
||||
Margin="{DynamicResource {x:Static atom:BreadcrumbTokenKey.SeparatorMargin}}"
|
||||
ContentTemplate="{TemplateBinding SeparatorTemplate}"
|
||||
IsVisible="{TemplateBinding IsLast, Converter={x:Static BoolConverters.Not}}"/>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.BreadcrumbItemContentPadding}}"></Setter>
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}"></Setter>
|
||||
<Setter Property="Padding" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.BreadcrumbItemContentPadding}}"/>
|
||||
<Setter Property="CornerRadius" Value="{DynamicResource {x:Static atom:SharedTokenKey.BorderRadius}}"/>
|
||||
<Setter Property="Background" Value="Transparent"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.ItemColor}}"/>
|
||||
|
||||
<Style Selector="^ /template/ atom|IconPresenter#PART_IconPresenter">
|
||||
<Setter Property="IconWidth"
|
||||
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeSM}}" />
|
||||
<Setter Property="IconHeight"
|
||||
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeSM}}" />
|
||||
<Style Selector="^[IsLast=True][IsNavigateResponsive=False]">
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.LastItemColor}}"/>
|
||||
</Style>
|
||||
|
||||
<!-- 非最后一个:浅灰色 -->
|
||||
<Style Selector="^:not(:is-last) /template/ ContentPresenter#PART_Content">
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.PrevLinkColor}}"/>
|
||||
</Style>
|
||||
|
||||
<!-- 如果有icon的话,搞出来一个margin当间隔 -->
|
||||
<Style Selector="^:has-icon">
|
||||
<Style Selector="^ /template/ ContentPresenter#PART_Content">
|
||||
<Setter Property="Margin"
|
||||
Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.BreadcrumbItemContentMargin}}" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<!-- 当鼠标掠过的时候 -->
|
||||
<Style Selector="^ /template/ Border#BorderItemPart">
|
||||
<Style Selector="^[IsNavigateResponsive=True]">
|
||||
<Setter Property="Cursor" Value="Hand"/>
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.LinkColor}}"/>
|
||||
|
||||
<Style Selector="^:pointerover">
|
||||
<Setter Property="Background"
|
||||
Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.LinkHoverBgColor}}" />
|
||||
<Style Selector="^ ContentPresenter#PART_Content">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.LinkHoverColor}}" />
|
||||
</Style>
|
||||
<Style Selector="^ atom|IconPresenter#PART_IconPresenter">
|
||||
<Setter Property="Foreground"
|
||||
Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.LinkHoverColor}}" />
|
||||
|
||||
<Style Selector="^ atom|IconPresenter#IconPresenter">
|
||||
<Setter Property="NormalFilledBrush"
|
||||
Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.LinkHoverColor}}" />
|
||||
</Style>
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^ /template/ atom|IconPresenter#IconPresenter">
|
||||
<Setter Property="NormalFilledBrush"
|
||||
Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.ItemColor}}" />
|
||||
<Setter Property="IconWidth"
|
||||
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeSM}}" />
|
||||
<Setter Property="IconHeight"
|
||||
Value="{DynamicResource {x:Static atom:SharedTokenKey.IconSizeSM}}" />
|
||||
</Style>
|
||||
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -2,29 +2,22 @@
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:atom="https://atomui.net">
|
||||
<atom:BoolToThicknessConverter x:Key="BoolToThicknessConverter" />
|
||||
<ControlTheme x:Key="{x:Type atom:Breadcrumb}" TargetType="atom:Breadcrumb">
|
||||
<Setter Property="HorizontalAlignment" Value="Left" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.ItemColor}}" />
|
||||
<Setter Property="IconSize" Value="{DynamicResource {x:Static atom:BreadcrumbTokenKey.IconSize}}" />
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<Border Name="{x:Static atom:BreadcrumbConstants.FramePart}"
|
||||
CornerRadius="{TemplateBinding CornerRadius}"
|
||||
Padding="{TemplateBinding Padding}"
|
||||
ClipToBounds="True"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center">
|
||||
<ItemsPresenter Name="{x:Static atom:BreadcrumbConstants.TextPresenterPart}">
|
||||
<ItemsPresenter.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<atom:BreadcrumbStackPanel />
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsPresenter.ItemsPanel>
|
||||
</ItemsPresenter>
|
||||
</Border>
|
||||
<ItemsPresenter>
|
||||
<ItemsPresenter.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<StackPanel Orientation="Horizontal"/>
|
||||
</ItemsPanelTemplate>
|
||||
</ItemsPresenter.ItemsPanel>
|
||||
</ItemsPresenter>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
|
||||
<Setter Property="IsMotionEnabled" Value="{DynamicResource {x:Static atom:SharedTokenKey.EnableMotion}}" />
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
-14
@@ -90,7 +90,6 @@ namespace AtomUI.Theme.Styling
|
||||
|
||||
public static class BreadcrumbTokenKey
|
||||
{
|
||||
public static readonly TokenResourceKey BreadcrumbItemContentMargin = new TokenResourceKey("Breadcrumb.BreadcrumbItemContentMargin");
|
||||
public static readonly TokenResourceKey BreadcrumbItemContentPadding = new TokenResourceKey("Breadcrumb.BreadcrumbItemContentPadding");
|
||||
public static readonly TokenResourceKey IconSize = new TokenResourceKey("Breadcrumb.IconSize");
|
||||
public static readonly TokenResourceKey ItemColor = new TokenResourceKey("Breadcrumb.ItemColor");
|
||||
@@ -98,23 +97,10 @@ namespace AtomUI.Theme.Styling
|
||||
public static readonly TokenResourceKey LinkColor = new TokenResourceKey("Breadcrumb.LinkColor");
|
||||
public static readonly TokenResourceKey LinkHoverBgColor = new TokenResourceKey("Breadcrumb.LinkHoverBgColor");
|
||||
public static readonly TokenResourceKey LinkHoverColor = new TokenResourceKey("Breadcrumb.LinkHoverColor");
|
||||
public static readonly TokenResourceKey PrevLinkColor = new TokenResourceKey("Breadcrumb.PrevLinkColor");
|
||||
public static readonly TokenResourceKey SeparatorColor = new TokenResourceKey("Breadcrumb.SeparatorColor");
|
||||
public static readonly TokenResourceKey SeparatorMargin = new TokenResourceKey("Breadcrumb.SeparatorMargin");
|
||||
}
|
||||
|
||||
public static class ButtonSpinnerTokenKey
|
||||
{
|
||||
public static readonly TokenResourceKey ControlWidth = new TokenResourceKey("ButtonSpinner.ControlWidth");
|
||||
public static readonly TokenResourceKey FilledHandleBg = new TokenResourceKey("ButtonSpinner.FilledHandleBg");
|
||||
public static readonly TokenResourceKey HandleActiveBg = new TokenResourceKey("ButtonSpinner.HandleActiveBg");
|
||||
public static readonly TokenResourceKey HandleBg = new TokenResourceKey("ButtonSpinner.HandleBg");
|
||||
public static readonly TokenResourceKey HandleBorderColor = new TokenResourceKey("ButtonSpinner.HandleBorderColor");
|
||||
public static readonly TokenResourceKey HandleHoverColor = new TokenResourceKey("ButtonSpinner.HandleHoverColor");
|
||||
public static readonly TokenResourceKey HandleIconSize = new TokenResourceKey("ButtonSpinner.HandleIconSize");
|
||||
public static readonly TokenResourceKey HandleWidth = new TokenResourceKey("ButtonSpinner.HandleWidth");
|
||||
}
|
||||
|
||||
public static class ButtonTokenKey
|
||||
{
|
||||
public static readonly TokenResourceKey BorderColorDisabled = new TokenResourceKey("Button.BorderColorDisabled");
|
||||
|
||||
Reference in New Issue
Block a user