From 1d6d8feaecf835c88d7e3e315281906f07c96cd7 Mon Sep 17 00:00:00 2001 From: rabbitism Date: Tue, 2 Jan 2024 22:32:25 +0800 Subject: [PATCH] wip: layout. --- .../Ursa.Demo.Desktop.csproj | 1 + demo/Ursa.Demo/Pages/TimelineDemo.axaml | 64 +++++++++++---- src/Ursa.Themes.Semi/Controls/Timeline.axaml | 79 +++++++------------ src/Ursa/Controls/Timeline/Timeline.cs | 26 ++++++ .../Controls/Timeline/TimelineDisplayMode.cs | 9 +++ src/Ursa/Controls/Timeline/TimelineItem.cs | 47 ++++++++++- src/Ursa/Controls/Timeline/TimelinePanel.cs | 43 ++++++++++ 7 files changed, 197 insertions(+), 72 deletions(-) create mode 100644 src/Ursa/Controls/Timeline/TimelineDisplayMode.cs create mode 100644 src/Ursa/Controls/Timeline/TimelinePanel.cs diff --git a/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj b/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj index 3d3f388..64e44ce 100644 --- a/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj +++ b/demo/Ursa.Demo.Desktop/Ursa.Demo.Desktop.csproj @@ -6,6 +6,7 @@ net7.0 enable true + false diff --git a/demo/Ursa.Demo/Pages/TimelineDemo.axaml b/demo/Ursa.Demo/Pages/TimelineDemo.axaml index 39e428a..04d12b4 100644 --- a/demo/Ursa.Demo/Pages/TimelineDemo.axaml +++ b/demo/Ursa.Demo/Pages/TimelineDemo.axaml @@ -4,37 +4,67 @@ 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:selectors="clr-namespace:Ursa.Demo.TemplateSelectors" xmlns:u="https://irihi.tech/ursa" xmlns:viewModels="clr-namespace:Ursa.Demo.ViewModels" - xmlns:selectors="clr-namespace:Ursa.Demo.TemplateSelectors" d:DesignHeight="450" d:DesignWidth="800" - x:DataType="viewModels:TimelineDemoViewModel" x:CompileBindings="True" + x:DataType="viewModels:TimelineDemoViewModel" mc:Ignorable="d"> - - - - - + + + + + - - + - - - + + + diff --git a/src/Ursa.Themes.Semi/Controls/Timeline.axaml b/src/Ursa.Themes.Semi/Controls/Timeline.axaml index 7b192ce..dd7c25f 100644 --- a/src/Ursa.Themes.Semi/Controls/Timeline.axaml +++ b/src/Ursa.Themes.Semi/Controls/Timeline.axaml @@ -26,48 +26,35 @@ + WarningBrush="{DynamicResource WarningTimelineIconForeground}" /> - - + - - - - - - + Grid.Column="1" + Width="1" + Height="8" + HorizontalAlignment="Center" + VerticalAlignment="Top" + Classes="start" + Fill="{DynamicResource TimelineLineBrush}" /> + - + Foreground="Gray" /> - - - - - - diff --git a/src/Ursa/Controls/Timeline/Timeline.cs b/src/Ursa/Controls/Timeline/Timeline.cs index 1586733..3577226 100644 --- a/src/Ursa/Controls/Timeline/Timeline.cs +++ b/src/Ursa/Controls/Timeline/Timeline.cs @@ -6,12 +6,15 @@ using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Controls.Templates; using Avalonia.Data; +using Avalonia.Layout; using Avalonia.Metadata; namespace Ursa.Controls; public class Timeline: ItemsControl { + private static readonly FuncTemplate DefaultPanel = new((Func)(() => new TimelinePanel())); + public static readonly StyledProperty IconMemberBindingProperty = AvaloniaProperty.Register( nameof(IconMemberBinding)); @@ -66,6 +69,29 @@ public class Timeline: ItemsControl set => SetValue(DescriptionTemplateProperty, value); } + public static readonly StyledProperty ModeProperty = AvaloniaProperty.Register( + nameof(Mode)); + + public TimelineDisplayMode Mode + { + get => GetValue(ModeProperty); + set => SetValue(ModeProperty, value); + } + + static Timeline() + { + ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); + ModeProperty.Changed.AddClassHandler((t, e) => { t.OnDisplayModeChanged(e); }); + } + + private void OnDisplayModeChanged(AvaloniaPropertyChangedEventArgs e) + { + if (this.ItemsPanelRoot is TimelinePanel panel) + { + panel.Mode = e.NewValue.Value; + } + } + protected override bool NeedsContainerOverride(object? item, int index, out object? recycleKey) { recycleKey = null; diff --git a/src/Ursa/Controls/Timeline/TimelineDisplayMode.cs b/src/Ursa/Controls/Timeline/TimelineDisplayMode.cs new file mode 100644 index 0000000..1907672 --- /dev/null +++ b/src/Ursa/Controls/Timeline/TimelineDisplayMode.cs @@ -0,0 +1,9 @@ +namespace Ursa.Controls; + +public enum TimelineDisplayMode +{ + Left, + Center, + Right, + Alternate, +} \ No newline at end of file diff --git a/src/Ursa/Controls/Timeline/TimelineItem.cs b/src/Ursa/Controls/Timeline/TimelineItem.cs index 20e57d6..8f08983 100644 --- a/src/Ursa/Controls/Timeline/TimelineItem.cs +++ b/src/Ursa/Controls/Timeline/TimelineItem.cs @@ -8,9 +8,13 @@ using Avalonia.Media; namespace Ursa.Controls; -[PseudoClasses(":first", ":last")] +[PseudoClasses(PC_First, PC_Last, PC_EmptyIcon)] public class TimelineItem: HeaderedContentControl { + public const string PC_First = ":first"; + public const string PC_Last = ":last"; + public const string PC_EmptyIcon = ":empty-icon"; + public static readonly StyledProperty IconProperty = AvaloniaProperty.Register( nameof(Icon)); @@ -37,10 +41,47 @@ public class TimelineItem: HeaderedContentControl get => GetValue(TypeProperty); set => SetValue(TypeProperty, value); } + + public static readonly DirectProperty LeftWidthProperty = AvaloniaProperty.RegisterDirect( + nameof(LeftWidth), o => o.LeftWidth, (o, v) => o.LeftWidth = v); + private double _leftWidth; + public double LeftWidth + { + get => _leftWidth; + set => SetAndRaise(LeftWidthProperty, ref _leftWidth, value); + } + + public static readonly DirectProperty IconWidthProperty = AvaloniaProperty.RegisterDirect( + nameof(IconWidth), o => o.IconWidth, (o, v) => o.IconWidth = v); + private double _iconWidth; + public double IconWidth + { + get => _iconWidth; + set => SetAndRaise(IconWidthProperty, ref _iconWidth, value); + } + + public static readonly DirectProperty RightWidthProperty = AvaloniaProperty.RegisterDirect( + nameof(RightWidth), o => o.RightWidth, (o, v) => o.RightWidth = v); + private double _rightWidth; + public double RightWidth + { + get => _rightWidth; + set => SetAndRaise(RightWidthProperty, ref _rightWidth, value); + } + + static TimelineItem() + { + IconProperty.Changed.AddClassHandler((item, args) => { item.OnIconChanged(args); }); + } + + private void OnIconChanged(AvaloniaPropertyChangedEventArgs args) + { + PseudoClasses.Set(PC_EmptyIcon, args.NewValue.Value is null); + } internal void SetEnd(bool start, bool end) { - PseudoClasses.Set(":first", start); - PseudoClasses.Set(":last", end); + PseudoClasses.Set(PC_First, start); + PseudoClasses.Set(PC_Last, end); } } \ No newline at end of file diff --git a/src/Ursa/Controls/Timeline/TimelinePanel.cs b/src/Ursa/Controls/Timeline/TimelinePanel.cs new file mode 100644 index 0000000..ea6efba --- /dev/null +++ b/src/Ursa/Controls/Timeline/TimelinePanel.cs @@ -0,0 +1,43 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Layout; + +namespace Ursa.Controls; + +public class TimelinePanel: Panel +{ + public static readonly StyledProperty ModeProperty = + Timeline.ModeProperty.AddOwner(); + + public TimelineDisplayMode Mode + { + get => GetValue(ModeProperty); + set => SetValue(ModeProperty, value); + } + + static TimelinePanel() + { + AffectsMeasure(ModeProperty); + } + + protected override Size MeasureOverride(Size availableSize) + { + double left = 0; + double right = 0; + double icon = 0; + foreach (var child in Children) + { + if (child is TimelineItem t) + { + + } + } + return base.MeasureOverride(availableSize); + } + + protected override Size ArrangeOverride(Size finalSize) + { + return base.ArrangeOverride(finalSize); + + } +} \ No newline at end of file