feat: add item styles, add color converter.
This commit is contained in:
@@ -16,9 +16,23 @@
|
|||||||
</UserControl.Resources>
|
</UserControl.Resources>
|
||||||
<StackPanel>
|
<StackPanel>
|
||||||
<u:Timeline>
|
<u:Timeline>
|
||||||
<u:TimelineItem Content="Start" Time="2022-01-01" />
|
<u:TimelineItem
|
||||||
<u:TimelineItem Content="In between" Time="2022-01-02" />
|
Content="Start"
|
||||||
<u:TimelineItem Content="Finished" Time="2022-01-03" />
|
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>
|
||||||
<u:Timeline HorizontalAlignment="Left" ItemsSource="{Binding Items}">
|
<u:Timeline HorizontalAlignment="Left" ItemsSource="{Binding Items}">
|
||||||
<u:Timeline.ItemTemplate>
|
<u:Timeline.ItemTemplate>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
<ResourceDictionary
|
<ResourceDictionary
|
||||||
xmlns="https://github.com/avaloniaui"
|
xmlns="https://github.com/avaloniaui"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
|
xmlns:converters="clr-namespace:Ursa.Themes.Semi.Converters"
|
||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<Design.PreviewWith>
|
<Design.PreviewWith>
|
||||||
<StackPanel Width="100" Spacing="20">
|
<StackPanel Width="100" Spacing="20">
|
||||||
@@ -22,48 +23,64 @@
|
|||||||
</Setter>
|
</Setter>
|
||||||
</ControlTheme>
|
</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">
|
<ControlTheme x:Key="{x:Type u:TimelineItem}" TargetType="u:TimelineItem">
|
||||||
<Setter Property="u:TimelineItem.Template">
|
<Setter Property="u:TimelineItem.Template">
|
||||||
<ControlTemplate TargetType="u:TimelineItem">
|
<ControlTemplate TargetType="u:TimelineItem">
|
||||||
<Grid ColumnDefinitions="Auto, *" RowDefinitions="*, Auto, *">
|
<Grid ColumnDefinitions="Auto, *" RowDefinitions="*, Auto, *">
|
||||||
|
|
||||||
<Rectangle
|
|
||||||
Grid.Row="2"
|
|
||||||
Grid.Column="0"
|
|
||||||
Width="1"
|
|
||||||
VerticalAlignment="Stretch"
|
|
||||||
Classes="end"
|
|
||||||
Fill="LightGray" />
|
|
||||||
<Grid
|
<Grid
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.RowSpan="2"
|
Grid.RowSpan="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Width="16"
|
|
||||||
RowDefinitions="Auto, Auto, *">
|
RowDefinitions="Auto, Auto, *">
|
||||||
<Rectangle
|
<Rectangle
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Width="1"
|
Width="1"
|
||||||
Height="8"
|
Height="8"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top"
|
||||||
Classes="start"
|
Classes="start"
|
||||||
Fill="LightGray" />
|
Fill="LightGray" />
|
||||||
|
<Panel Grid.Row="1">
|
||||||
<Ellipse
|
<Ellipse
|
||||||
Grid.Row="1"
|
|
||||||
Width="8"
|
Width="8"
|
||||||
Height="8"
|
Height="8"
|
||||||
Margin="2"
|
Margin="2"
|
||||||
HorizontalAlignment="Center"
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Top"
|
VerticalAlignment="Top">
|
||||||
Fill="LightGray" />
|
<Ellipse.Fill>
|
||||||
|
<MultiBinding Converter="{StaticResource ForegroundConverter}">
|
||||||
|
<Binding Path="ItemType" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||||
|
<Binding Path="IconForeground" RelativeSource="{RelativeSource TemplatedParent}" />
|
||||||
|
</MultiBinding>
|
||||||
|
</Ellipse.Fill>
|
||||||
|
</Ellipse>
|
||||||
|
</Panel>
|
||||||
<Rectangle
|
<Rectangle
|
||||||
Grid.Row="2"
|
Grid.Row="2"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
Width="1"
|
Width="1"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
VerticalAlignment="Stretch"
|
VerticalAlignment="Stretch"
|
||||||
Classes="end"
|
Classes="end"
|
||||||
Fill="LightGray" />
|
Fill="LightGray" />
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Rectangle
|
||||||
|
Grid.Row="2"
|
||||||
|
Grid.Column="0"
|
||||||
|
Width="1"
|
||||||
|
HorizontalAlignment="Center"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Classes="end"
|
||||||
|
Fill="LightGray" />
|
||||||
<ContentPresenter
|
<ContentPresenter
|
||||||
Grid.Row="0"
|
Grid.Row="0"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
@@ -81,6 +98,7 @@
|
|||||||
Name="content"
|
Name="content"
|
||||||
Grid.Row="1"
|
Grid.Row="1"
|
||||||
Grid.Column="1"
|
Grid.Column="1"
|
||||||
|
Margin="0,0,0,16"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
Content="{TemplateBinding Content}"
|
Content="{TemplateBinding Content}"
|
||||||
|
|||||||
@@ -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="Banner.axaml" />
|
||||||
<MergeResourceInclude Source="Divider.axaml" />
|
<MergeResourceInclude Source="Divider.axaml" />
|
||||||
<MergeResourceInclude Source="IPv4Box.axaml" />
|
<MergeResourceInclude Source="IPv4Box.axaml" />
|
||||||
|
<MergeResourceInclude Source="Timeline.axaml" />
|
||||||
</ResourceDictionary.MergedDictionaries>
|
</ResourceDictionary.MergedDictionaries>
|
||||||
</ResourceDictionary>
|
</ResourceDictionary>
|
||||||
|
|||||||
@@ -8,11 +8,25 @@ using Avalonia.Media;
|
|||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
[PseudoClasses(PC_First, PC_Last)]
|
[PseudoClasses(PC_First, PC_Last, PC_Default, PC_Ongoing, PC_Success, PC_Warning, PC_Error)]
|
||||||
public class TimelineItem: ContentControl
|
public class TimelineItem: ContentControl
|
||||||
{
|
{
|
||||||
public const string PC_First = ":first";
|
private const string PC_First = ":first";
|
||||||
public const string PC_Last = ":last";
|
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 =
|
public static readonly StyledProperty<IBrush> IconForegroundProperty =
|
||||||
AvaloniaProperty.Register<TimelineItem, IBrush>(nameof(IconForeground));
|
AvaloniaProperty.Register<TimelineItem, IBrush>(nameof(IconForeground));
|
||||||
@@ -49,9 +63,32 @@ public class TimelineItem: ContentControl
|
|||||||
set => SetValue(DescriptionTemplateProperty, value);
|
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)
|
internal void SetIndex(bool isFirst, bool isLast)
|
||||||
{
|
{
|
||||||
PseudoClasses.Set(PC_First, isFirst);
|
PseudoClasses.Set(PC_First, isFirst);
|
||||||
PseudoClasses.Set(PC_Last, isLast);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2,7 +2,6 @@ namespace Ursa.Controls;
|
|||||||
|
|
||||||
public enum TimelineItemType
|
public enum TimelineItemType
|
||||||
{
|
{
|
||||||
None,
|
|
||||||
Default,
|
Default,
|
||||||
Ongoing,
|
Ongoing,
|
||||||
Success,
|
Success,
|
||||||
|
|||||||
Reference in New Issue
Block a user