feat: add demo page, prepare collection changed behavior.
This commit is contained in:
51
src/Ursa.Themes.Semi/Controls/Timeline.axaml
Normal file
51
src/Ursa.Themes.Semi/Controls/Timeline.axaml
Normal file
@@ -0,0 +1,51 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:u="https://irihi.tech/ursa">
|
||||
<Design.PreviewWith>
|
||||
<StackPanel Width="100" Spacing="20">
|
||||
<u:Timeline>
|
||||
<u:TimelineItem Content="Hello" Time="2022-01-01" />
|
||||
<u:TimelineItem Content="World" Time="2022-02-01" />
|
||||
<u:TimelineItem Content="!" Time="2022-03-01" />
|
||||
<u:TimelineItem />
|
||||
</u:Timeline>
|
||||
</StackPanel>
|
||||
</Design.PreviewWith>
|
||||
<!-- Add Resources Here -->
|
||||
<u:TimelineFormatConverter x:Key="FormatConverter" />
|
||||
<ControlTheme x:Key="{x:Type u:Timeline}" TargetType="u:Timeline">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate TargetType="u:Timeline">
|
||||
<Grid Grid.IsSharedSizeScope="True">
|
||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:TimelineItem}" TargetType="u:TimelineItem">
|
||||
<Setter Property="u:TimelineItem.Template">
|
||||
<ControlTemplate TargetType="u:TimelineItem">
|
||||
<StackPanel>
|
||||
<ContentPresenter>
|
||||
<ContentPresenter.Content>
|
||||
<MultiBinding Converter="{StaticResource FormatConverter}">
|
||||
<Binding Path="Time" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="TimeFormat" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</ContentPresenter.Content>
|
||||
</ContentPresenter>
|
||||
<ContentPresenter Name="content" Content="{TemplateBinding Content}" />
|
||||
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:first /template/ ContentPresenter#content">
|
||||
<Setter Property="ContentPresenter.Foreground" Value="Red" />
|
||||
</Style>
|
||||
<Style Selector="^:last /template/ ContentPresenter#content">
|
||||
<Setter Property="ContentPresenter.Foreground" Value="Green" />
|
||||
</Style>
|
||||
</ControlTheme>
|
||||
</ResourceDictionary>
|
||||
@@ -5,5 +5,6 @@
|
||||
<ResourceInclude Source="Banner.axaml" />
|
||||
<ResourceInclude Source="Divider.axaml" />
|
||||
<ResourceInclude Source="IPv4Box.axaml" />
|
||||
<ResourceInclude Source="Timeline.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
using System.Collections.Specialized;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices.ComTypes;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Generators;
|
||||
using Avalonia.Controls.Presenters;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
@@ -17,33 +22,33 @@ public class Timeline: ItemsControl
|
||||
set => SetValue(ItemDescriptionTemplateProperty, value);
|
||||
}
|
||||
|
||||
protected override bool IsItemItsOwnContainerOverride(Control item)
|
||||
public Timeline()
|
||||
{
|
||||
return item is TimelineItem;
|
||||
ItemsView.CollectionChanged+=ItemsViewOnCollectionChanged;
|
||||
}
|
||||
|
||||
protected override Control CreateContainerForItemOverride()
|
||||
private void ItemsViewOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
return new TimelineItem();
|
||||
RefreshTimelineItems();
|
||||
}
|
||||
|
||||
protected override void PrepareContainerForItemOverride(Control container, object? item, int index)
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.PrepareContainerForItemOverride(container, item, index);
|
||||
if (container is TimelineItem c )
|
||||
base.OnPropertyChanged(change);
|
||||
RefreshTimelineItems();
|
||||
}
|
||||
|
||||
private void RefreshTimelineItems()
|
||||
{
|
||||
for (int i = 0; i < this.LogicalChildren.Count; i++)
|
||||
{
|
||||
if (item is ITimelineItemData data)
|
||||
if (this.LogicalChildren[i] is TimelineItem t)
|
||||
{
|
||||
c[TimelineItem.TimeProperty] = data;
|
||||
c[ContentControl.ContentProperty] = data.Content;
|
||||
c[TimelineItem.DescriptionProperty] = data.Description;
|
||||
if(ItemTemplate is {}) c[ContentControl.ContentTemplateProperty] = this.ItemTemplate;
|
||||
if(ItemDescriptionTemplate is {}) c[TimelineItem.DescriptionTemplateProperty] = this.ItemDescriptionTemplate;
|
||||
t.SetPosition(i == 0, i == this.LogicalChildren.Count - 1);
|
||||
}
|
||||
else
|
||||
else if (this.LogicalChildren[i] is ContentPresenter { Child: TimelineItem t2 })
|
||||
{
|
||||
c.Content = item;
|
||||
if (ItemTemplate is { }) c[ContentControl.ContentTemplateProperty] = this.ItemTemplate;
|
||||
t2.SetPosition(i == 0, i == this.LogicalChildren.Count - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
17
src/Ursa/Controls/Timeline/TimelineFormatConverter.cs
Normal file
17
src/Ursa/Controls/Timeline/TimelineFormatConverter.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Data.Converters;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public class TimelineFormatConverter: IMultiValueConverter
|
||||
{
|
||||
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (values.Count> 1 && values[0] is DateTime date && values[1] is string s)
|
||||
{
|
||||
return date.ToString(s, culture);
|
||||
}
|
||||
return AvaloniaProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
@@ -12,7 +13,7 @@ public class TimelineItem: ContentControl
|
||||
{
|
||||
public const string PC_First = ":first";
|
||||
public const string PC_Last = ":last";
|
||||
|
||||
|
||||
public static readonly StyledProperty<IBrush> IconForegroundProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, IBrush>(nameof(IconForeground));
|
||||
|
||||
@@ -40,7 +41,7 @@ public class TimelineItem: ContentControl
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string?> TimeFormatProperty = AvaloniaProperty.Register<TimelineItem, string?>(
|
||||
nameof(TimeFormat));
|
||||
nameof(TimeFormat), defaultValue:CultureInfo.CurrentUICulture.DateTimeFormat.SortableDateTimePattern);
|
||||
|
||||
public string? TimeFormat
|
||||
{
|
||||
@@ -56,4 +57,10 @@ public class TimelineItem: ContentControl
|
||||
get => GetValue(DescriptionTemplateProperty);
|
||||
set => SetValue(DescriptionTemplateProperty, value);
|
||||
}
|
||||
|
||||
internal void SetPosition(bool isFirst, bool isLast)
|
||||
{
|
||||
PseudoClasses.Set(PC_First, isFirst);
|
||||
PseudoClasses.Set(PC_Last, isLast);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public interface ITimelineItemData
|
||||
{
|
||||
public DateTime Time { get; set; }
|
||||
public object Content { get; set; }
|
||||
public object Description { get; set; }
|
||||
public TimelineItemType ItemType { get; set; }
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Describe how TimelineItem components should be placed around the line.
|
||||
/// </summary>
|
||||
public enum TimelinePlacement
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Center,
|
||||
Alternate,
|
||||
}
|
||||
Reference in New Issue
Block a user