mirror of
https://gitee.com/chinware/atomui.git
synced 2024-11-29 18:38:16 +08:00
Merge pull request #14 from yushuailiu/feature/timeline
Feature/timeline
This commit is contained in:
commit
52904cff8c
@ -103,6 +103,8 @@
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TabStripItemTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TabStripTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TagTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TimelineItemTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TimelineTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.RangeTimePickerTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TimePickerFlyoutPresenterTheme());
|
||||
ThemeManager.Current.RegisterControlTheme(new AtomUI.Controls.TimePickerPresenterTheme());
|
||||
|
@ -1,17 +1,17 @@
|
||||
namespace AtomUI.Theme
|
||||
{
|
||||
internal class LanguageProviderRegister
|
||||
{
|
||||
internal static void Register()
|
||||
{
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.DatePickerLang.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.DatePickerLang.zh_CN());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.Localization.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.Localization.zh_CN());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.PopupConfirmLang.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.PopupConfirmLang.zh_CN());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.TimePickerLang.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.TimePickerLang.zh_CN());
|
||||
}
|
||||
}
|
||||
namespace AtomUI.Theme
|
||||
{
|
||||
internal class LanguageProviderRegister
|
||||
{
|
||||
internal static void Register()
|
||||
{
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.DatePickerLang.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.DatePickerLang.zh_CN());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.Localization.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.Localization.zh_CN());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.PopupConfirmLang.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.PopupConfirmLang.zh_CN());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.TimePickerLang.en_US());
|
||||
ThemeManager.Current.RegisterLanguageProvider(new AtomUI.Controls.TimePickerLang.zh_CN());
|
||||
}
|
||||
}
|
||||
}
|
@ -1,38 +1,38 @@
|
||||
using AtomUI.Theme;
|
||||
|
||||
namespace AtomUI.Controls.DatePickerLang
|
||||
{
|
||||
public static class DatePickerLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey Today = new LanguageResourceKey("DatePicker.Today", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey Now = new LanguageResourceKey("DatePicker.Now", "AtomUI.Lang");
|
||||
}
|
||||
}
|
||||
|
||||
namespace AtomUI.Controls.Localization
|
||||
{
|
||||
public static class CommonLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey OkText = new LanguageResourceKey("Common.OkText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey CancelText = new LanguageResourceKey("Common.CancelText", "AtomUI.Lang");
|
||||
}
|
||||
}
|
||||
|
||||
namespace AtomUI.Controls.PopupConfirmLang
|
||||
{
|
||||
public static class PopupConfirmLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey OkText = new LanguageResourceKey("PopupConfirm.OkText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey CancelText = new LanguageResourceKey("PopupConfirm.CancelText", "AtomUI.Lang");
|
||||
}
|
||||
}
|
||||
|
||||
namespace AtomUI.Controls.TimePickerLang
|
||||
{
|
||||
public static class TimePickerLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey AMText = new LanguageResourceKey("TimePicker.AMText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey PMText = new LanguageResourceKey("TimePicker.PMText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey Now = new LanguageResourceKey("TimePicker.Now", "AtomUI.Lang");
|
||||
}
|
||||
using AtomUI.Theme;
|
||||
|
||||
namespace AtomUI.Controls.DatePickerLang
|
||||
{
|
||||
public static class DatePickerLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey Today = new LanguageResourceKey("DatePicker.Today", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey Now = new LanguageResourceKey("DatePicker.Now", "AtomUI.Lang");
|
||||
}
|
||||
}
|
||||
|
||||
namespace AtomUI.Controls.Localization
|
||||
{
|
||||
public static class CommonLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey OkText = new LanguageResourceKey("Common.OkText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey CancelText = new LanguageResourceKey("Common.CancelText", "AtomUI.Lang");
|
||||
}
|
||||
}
|
||||
|
||||
namespace AtomUI.Controls.PopupConfirmLang
|
||||
{
|
||||
public static class PopupConfirmLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey OkText = new LanguageResourceKey("PopupConfirm.OkText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey CancelText = new LanguageResourceKey("PopupConfirm.CancelText", "AtomUI.Lang");
|
||||
}
|
||||
}
|
||||
|
||||
namespace AtomUI.Controls.TimePickerLang
|
||||
{
|
||||
public static class TimePickerLangResourceKey
|
||||
{
|
||||
public static readonly LanguageResourceKey AMText = new LanguageResourceKey("TimePicker.AMText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey PMText = new LanguageResourceKey("TimePicker.PMText", "AtomUI.Lang");
|
||||
public static readonly LanguageResourceKey Now = new LanguageResourceKey("TimePicker.Now", "AtomUI.Lang");
|
||||
}
|
||||
}
|
@ -39,6 +39,7 @@
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.ToggleSwitchToken));
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.TabControlToken));
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.TagToken));
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.TimelineToken));
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.TimePickerToken));
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.ToolTipToken));
|
||||
ThemeManager.Current.RegisterControlTokenType(typeof(AtomUI.Controls.TreeViewToken));
|
||||
|
@ -650,6 +650,23 @@ namespace AtomUI.Theme.Styling
|
||||
public static readonly TokenResourceKey TagBorderlessBg = new TokenResourceKey("Tag.TagBorderlessBg", "AtomUI.Token");
|
||||
}
|
||||
|
||||
public static class TimelineTokenResourceKey
|
||||
{
|
||||
public static readonly TokenResourceKey TailColor = new TokenResourceKey("Timeline.TailColor", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey TailWidth = new TokenResourceKey("Timeline.TailWidth", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey DotBorderWidth = new TokenResourceKey("Timeline.DotBorderWidth", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemSelectedColor = new TokenResourceKey("Timeline.ItemSelectedColor", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey DotBg = new TokenResourceKey("Timeline.DotBg", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemBgColor = new TokenResourceKey("Timeline.ItemBgColor", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemPaddingBottom = new TokenResourceKey("Timeline.ItemPaddingBottom", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey RightMargin = new TokenResourceKey("Timeline.RightMargin", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey LeftMargin = new TokenResourceKey("Timeline.LeftMargin", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey LastItemContentMinHeight = new TokenResourceKey("Timeline.LastItemContentMinHeight", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey FontSize = new TokenResourceKey("Timeline.FontSize", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey ItemHeadSize = new TokenResourceKey("Timeline.ItemHeadSize", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey CustomHeadSize = new TokenResourceKey("Timeline.CustomHeadSize", "AtomUI.Token");
|
||||
}
|
||||
|
||||
public static class TimePickerTokenResourceKey
|
||||
{
|
||||
public static readonly TokenResourceKey ItemHeight = new TokenResourceKey("TimePicker.ItemHeight", "AtomUI.Token");
|
||||
|
@ -18,8 +18,14 @@ public class ListBox : AvaloniaListBox
|
||||
public static readonly StyledProperty<SizeType> SizeTypeProperty =
|
||||
AvaloniaProperty.Register<ListBox, SizeType>(nameof(SizeType), SizeType.Middle);
|
||||
|
||||
#endregion
|
||||
public static readonly StyledProperty<bool> DisabledItemHoverEffectProperty =
|
||||
AvaloniaProperty.Register<ListBox, bool>(nameof(DisabledItemHoverEffect));
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
return new ListBoxItem();
|
||||
}
|
||||
|
||||
public SizeType SizeType
|
||||
{
|
||||
@ -33,8 +39,6 @@ public class ListBox : AvaloniaListBox
|
||||
set => SetValue(DisabledItemHoverEffectProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
return base.ArrangeOverride(finalSize.Deflate(new Thickness(BorderThickness.Left,
|
||||
@ -62,4 +66,4 @@ public class ListBox : AvaloniaListBox
|
||||
BindingPriority.Template,
|
||||
new RenderScaleAwareThicknessConfigure(this));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
201
src/AtomUI.Controls/Timeline/Timeline.cs
Normal file
201
src/AtomUI.Controls/Timeline/Timeline.cs
Normal file
@ -0,0 +1,201 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.Icon;
|
||||
using AtomUI.Theme.Data;
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Layout;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public enum TimeLineMode
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Alternate
|
||||
}
|
||||
|
||||
public class Timeline : ItemsControl
|
||||
{
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<TimeLineMode> ModeProperty =
|
||||
AvaloniaProperty.Register<Timeline, TimeLineMode>(nameof(Mode), TimeLineMode.Left);
|
||||
|
||||
public static readonly StyledProperty<string> PendingProperty =
|
||||
AvaloniaProperty.Register<Timeline, string>(nameof(Pending), "");
|
||||
|
||||
public static readonly StyledProperty<bool> ReverseProperty =
|
||||
AvaloniaProperty.Register<Timeline, bool>(nameof(Reverse), false);
|
||||
|
||||
public static readonly StyledProperty<PathIcon?> PendingIconProperty =
|
||||
AvaloniaProperty.Register<Alert, PathIcon?>(nameof(PendingIcon));
|
||||
|
||||
public TimeLineMode Mode
|
||||
{
|
||||
get => GetValue(ModeProperty);
|
||||
set => SetValue(ModeProperty, value);
|
||||
}
|
||||
|
||||
public string Pending
|
||||
{
|
||||
get => GetValue(PendingProperty);
|
||||
set => SetValue(PendingProperty, value);
|
||||
}
|
||||
|
||||
public bool Reverse
|
||||
{
|
||||
get => GetValue(ReverseProperty);
|
||||
set { SetValue(ReverseProperty, value); }
|
||||
}
|
||||
|
||||
public PathIcon? PendingIcon
|
||||
{
|
||||
get => GetValue(PendingIconProperty);
|
||||
set => SetValue(PendingIconProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private TimelineItem? _pendingItem;
|
||||
|
||||
static Timeline()
|
||||
{
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride(object? item, int index, object? recycleKey)
|
||||
{
|
||||
return new TimelineItem();
|
||||
}
|
||||
|
||||
protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey)
|
||||
{
|
||||
return NeedsContainer<TimelineItem>(item, out recycleKey);
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control element, object? item, int index)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(element, item, index);
|
||||
if (element is TimelineItem timelineItem)
|
||||
{
|
||||
BindUtils.RelayBind(this, ModeProperty, timelineItem, TimelineItem.ModeProperty);
|
||||
BindUtils.RelayBind(this, ReverseProperty, timelineItem, TimelineItem.ReverseProperty);
|
||||
BindUtils.RelayBind(this, ItemCountProperty, timelineItem, TimelineItem.CountProperty);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
OnReversePropertyChanged();
|
||||
addPendingItem();
|
||||
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, BorderThicknessProperty,
|
||||
GlobalTokenResourceKey.BorderThickness,
|
||||
BindingPriority.Template,
|
||||
new RenderScaleAwareThicknessConfigure(this));
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
if (change.Property == ReverseProperty && VisualRoot is not null)
|
||||
{
|
||||
OnReversePropertyChanged();
|
||||
}
|
||||
|
||||
if (change.Property == ItemCountProperty && VisualRoot is not null)
|
||||
{
|
||||
OnItemCountPropertyChanged();
|
||||
}
|
||||
|
||||
if (change.Property == PendingProperty && VisualRoot is not null)
|
||||
{
|
||||
OnPendingPropertyChanged();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void OnPendingPropertyChanged()
|
||||
{
|
||||
foreach (var item in Items)
|
||||
{
|
||||
if (item is TimelineItem timelineItem && timelineItem.IsPending)
|
||||
{
|
||||
Items.Remove(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
addPendingItem();
|
||||
}
|
||||
|
||||
private void addPendingItem()
|
||||
{
|
||||
if (!String.IsNullOrEmpty(Pending))
|
||||
{
|
||||
if (_pendingItem is null)
|
||||
{
|
||||
_pendingItem = new TimelineItem();
|
||||
var textBlock = new TextBlock();
|
||||
|
||||
if (PendingIcon is null)
|
||||
{
|
||||
PendingIcon = new PathIcon
|
||||
{
|
||||
Kind = "LoadingOutlined",
|
||||
Width = 10,
|
||||
Height = 10,
|
||||
LoadingAnimation = IconAnimation.Spin,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
HorizontalAlignment = HorizontalAlignment.Center,
|
||||
};
|
||||
}
|
||||
|
||||
_pendingItem.DotIcon = PendingIcon;
|
||||
_pendingItem.IsPending = true;
|
||||
_pendingItem.Content = textBlock;
|
||||
BindUtils.RelayBind(this, PendingProperty, textBlock, TextBlock.TextProperty);
|
||||
}
|
||||
|
||||
if (Reverse)
|
||||
{
|
||||
Items.Insert(0, _pendingItem);
|
||||
}
|
||||
else
|
||||
{
|
||||
Items.Add(_pendingItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnItemCountPropertyChanged()
|
||||
{
|
||||
}
|
||||
|
||||
private void OnReversePropertyChanged()
|
||||
{
|
||||
var items = Items.Cast<object>().ToList();
|
||||
items.Reverse();
|
||||
Items.Clear();
|
||||
foreach (var item in items)
|
||||
{
|
||||
Items.Add(item);
|
||||
if (item is TimelineItem timelineItem)
|
||||
{
|
||||
timelineItem.Index = Items.IndexOf(item);
|
||||
}
|
||||
}
|
||||
foreach (var item in items)
|
||||
{
|
||||
if (item is TimelineItem timelineItem)
|
||||
{
|
||||
timelineItem.Index = Items.IndexOf(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
361
src/AtomUI.Controls/Timeline/TimelineItem.cs
Normal file
361
src/AtomUI.Controls/Timeline/TimelineItem.cs
Normal file
@ -0,0 +1,361 @@
|
||||
using AtomUI.Theme.Styling;
|
||||
using AtomUI.Utils;
|
||||
using Avalonia;
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
public class TimelineItem : ContentControl
|
||||
{
|
||||
internal const string PendingNodePC = ":pending";
|
||||
internal const string ContentLeftPC = ":ContentLeft";
|
||||
internal const string LabelLeftPC = ":labelLeft";
|
||||
|
||||
#region 公共属性定义
|
||||
|
||||
public static readonly StyledProperty<string?> LabelProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, string?>(nameof(Label));
|
||||
|
||||
public static readonly StyledProperty<PathIcon?> DotIconProperty =
|
||||
AvaloniaProperty.Register<Alert, PathIcon?>(nameof(DotIcon));
|
||||
|
||||
public static readonly StyledProperty<string> ColorProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, string>(nameof(Color), "blue");
|
||||
|
||||
public string? Label
|
||||
{
|
||||
get => GetValue(LabelProperty);
|
||||
set => SetValue(LabelProperty, value);
|
||||
}
|
||||
|
||||
public PathIcon? DotIcon
|
||||
{
|
||||
get => GetValue(DotIconProperty);
|
||||
set => SetValue(DotIconProperty, value);
|
||||
}
|
||||
|
||||
public string Color
|
||||
{
|
||||
get => GetValue(ColorProperty);
|
||||
set => SetValue(ColorProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 内部属性定义
|
||||
|
||||
internal static readonly StyledProperty<int> IndexProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, int>(nameof(Index), 0);
|
||||
|
||||
internal static readonly StyledProperty<int> CountProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, int>(nameof(Count), 0);
|
||||
|
||||
internal static readonly StyledProperty<TimeLineMode> ModeProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, TimeLineMode>(nameof(Mode), TimeLineMode.Left);
|
||||
|
||||
internal static readonly StyledProperty<bool> HasLabelProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, bool>(nameof(HasLabel), false);
|
||||
|
||||
internal static readonly StyledProperty<bool> IsLastProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, bool>(nameof(IsLast), false);
|
||||
|
||||
internal static readonly StyledProperty<bool> ReverseProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, bool>(nameof(Reverse), false);
|
||||
|
||||
internal static readonly StyledProperty<bool> IsPendingProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, bool>(nameof(IsPending), false);
|
||||
|
||||
internal static readonly StyledProperty<HorizontalAlignment> ContentTextAlignProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, HorizontalAlignment>(nameof(ContentTextAlign),
|
||||
HorizontalAlignment.Left);
|
||||
|
||||
internal static readonly StyledProperty<HorizontalAlignment> LabelTextAlignProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, HorizontalAlignment>(nameof(LabelTextAlign), HorizontalAlignment.Left);
|
||||
|
||||
internal int Index
|
||||
{
|
||||
get => GetValue(IndexProperty);
|
||||
set => SetValue(IndexProperty, value);
|
||||
}
|
||||
|
||||
internal int Count
|
||||
{
|
||||
get => GetValue(CountProperty);
|
||||
set => SetValue(CountProperty, value);
|
||||
}
|
||||
|
||||
internal TimeLineMode Mode
|
||||
{
|
||||
get => GetValue(ModeProperty);
|
||||
set => SetValue(ModeProperty, value);
|
||||
}
|
||||
|
||||
internal bool HasLabel
|
||||
{
|
||||
get => GetValue(HasLabelProperty);
|
||||
set => SetValue(HasLabelProperty, value);
|
||||
}
|
||||
|
||||
internal bool IsLast
|
||||
{
|
||||
get => GetValue(IsLastProperty);
|
||||
set => SetValue(IsLastProperty, value);
|
||||
}
|
||||
|
||||
internal bool Reverse
|
||||
{
|
||||
get => GetValue(ReverseProperty);
|
||||
set => SetValue(ReverseProperty, value);
|
||||
}
|
||||
|
||||
internal bool IsPending
|
||||
{
|
||||
get => GetValue(IsPendingProperty);
|
||||
set => SetValue(IsPendingProperty, value);
|
||||
}
|
||||
|
||||
internal HorizontalAlignment ContentTextAlign
|
||||
{
|
||||
get => GetValue(ContentTextAlignProperty);
|
||||
set => SetValue(ContentTextAlignProperty, value);
|
||||
}
|
||||
|
||||
internal HorizontalAlignment LabelTextAlign
|
||||
{
|
||||
get => GetValue(LabelTextAlignProperty);
|
||||
set => SetValue(LabelTextAlignProperty, value);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected internal int LabelIndex = 0;
|
||||
protected internal int SplitIndex = 1;
|
||||
protected internal int ContentIndex = 2;
|
||||
|
||||
private Grid? _gridContainer;
|
||||
private DockPanel? _splitPanel;
|
||||
private TextBlock? _labelBlock;
|
||||
private ContentPresenter? _itemsContentPresenter;
|
||||
private Border? _splitHeadPart;
|
||||
private PathIcon? _dotPart;
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
|
||||
if (change.Property == ModeProperty || change.Property == CountProperty || change.Property == IndexProperty)
|
||||
{
|
||||
UpdateAll();
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
{
|
||||
base.OnApplyTemplate(e);
|
||||
|
||||
HandleTemplateApplied(e.NameScope);
|
||||
}
|
||||
|
||||
private void HandleTemplateApplied(INameScope scope)
|
||||
{
|
||||
_gridContainer = scope.Find<Grid>(TimelineItemTheme.GridPart);
|
||||
_splitPanel = scope.Find<DockPanel>(TimelineItemTheme.SplitPanelPart);
|
||||
_labelBlock = scope.Find<TextBlock>(TimelineItemTheme.LabelPart);
|
||||
_itemsContentPresenter = scope.Find<ContentPresenter>(TimelineItemTheme.ItemsContentPresenterPart);
|
||||
_splitHeadPart = scope.Find<Border>(TimelineItemTheme.SplitHeadPart);
|
||||
_dotPart = scope.Find<PathIcon>(TimelineItemTheme.DotPart);
|
||||
|
||||
UpdateAll();
|
||||
}
|
||||
|
||||
protected void UpdateAll()
|
||||
{
|
||||
CalculateIndex();
|
||||
SetupShowInfo();
|
||||
UpdatePseudoClasses();
|
||||
}
|
||||
|
||||
protected void UpdatePseudoClasses()
|
||||
{
|
||||
PseudoClasses.Set(PendingNodePC, IsPending);
|
||||
PseudoClasses.Set(ContentLeftPC, ContentIndex == 0);
|
||||
PseudoClasses.Set(LabelLeftPC, LabelIndex == 0);
|
||||
}
|
||||
|
||||
private void CalculateIndex()
|
||||
{
|
||||
if (VisualRoot is null || _gridContainer is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (Parent is Timeline timeline)
|
||||
{
|
||||
Index = timeline.Items.IndexOf(this);
|
||||
IsLast = Index == timeline.Items.Count - 1;
|
||||
HasLabel = false;
|
||||
|
||||
foreach (var child in timeline.Items)
|
||||
{
|
||||
if (child is TimelineItem item)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(item.Label))
|
||||
{
|
||||
HasLabel = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SplitIndex = 1;
|
||||
LabelTextAlign = HorizontalAlignment.Right;
|
||||
ContentTextAlign = HorizontalAlignment.Left;
|
||||
if (Mode == TimeLineMode.Right || (Mode == TimeLineMode.Alternate && Index % 2 == 1))
|
||||
{
|
||||
LabelIndex = 2;
|
||||
ContentIndex = 0;
|
||||
LabelTextAlign = HorizontalAlignment.Left;
|
||||
ContentTextAlign = HorizontalAlignment.Right;
|
||||
}
|
||||
else
|
||||
{
|
||||
LabelIndex = 0;
|
||||
ContentIndex = 2;
|
||||
LabelTextAlign = HorizontalAlignment.Right;
|
||||
ContentTextAlign = HorizontalAlignment.Left;
|
||||
}
|
||||
|
||||
_gridContainer.ColumnDefinitions[0].Width = GridLength.Star;
|
||||
_gridContainer.ColumnDefinitions[2].Width = GridLength.Star;
|
||||
|
||||
if (!HasLabel)
|
||||
{
|
||||
if (Mode == TimeLineMode.Left)
|
||||
{
|
||||
LabelIndex = 0;
|
||||
ContentIndex = 2;
|
||||
ContentTextAlign = HorizontalAlignment.Left;
|
||||
}
|
||||
|
||||
if (Mode == TimeLineMode.Right)
|
||||
{
|
||||
LabelIndex = 2;
|
||||
ContentIndex = 0;
|
||||
ContentTextAlign = HorizontalAlignment.Right;
|
||||
}
|
||||
|
||||
_gridContainer.ColumnDefinitions[LabelIndex].Width = new GridLength(0);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupShowInfo()
|
||||
{
|
||||
if (_splitPanel is null || _itemsContentPresenter is null || _labelBlock is null || _gridContainer is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Grid.SetColumn(_labelBlock, LabelIndex);
|
||||
Grid.SetColumn(_itemsContentPresenter, ContentIndex);
|
||||
Grid.SetColumn(_splitPanel, SplitIndex);
|
||||
|
||||
var dot = _splitPanel.Children[0];
|
||||
var border = _splitPanel.Children[1] as Border;
|
||||
var rect = border?.Child as Rectangle;
|
||||
var isPendingItem = false;
|
||||
MinHeight = 0;
|
||||
|
||||
if (Parent is Timeline timeline && !String.IsNullOrEmpty(timeline.Pending) && rect is not null &&
|
||||
border is not null)
|
||||
{
|
||||
rect.StrokeDashArray = null;
|
||||
|
||||
isPendingItem = Reverse && Index == 0 || !Reverse && timeline.ItemCount - 2 == Index;
|
||||
if (isPendingItem)
|
||||
{
|
||||
rect.StrokeDashArray = new AvaloniaList<double> { 0, 2 };
|
||||
}
|
||||
}
|
||||
|
||||
if (rect is not null)
|
||||
{
|
||||
rect.IsVisible = !IsLast;
|
||||
}
|
||||
|
||||
if (IsLast || isPendingItem)
|
||||
{
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(this, Layoutable.MinHeightProperty,
|
||||
TimelineTokenResourceKey.LastItemContentMinHeight);
|
||||
}
|
||||
|
||||
if (Color.StartsWith("#"))
|
||||
{
|
||||
try
|
||||
{
|
||||
var color = Avalonia.Media.Color.Parse(Color);
|
||||
var brush = new SolidColorBrush(color);
|
||||
if (_dotPart is not null && _dotPart.NormalFilledBrush is null)
|
||||
{
|
||||
_dotPart.NormalFilledBrush = brush;
|
||||
}
|
||||
|
||||
if (_splitHeadPart is not null)
|
||||
{
|
||||
_splitHeadPart.BorderBrush = brush;
|
||||
}
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
if (_dotPart is not null && _dotPart.NormalFilledBrush is null)
|
||||
{
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(_dotPart, PathIcon.NormalFilledBrushProperty,
|
||||
GlobalTokenResourceKey.ColorPrimary);
|
||||
}
|
||||
|
||||
if (_splitHeadPart is not null)
|
||||
{
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(_splitHeadPart, Border.BorderBrushProperty,
|
||||
GlobalTokenResourceKey.ColorPrimary);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var tokenText = GlobalTokenResourceKey.ColorSuccess;
|
||||
switch (Color)
|
||||
{
|
||||
case "blue":
|
||||
tokenText = GlobalTokenResourceKey.ColorPrimary;
|
||||
break;
|
||||
case "green":
|
||||
tokenText = GlobalTokenResourceKey.ColorSuccess;
|
||||
break;
|
||||
case "red":
|
||||
tokenText = GlobalTokenResourceKey.ColorError;
|
||||
break;
|
||||
case "gray":
|
||||
tokenText = GlobalTokenResourceKey.ColorTextDisabled;
|
||||
break;
|
||||
}
|
||||
if (_dotPart is not null && _dotPart.NormalFilledBrush is null)
|
||||
{
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(_dotPart, PathIcon.NormalFilledBrushProperty,
|
||||
tokenText);
|
||||
}
|
||||
|
||||
if (_splitHeadPart is not null)
|
||||
{
|
||||
TokenResourceBinder.CreateGlobalTokenBinding(_splitHeadPart, Border.BorderBrushProperty,
|
||||
tokenText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
195
src/AtomUI.Controls/Timeline/TimelineItemTheme.cs
Normal file
195
src/AtomUI.Controls/Timeline/TimelineItemTheme.cs
Normal file
@ -0,0 +1,195 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Shapes;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Styling;
|
||||
using HorizontalAlignment = Avalonia.Layout.HorizontalAlignment;
|
||||
using VerticalAlignment = Avalonia.Layout.VerticalAlignment;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
internal class TimelineItemTheme : BaseControlTheme
|
||||
{
|
||||
public const string GridPart = "PART_Grid";
|
||||
public const string ItemsContentPresenterPart = "PART_ItemsContentPresenter";
|
||||
public const string SplitPanelPart = "PART_PanelHead";
|
||||
public const string SplitHeadPart = "PART_SplitHead";
|
||||
public const string SplitLineBorderPart = "PART_SplitBorderLine";
|
||||
public const string SplitLinePart = "PART_SplitLine";
|
||||
public const string LabelPart = "PART_Label";
|
||||
public const string DotPart = "PART_Dot";
|
||||
|
||||
public TimelineItemTheme() : base(typeof(TimelineItem))
|
||||
{
|
||||
}
|
||||
|
||||
protected override IControlTemplate BuildControlTemplate()
|
||||
{
|
||||
return new FuncControlTemplate<TimelineItem>((timelineItem, scope) =>
|
||||
{
|
||||
var grid = new Grid()
|
||||
{
|
||||
Name = GridPart,
|
||||
ColumnDefinitions = new ColumnDefinitions()
|
||||
{
|
||||
new ColumnDefinition(GridLength.Star),
|
||||
new ColumnDefinition(new GridLength(10)),
|
||||
new ColumnDefinition(GridLength.Star)
|
||||
},
|
||||
RowDefinitions =
|
||||
{
|
||||
new RowDefinition(GridLength.Star),
|
||||
new RowDefinition(GridLength.Star),
|
||||
},
|
||||
};
|
||||
grid.RegisterInNameScope(scope);
|
||||
|
||||
var labelBlock = new TextBlock()
|
||||
{
|
||||
Name = LabelPart,
|
||||
VerticalAlignment = VerticalAlignment.Top,
|
||||
};
|
||||
labelBlock.RegisterInNameScope(scope);
|
||||
|
||||
CreateTemplateParentBinding(labelBlock, TextBlock.TextProperty, TimelineItem.LabelProperty);
|
||||
CreateTemplateParentBinding(labelBlock, Visual.IsVisibleProperty, TimelineItem.HasLabelProperty);
|
||||
CreateTemplateParentBinding(labelBlock, Layoutable.HorizontalAlignmentProperty,
|
||||
TimelineItem.LabelTextAlignProperty);
|
||||
|
||||
grid.Children.Add(labelBlock);
|
||||
|
||||
var splitPanel = new DockPanel()
|
||||
{
|
||||
Name = SplitPanelPart,
|
||||
Width = 10,
|
||||
};
|
||||
splitPanel.RegisterInNameScope(scope);
|
||||
BuildDotIcon(splitPanel, timelineItem, scope);
|
||||
|
||||
var border = new Border
|
||||
{
|
||||
Name = SplitLineBorderPart,
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch
|
||||
};
|
||||
|
||||
var verticalDashedLine = new Rectangle
|
||||
{
|
||||
Name = SplitLinePart,
|
||||
StrokeLineCap = PenLineCap.Round,
|
||||
Fill = Brushes.Transparent,
|
||||
VerticalAlignment = VerticalAlignment.Stretch,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch
|
||||
};
|
||||
|
||||
verticalDashedLine.RegisterInNameScope(scope);
|
||||
|
||||
border.Child = verticalDashedLine;
|
||||
|
||||
splitPanel.Children.Add(border);
|
||||
grid.Children.Add(splitPanel);
|
||||
|
||||
var contentPresenter = new ContentPresenter()
|
||||
{
|
||||
Name = ItemsContentPresenterPart,
|
||||
};
|
||||
contentPresenter.RegisterInNameScope(scope);
|
||||
|
||||
CreateTemplateParentBinding(contentPresenter, ContentPresenter.ContentProperty,
|
||||
ContentControl.ContentProperty);
|
||||
CreateTemplateParentBinding(contentPresenter, Layoutable.HorizontalAlignmentProperty,
|
||||
TimelineItem.ContentTextAlignProperty);
|
||||
|
||||
grid.Children.Add(contentPresenter);
|
||||
|
||||
return grid;
|
||||
});
|
||||
}
|
||||
|
||||
private void BuildDotIcon(DockPanel panel, TimelineItem timelineItem, INameScope scope)
|
||||
{
|
||||
if (timelineItem.DotIcon is not null)
|
||||
{
|
||||
timelineItem.DotIcon.Width = 10;
|
||||
timelineItem.DotIcon.Height = 10;
|
||||
timelineItem.DotIcon.Name = DotPart;
|
||||
timelineItem.DotIcon.RegisterInNameScope(scope);
|
||||
DockPanel.SetDock(timelineItem.DotIcon, Dock.Top);
|
||||
panel.Children.Add(timelineItem.DotIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
var splitHead = new Border()
|
||||
{
|
||||
Width = 10,
|
||||
Height = 10,
|
||||
CornerRadius = new CornerRadius(5),
|
||||
BorderThickness = new Thickness(3),
|
||||
Name = SplitHeadPart,
|
||||
};
|
||||
splitHead.RegisterInNameScope(scope);
|
||||
DockPanel.SetDock(splitHead, Dock.Top);
|
||||
panel.Children.Add(splitHead);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
// 分割线样式
|
||||
var splitLineborderStyle = new Style(selector => selector.Nesting().Template().Name(SplitLineBorderPart));
|
||||
splitLineborderStyle.Add(Layoutable.WidthProperty, TimelineTokenResourceKey.TailWidth);
|
||||
Add(splitLineborderStyle);
|
||||
|
||||
var lineStyle = new Style(selector => selector.Nesting().Template().Child().OfType<Rectangle>());
|
||||
lineStyle.Add(Shape.StrokeProperty, TimelineTokenResourceKey.TailColor);
|
||||
lineStyle.Add(Layoutable.WidthProperty, TimelineTokenResourceKey.TailWidth);
|
||||
lineStyle.Add(Shape.StrokeThicknessProperty, TimelineTokenResourceKey.TailWidth);
|
||||
|
||||
Add(lineStyle);
|
||||
|
||||
// 内容样式
|
||||
var contentPresenterStyle =
|
||||
new Style(selector => selector.Nesting().Template().Name(ItemsContentPresenterPart));
|
||||
contentPresenterStyle.Add(ContentPresenter.FontSizeProperty, TimelineTokenResourceKey.FontSize);
|
||||
contentPresenterStyle.Add(ContentPresenter.PaddingProperty, TimelineTokenResourceKey.ItemPaddingBottom);
|
||||
|
||||
var contentPresenterLeftStyle =
|
||||
new Style(selector => selector.Nesting().Template().Name(ItemsContentPresenterPart));
|
||||
contentPresenterLeftStyle.Add(Layoutable.MarginProperty, TimelineTokenResourceKey.RightMargin);
|
||||
|
||||
var contentPresenterRightStyle =
|
||||
new Style(selector => selector.Nesting().Template().Name(ItemsContentPresenterPart));
|
||||
contentPresenterRightStyle.Add(Layoutable.MarginProperty, TimelineTokenResourceKey.LeftMargin);
|
||||
|
||||
var contentLeftStyle = new Style(selector => selector.Nesting().Class(TimelineItem.ContentLeftPC));
|
||||
var contentRightStyle = new Style(selector => selector.Nesting().Not(x => x.Class(TimelineItem.ContentLeftPC)));
|
||||
|
||||
contentLeftStyle.Add(contentPresenterLeftStyle);
|
||||
contentRightStyle.Add(contentPresenterRightStyle);
|
||||
|
||||
Add(contentPresenterStyle);
|
||||
Add(contentLeftStyle);
|
||||
Add(contentRightStyle);
|
||||
|
||||
// 标签样式
|
||||
var labelStyle = new Style(selector => selector.Nesting().Template().Name(LabelPart));
|
||||
labelStyle.Add(TextBlock.FontSizeProperty, TimelineTokenResourceKey.FontSize);
|
||||
|
||||
var labelLeftStyle = new Style(selector =>
|
||||
selector.Nesting().Class(TimelineItem.LabelLeftPC).Template().Name(LabelPart));
|
||||
var labelRightStyle = new Style(selector =>
|
||||
selector.Nesting().Not(x => x.Class(TimelineItem.LabelLeftPC)).Template().Name(LabelPart));
|
||||
labelLeftStyle.Add(TextBlock.PaddingProperty, TimelineTokenResourceKey.RightMargin);
|
||||
labelRightStyle.Add(TextBlock.PaddingProperty, TimelineTokenResourceKey.LeftMargin);
|
||||
|
||||
Add(labelStyle);
|
||||
Add(labelLeftStyle);
|
||||
Add(labelRightStyle);
|
||||
}
|
||||
}
|
80
src/AtomUI.Controls/Timeline/TimelineTheme.cs
Normal file
80
src/AtomUI.Controls/Timeline/TimelineTheme.cs
Normal file
@ -0,0 +1,80 @@
|
||||
using AtomUI.Theme;
|
||||
using AtomUI.Theme.Styling;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Styling;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlThemeProvider]
|
||||
internal class TimelineTheme : BaseControlTheme
|
||||
{
|
||||
public const string FrameDecoratorPart = "PART_FrameDecorator";
|
||||
public const string ScrollViewerPart = "PART_ScrollViewer";
|
||||
public const string ItemsPresenterPart = "PART_ItemsPresenter";
|
||||
|
||||
public TimelineTheme() : base(typeof(Timeline)) { }
|
||||
|
||||
protected override IControlTemplate BuildControlTemplate()
|
||||
{
|
||||
return new FuncControlTemplate<Timeline>((timeline, scope) =>
|
||||
{
|
||||
var frameBorder = new Border()
|
||||
{
|
||||
Name = FrameDecoratorPart
|
||||
};
|
||||
|
||||
var itemsPresenter = BuildItemsPresenter(timeline, scope);
|
||||
var scrollViewer = BuildScrollViewer(timeline, scope);
|
||||
|
||||
scrollViewer.Content = itemsPresenter;
|
||||
frameBorder.Child = scrollViewer;
|
||||
|
||||
return frameBorder;
|
||||
});
|
||||
}
|
||||
|
||||
private ScrollViewer BuildScrollViewer(Timeline timeline, INameScope scope)
|
||||
{
|
||||
var scrollViewer = new ScrollViewer
|
||||
{
|
||||
Name = ScrollViewerPart
|
||||
};
|
||||
|
||||
return scrollViewer;
|
||||
}
|
||||
|
||||
private ItemsPresenter BuildItemsPresenter(Timeline timeline, INameScope scope)
|
||||
{
|
||||
var itemsPresenter = new ItemsPresenter
|
||||
{
|
||||
Name = ItemsPresenterPart,
|
||||
};
|
||||
itemsPresenter.RegisterInNameScope(scope);
|
||||
return itemsPresenter;
|
||||
}
|
||||
|
||||
protected override void BuildStyles()
|
||||
{
|
||||
BuildFixedStyle();
|
||||
BuildCommonStyle();
|
||||
}
|
||||
private void BuildFixedStyle()
|
||||
{
|
||||
this.Add(ScrollViewer.HorizontalScrollBarVisibilityProperty, ScrollBarVisibility.Disabled);
|
||||
this.Add(ScrollViewer.VerticalScrollBarVisibilityProperty, ScrollBarVisibility.Auto);
|
||||
this.Add(ScrollViewer.IsScrollChainingEnabledProperty, true);
|
||||
}
|
||||
|
||||
private void BuildCommonStyle()
|
||||
{
|
||||
var commonStyle = new Style(selector => selector.Nesting());
|
||||
commonStyle.Add(Border.BorderBrushProperty, GlobalTokenResourceKey.ColorBorder);
|
||||
var frameStyle = new Style(selector => selector.Nesting().Template().Name(FrameDecoratorPart));
|
||||
frameStyle.Add(Border.BackgroundProperty, GlobalTokenResourceKey.ColorBgContainer);
|
||||
commonStyle.Add(frameStyle);
|
||||
Add(commonStyle);
|
||||
}
|
||||
}
|
105
src/AtomUI.Controls/Timeline/TimelineToken.cs
Normal file
105
src/AtomUI.Controls/Timeline/TimelineToken.cs
Normal file
@ -0,0 +1,105 @@
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using Avalonia;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
[ControlDesignToken]
|
||||
internal class TimelineToken : AbstractControlDesignToken
|
||||
{
|
||||
public const string ID = "Timeline";
|
||||
|
||||
public TimelineToken()
|
||||
: this(ID) { }
|
||||
|
||||
protected TimelineToken(string id)
|
||||
: base(id) { }
|
||||
|
||||
/// <summary>
|
||||
/// Timeline 轨迹颜色
|
||||
/// </summary>
|
||||
public Color TailColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 轨迹宽度
|
||||
/// </summary>
|
||||
public double TailWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 节点边框宽度
|
||||
/// </summary>
|
||||
public double DotBorderWidth { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 列表项文字选中颜色
|
||||
/// </summary>
|
||||
public Color ItemSelectedColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 节点背景色
|
||||
/// </summary>
|
||||
public Color DotBg { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 列表项背景色
|
||||
/// </summary>
|
||||
public Color ItemBgColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 时间项下间距
|
||||
/// </summary>
|
||||
public Thickness ItemPaddingBottom { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// right margin
|
||||
/// </summary>
|
||||
public Thickness RightMargin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// left margin
|
||||
/// </summary>
|
||||
public Thickness LeftMargin { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最后一个Item的Content最小高度
|
||||
/// </summary>
|
||||
public double LastItemContentMinHeight { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 字体大小
|
||||
/// </summary>
|
||||
public double FontSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// item head size
|
||||
/// </summary>
|
||||
public double ItemHeadSize { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// custom head size
|
||||
/// </summary>
|
||||
public double CustomHeadSize { get; set; }
|
||||
|
||||
internal override void CalculateFromAlias()
|
||||
{
|
||||
base.CalculateFromAlias();
|
||||
|
||||
|
||||
TailColor = _globalToken.ColorSplit;
|
||||
TailWidth = _globalToken.LineWidthBold;
|
||||
DotBorderWidth = _globalToken.Wireframe
|
||||
? _globalToken.LineWidthBold
|
||||
: _globalToken.LineWidth * 3;
|
||||
DotBg = _globalToken.ColorBgContainer;
|
||||
ItemPaddingBottom = new Thickness(0, 0, 0, _globalToken.Padding * 1.25);
|
||||
|
||||
LeftMargin = new Thickness(_globalToken.Margin, 0, 0, 0);
|
||||
RightMargin = new Thickness(0, 0, _globalToken.MarginSM, 0);
|
||||
|
||||
LastItemContentMinHeight = _globalToken.ControlHeightLG * 1.2;
|
||||
FontSize = _globalToken.FontSize;
|
||||
ItemHeadSize = 10;
|
||||
CustomHeadSize = _globalToken.FontSize;
|
||||
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
namespace AtomUI.Theme
|
||||
{
|
||||
internal class LanguageProviderRegister
|
||||
{
|
||||
internal static void Register()
|
||||
{
|
||||
}
|
||||
}
|
||||
namespace AtomUI.Theme
|
||||
{
|
||||
internal class LanguageProviderRegister
|
||||
{
|
||||
internal static void Register()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
using AtomUI.Theme.TokenSystem;
|
||||
|
||||
namespace AtomUI.Theme.Styling
|
||||
{
|
||||
@ -223,4 +223,4 @@ namespace AtomUI.Theme.Styling
|
||||
public static readonly TokenResourceKey MotionDurationSlow = new TokenResourceKey("MotionDurationSlow", "AtomUI.Token");
|
||||
public static readonly TokenResourceKey MotionDurationVerySlow = new TokenResourceKey("MotionDurationVerySlow", "AtomUI.Token");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user