58
demo/Ursa.Demo/Pages/TimelineDemo.axaml
Normal file
58
demo/Ursa.Demo/Pages/TimelineDemo.axaml
Normal file
@@ -0,0 +1,58 @@
|
||||
<UserControl
|
||||
x:Class="Ursa.Demo.Pages.TimelineDemo"
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:u="https://irihi.tech/ursa"
|
||||
xmlns:viewModels="clr-namespace:Ursa.Demo.ViewModels"
|
||||
d:DesignHeight="450"
|
||||
d:DesignWidth="800"
|
||||
x:CompileBindings="False"
|
||||
x:DataType="viewModels:TimelineDemoViewModel"
|
||||
mc:Ignorable="d">
|
||||
<UserControl.Resources>
|
||||
<u:TimelineFormatConverter x:Key="FormatConverter" />
|
||||
</UserControl.Resources>
|
||||
<StackPanel>
|
||||
<u:Timeline>
|
||||
<u:TimelineItem
|
||||
Content="Start"
|
||||
ItemType="Warning"
|
||||
Time="2022-01-01" />
|
||||
<u:TimelineItem
|
||||
Content="In between"
|
||||
ItemType="Ongoing"
|
||||
Time="2022-01-02" />
|
||||
<u:TimelineItem
|
||||
Content="Finished"
|
||||
ItemType="Error"
|
||||
Time="2022-01-03" />
|
||||
<u:TimelineItem
|
||||
Content="Finished"
|
||||
IconForeground="Yellow"
|
||||
ItemType="Default"
|
||||
Time="2022-01-03" />
|
||||
</u:Timeline>
|
||||
<u:Timeline HorizontalAlignment="Left" ItemsSource="{Binding Items}">
|
||||
<u:Timeline.ItemTemplate>
|
||||
<DataTemplate x:DataType="viewModels:TimelineItemViewModel">
|
||||
<u:TimelineItem
|
||||
Content="{Binding Content}"
|
||||
ItemType="{Binding ItemType}"
|
||||
Time="{Binding Time}"
|
||||
TimeFormat="{Binding TimeFormat}">
|
||||
<u:TimelineItem.ContentTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock
|
||||
MaxWidth="100"
|
||||
Text="{Binding}"
|
||||
TextWrapping="Wrap" />
|
||||
</DataTemplate>
|
||||
</u:TimelineItem.ContentTemplate>
|
||||
</u:TimelineItem>
|
||||
</DataTemplate>
|
||||
</u:Timeline.ItemTemplate>
|
||||
</u:Timeline>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
15
demo/Ursa.Demo/Pages/TimelineDemo.axaml.cs
Normal file
15
demo/Ursa.Demo/Pages/TimelineDemo.axaml.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Ursa.Demo.ViewModels;
|
||||
|
||||
namespace Ursa.Demo.Pages;
|
||||
|
||||
public partial class TimelineDemo : UserControl
|
||||
{
|
||||
public TimelineDemo()
|
||||
{
|
||||
InitializeComponent();
|
||||
this.DataContext = new TimelineDemoViewModel();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<BuiltInComInteropSupport>true</BuiltInComInteropSupport>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<AvaloniaUseCompiledBindingsByDefault>false</AvaloniaUseCompiledBindingsByDefault>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
115
demo/Ursa.Demo/ViewModels/TimelineDemoViewModel.cs
Normal file
115
demo/Ursa.Demo/ViewModels/TimelineDemoViewModel.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using System;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Ursa.Controls;
|
||||
|
||||
namespace Ursa.Demo.ViewModels;
|
||||
|
||||
public class TimelineDemoViewModel: ObservableObject
|
||||
{
|
||||
public TimelineItemViewModel[] Items { get; } =
|
||||
{
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "yyyy-MM-dd HH:mm:ss",
|
||||
Description = "Item 1",
|
||||
Content = "First",
|
||||
ItemType = TimelineItemType.Success,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 2",
|
||||
Content = "Content 2",
|
||||
ItemType = TimelineItemType.Success,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 3",
|
||||
Content = "Content 3",
|
||||
ItemType = TimelineItemType.Ongoing,
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 4",
|
||||
Content = "Content 4"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 5",
|
||||
Content = "Content 5"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 6",
|
||||
Content = "Content 6"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 7",
|
||||
Content = "Content 71231"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 8",
|
||||
Content = "Content 8123123"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 9",
|
||||
Content = "Content 9123123"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 10",
|
||||
Content = "Content 1231231231231231231230"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 11",
|
||||
Content = "Content 11231231"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 12",
|
||||
Content = "Content 12123123123123"
|
||||
},
|
||||
new()
|
||||
{
|
||||
Time = DateTime.Now,
|
||||
TimeFormat = "HH:mm:ss",
|
||||
Description = "Item 13",
|
||||
Content = "Last"
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public class TimelineItemViewModel: ObservableObject
|
||||
{
|
||||
public DateTime Time { get; set; }
|
||||
public string? TimeFormat { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public string? Content { get; set; }
|
||||
public TimelineItemType ItemType { get; set; }
|
||||
}
|
||||
@@ -35,6 +35,9 @@
|
||||
<TabItem Header="IPv4Box">
|
||||
<pages:IPv4BoxDemo />
|
||||
</TabItem>
|
||||
<TabItem Header="Timeline">
|
||||
<pages:TimelineDemo />
|
||||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
|
||||
|
||||
116
src/Ursa.Themes.Semi/Controls/Timeline.axaml
Normal file
116
src/Ursa.Themes.Semi/Controls/Timeline.axaml
Normal file
@@ -0,0 +1,116 @@
|
||||
<ResourceDictionary
|
||||
xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||
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">
|
||||
<ItemsPresenter ItemsPanel="{TemplateBinding ItemsPanel}" />
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
</ControlTheme>
|
||||
|
||||
<converters:TimelineItemTypeToIconForegroundConverter
|
||||
x:Key="ForegroundConverter"
|
||||
DefaultBrush="{DynamicResource DefaultTimelineIconForeground}"
|
||||
ErrorBrush="{DynamicResource ErrorTimelineIconForeground}"
|
||||
OngoingBrush="{DynamicResource OngoingTimelineIconForeground}"
|
||||
SuccessBrush="{DynamicResource SuccessTimelineIconForeground}"
|
||||
WarningBrush="{DynamicResource WarningTimelineIconForeground}" />
|
||||
|
||||
<ControlTheme x:Key="{x:Type u:TimelineItem}" TargetType="u:TimelineItem">
|
||||
<Setter Property="u:TimelineItem.Template">
|
||||
<ControlTemplate TargetType="u:TimelineItem">
|
||||
<Grid ColumnDefinitions="Auto, *" RowDefinitions="*, Auto, *">
|
||||
<Grid
|
||||
Grid.Row="0"
|
||||
Grid.RowSpan="2"
|
||||
Grid.Column="0"
|
||||
RowDefinitions="Auto, Auto, *">
|
||||
<Rectangle
|
||||
Grid.Row="0"
|
||||
Grid.Column="0"
|
||||
Width="1"
|
||||
Height="8"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top"
|
||||
Classes="start"
|
||||
Fill="LightGray" />
|
||||
<Panel Grid.Row="1">
|
||||
<Ellipse
|
||||
Width="8"
|
||||
Height="8"
|
||||
Margin="2"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Top">
|
||||
<Ellipse.Fill>
|
||||
<MultiBinding Converter="{StaticResource ForegroundConverter}">
|
||||
<Binding Path="ItemType" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
<Binding Path="IconForeground" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||
</MultiBinding>
|
||||
</Ellipse.Fill>
|
||||
</Ellipse>
|
||||
</Panel>
|
||||
<Rectangle
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Width="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="end"
|
||||
Fill="LightGray" />
|
||||
</Grid>
|
||||
<Rectangle
|
||||
Grid.Row="2"
|
||||
Grid.Column="0"
|
||||
Width="1"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Stretch"
|
||||
Classes="end"
|
||||
Fill="LightGray" />
|
||||
<ContentPresenter
|
||||
Grid.Row="0"
|
||||
Grid.Column="1"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Bottom"
|
||||
Foreground="Gray">
|
||||
<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"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"
|
||||
Margin="0,0,0,16"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}" />
|
||||
</Grid>
|
||||
</ControlTemplate>
|
||||
</Setter>
|
||||
<Style Selector="^:first /template/ Rectangle.start">
|
||||
<Setter Property="Rectangle.Fill" Value="Transparent" />
|
||||
</Style>
|
||||
<Style Selector="^:last /template/ Rectangle.end">
|
||||
<Setter Property="Rectangle.Fill" Value="Transparent" />
|
||||
</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>
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Data.Converters;
|
||||
using Avalonia.Media;
|
||||
using Ursa.Controls;
|
||||
|
||||
namespace Ursa.Themes.Semi.Converters;
|
||||
|
||||
public class TimelineItemTypeToIconForegroundConverter: AvaloniaObject, IMultiValueConverter
|
||||
{
|
||||
public static readonly StyledProperty<IBrush> DefaultBrushProperty = AvaloniaProperty.Register<TimelineItemTypeToIconForegroundConverter, IBrush>(
|
||||
nameof(DefaultBrush));
|
||||
|
||||
public IBrush DefaultBrush
|
||||
{
|
||||
get => GetValue(DefaultBrushProperty);
|
||||
set => SetValue(DefaultBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> OngoingBrushProperty = AvaloniaProperty.Register<TimelineItemTypeToIconForegroundConverter, IBrush>(
|
||||
nameof(OngoingBrush));
|
||||
|
||||
public IBrush OngoingBrush
|
||||
{
|
||||
get => GetValue(OngoingBrushProperty);
|
||||
set => SetValue(OngoingBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> SuccessBrushProperty = AvaloniaProperty.Register<TimelineItemTypeToIconForegroundConverter, IBrush>(
|
||||
nameof(SuccessBrush));
|
||||
|
||||
public IBrush SuccessBrush
|
||||
{
|
||||
get => GetValue(SuccessBrushProperty);
|
||||
set => SetValue(SuccessBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> WarningBrushProperty = AvaloniaProperty.Register<TimelineItemTypeToIconForegroundConverter, IBrush>(
|
||||
nameof(WarningBrush));
|
||||
|
||||
public IBrush WarningBrush
|
||||
{
|
||||
get => GetValue(WarningBrushProperty);
|
||||
set => SetValue(WarningBrushProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IBrush> ErrorBrushProperty = AvaloniaProperty.Register<TimelineItemTypeToIconForegroundConverter, IBrush>(
|
||||
nameof(ErrorBrush));
|
||||
|
||||
public IBrush ErrorBrush
|
||||
{
|
||||
get => GetValue(ErrorBrushProperty);
|
||||
set => SetValue(ErrorBrushProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
|
||||
{
|
||||
if (values[0] is TimelineItemType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case TimelineItemType.Error:
|
||||
return ErrorBrush;
|
||||
case TimelineItemType.Warning:
|
||||
return WarningBrush;
|
||||
case TimelineItemType.Success:
|
||||
return SuccessBrush;
|
||||
case TimelineItemType.Ongoing:
|
||||
return OngoingBrush;
|
||||
case TimelineItemType.Default:
|
||||
if (values[1] is IBrush brush)
|
||||
{
|
||||
return brush;
|
||||
}
|
||||
return DefaultBrush;
|
||||
}
|
||||
}
|
||||
return AvaloniaProperty.UnsetValue;
|
||||
}
|
||||
}
|
||||
8
src/Ursa.Themes.Semi/Themes/Light/Timeline.axaml
Normal file
8
src/Ursa.Themes.Semi/Themes/Light/Timeline.axaml
Normal file
@@ -0,0 +1,8 @@
|
||||
<ResourceDictionary xmlns="https://github.com/avaloniaui" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
|
||||
<!-- Add Resources Here -->
|
||||
<SolidColorBrush x:Key="DefaultTimelineIconForeground" Opacity="0.13" Color="#FF2E3238" />
|
||||
<SolidColorBrush x:Key="OngoingTimelineIconForeground" Color="#FF0077FA" />
|
||||
<SolidColorBrush x:Key="SuccessTimelineIconForeground" Color="#FF3BB346" />
|
||||
<SolidColorBrush x:Key="WarningTimelineIconForeground" Color="#FFFC8800" />
|
||||
<SolidColorBrush x:Key="ErrorTimelineIconForeground" Color="#FFF93920" />
|
||||
</ResourceDictionary>
|
||||
@@ -5,5 +5,6 @@
|
||||
<MergeResourceInclude Source="Banner.axaml" />
|
||||
<MergeResourceInclude Source="Divider.axaml" />
|
||||
<MergeResourceInclude Source="IPv4Box.axaml" />
|
||||
<MergeResourceInclude Source="Timeline.axaml" />
|
||||
</ResourceDictionary.MergedDictionaries>
|
||||
</ResourceDictionary>
|
||||
|
||||
56
src/Ursa/Controls/Timeline/Timeline.cs
Normal file
56
src/Ursa/Controls/Timeline/Timeline.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
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;
|
||||
|
||||
public class Timeline: ItemsControl
|
||||
{
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate?> ItemDescriptionTemplateProperty = AvaloniaProperty.Register<Timeline, IDataTemplate?>(
|
||||
nameof(ItemDescriptionTemplate));
|
||||
|
||||
public IDataTemplate? ItemDescriptionTemplate
|
||||
{
|
||||
get => GetValue(ItemDescriptionTemplateProperty);
|
||||
set => SetValue(ItemDescriptionTemplateProperty, value);
|
||||
}
|
||||
|
||||
public Timeline()
|
||||
{
|
||||
ItemsView.CollectionChanged+=ItemsViewOnCollectionChanged;
|
||||
}
|
||||
|
||||
private void ItemsViewOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
RefreshTimelineItems();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
{
|
||||
base.OnPropertyChanged(change);
|
||||
RefreshTimelineItems();
|
||||
}
|
||||
|
||||
private void RefreshTimelineItems()
|
||||
{
|
||||
for (int i = 0; i < this.LogicalChildren.Count; i++)
|
||||
{
|
||||
if (this.LogicalChildren[i] is TimelineItem t)
|
||||
{
|
||||
t.SetIndex(i == 0, i == this.LogicalChildren.Count - 1);
|
||||
}
|
||||
else if (this.LogicalChildren[i] is ContentPresenter { Child: TimelineItem t2 })
|
||||
{
|
||||
t2.SetIndex(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;
|
||||
}
|
||||
}
|
||||
94
src/Ursa/Controls/Timeline/TimelineItem.cs
Normal file
94
src/Ursa/Controls/Timeline/TimelineItem.cs
Normal file
@@ -0,0 +1,94 @@
|
||||
using System.Globalization;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Media;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
[PseudoClasses(PC_First, PC_Last, PC_Default, PC_Ongoing, PC_Success, PC_Warning, PC_Error)]
|
||||
public class TimelineItem: ContentControl
|
||||
{
|
||||
private const string PC_First = ":first";
|
||||
private const string PC_Last = ":last";
|
||||
private const string PC_Default = ":default";
|
||||
private const string PC_Ongoing = ":ongoing";
|
||||
private const string PC_Success = ":success";
|
||||
private const string PC_Warning = ":warning";
|
||||
private const string PC_Error = ":error";
|
||||
|
||||
private static readonly IReadOnlyDictionary<TimelineItemType, string> _itemTypeMapping = new Dictionary<TimelineItemType, string>
|
||||
{
|
||||
{TimelineItemType.Default, PC_Default},
|
||||
{TimelineItemType.Ongoing, PC_Ongoing},
|
||||
{TimelineItemType.Success, PC_Success},
|
||||
{TimelineItemType.Warning, PC_Warning},
|
||||
{TimelineItemType.Error, PC_Error},
|
||||
};
|
||||
|
||||
public static readonly StyledProperty<IBrush> IconForegroundProperty =
|
||||
AvaloniaProperty.Register<TimelineItem, IBrush>(nameof(IconForeground));
|
||||
|
||||
public IBrush IconForeground
|
||||
{
|
||||
get => GetValue(IconForegroundProperty);
|
||||
set => SetValue(IconForegroundProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<DateTime> TimeProperty = AvaloniaProperty.Register<TimelineItem, DateTime>(
|
||||
nameof(Time));
|
||||
public DateTime Time
|
||||
{
|
||||
get => GetValue(TimeProperty);
|
||||
set => SetValue(TimeProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<string?> TimeFormatProperty = AvaloniaProperty.Register<TimelineItem, string?>(
|
||||
nameof(TimeFormat), defaultValue:CultureInfo.CurrentUICulture.DateTimeFormat.ShortDatePattern);
|
||||
|
||||
public string? TimeFormat
|
||||
{
|
||||
get => GetValue(TimeFormatProperty);
|
||||
set => SetValue(TimeFormatProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<IDataTemplate> DescriptionTemplateProperty = AvaloniaProperty.Register<TimelineItem, IDataTemplate>(
|
||||
nameof(DescriptionTemplate));
|
||||
|
||||
public IDataTemplate DescriptionTemplate
|
||||
{
|
||||
get => GetValue(DescriptionTemplateProperty);
|
||||
set => SetValue(DescriptionTemplateProperty, value);
|
||||
}
|
||||
|
||||
public static readonly StyledProperty<TimelineItemType> ItemTypeProperty = AvaloniaProperty.Register<TimelineItem, TimelineItemType>(
|
||||
nameof(ItemType));
|
||||
|
||||
public TimelineItemType ItemType
|
||||
{
|
||||
get => GetValue(ItemTypeProperty);
|
||||
set => SetValue(ItemTypeProperty, value);
|
||||
}
|
||||
|
||||
internal void SetIndex(bool isFirst, bool isLast)
|
||||
{
|
||||
PseudoClasses.Set(PC_First, isFirst);
|
||||
PseudoClasses.Set(PC_Last, isLast);
|
||||
}
|
||||
|
||||
static TimelineItem()
|
||||
{
|
||||
ItemTypeProperty.Changed.AddClassHandler<TimelineItem>((o, e) => { o.OnItemTypeChanged(e); });
|
||||
}
|
||||
|
||||
private void OnItemTypeChanged(AvaloniaPropertyChangedEventArgs args)
|
||||
{
|
||||
var oldValue = args.GetOldValue<TimelineItemType>();
|
||||
var newValue = args.GetNewValue<TimelineItemType>();
|
||||
PseudoClasses.Set(_itemTypeMapping[oldValue], false);
|
||||
PseudoClasses.Set(_itemTypeMapping[newValue], true);
|
||||
}
|
||||
|
||||
}
|
||||
10
src/Ursa/Controls/Timeline/TimelineItemType.cs
Normal file
10
src/Ursa/Controls/Timeline/TimelineItemType.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace Ursa.Controls;
|
||||
|
||||
public enum TimelineItemType
|
||||
{
|
||||
Default,
|
||||
Ongoing,
|
||||
Success,
|
||||
Warning,
|
||||
Error,
|
||||
}
|
||||
Reference in New Issue
Block a user