From db6ba785ddf3d13bae67aa3d2bb7229b905d01bc Mon Sep 17 00:00:00 2001 From: rabbitism Date: Mon, 22 Apr 2024 02:05:29 +0800 Subject: [PATCH] feat: add auto tick sample. --- demo/Ursa.Demo/Pages/ClockDemo.axaml | 6 +- .../ViewModels/ClockDemoViewModel.cs | 29 +++++- src/Ursa.Themes.Semi/Controls/Clock.axaml | 52 ++++++++-- src/Ursa/Controls/Clock/Clock.cs | 97 ++++++++++++++++--- 4 files changed, 161 insertions(+), 23 deletions(-) diff --git a/demo/Ursa.Demo/Pages/ClockDemo.axaml b/demo/Ursa.Demo/Pages/ClockDemo.axaml index 4dcde2d..892aa17 100644 --- a/demo/Ursa.Demo/Pages/ClockDemo.axaml +++ b/demo/Ursa.Demo/Pages/ClockDemo.axaml @@ -5,10 +5,14 @@ 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:vm="clr-namespace:Ursa.Demo.ViewModels" + x:DataType="vm:ClockDemoViewModel" + x:CompileBindings="True" d:DesignHeight="450" d:DesignWidth="800" + mc:Ignorable="d"> - + diff --git a/demo/Ursa.Demo/ViewModels/ClockDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/ClockDemoViewModel.cs index 4670003..48cda91 100644 --- a/demo/Ursa.Demo/ViewModels/ClockDemoViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/ClockDemoViewModel.cs @@ -1,6 +1,31 @@ -namespace Ursa.Demo.ViewModels; +using System; +using System.Timers; +using CommunityToolkit.Mvvm.ComponentModel; -public class ClockDemoViewModel +namespace Ursa.Demo.ViewModels; + +public partial class ClockDemoViewModel: ObservableObject, IDisposable { + private Timer _timer; + [ObservableProperty] private DateTime _time; + public ClockDemoViewModel() + { + Time = DateTime.Now; + _timer = new Timer(1000); + _timer.Elapsed += TimerOnElapsed; + _timer.Start(); + } + + private void TimerOnElapsed(object? sender, ElapsedEventArgs e) + { + Time = DateTime.Now; + } + + public void Dispose() + { + _timer.Stop(); + _timer.Elapsed -= TimerOnElapsed; + _timer.Dispose(); + } } \ No newline at end of file diff --git a/src/Ursa.Themes.Semi/Controls/Clock.axaml b/src/Ursa.Themes.Semi/Controls/Clock.axaml index a62b9f9..14b554a 100644 --- a/src/Ursa.Themes.Semi/Controls/Clock.axaml +++ b/src/Ursa.Themes.Semi/Controls/Clock.axaml @@ -5,15 +5,55 @@ xmlns:u="https://irihi.tech/ursa"> + - - - - + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ursa/Controls/Clock/Clock.cs b/src/Ursa/Controls/Clock/Clock.cs index 92bb777..f73b0fd 100644 --- a/src/Ursa/Controls/Clock/Clock.cs +++ b/src/Ursa/Controls/Clock/Clock.cs @@ -1,6 +1,8 @@ using Avalonia; using Avalonia.Controls.Metadata; using Avalonia.Controls.Primitives; +using Avalonia.Data; +using Avalonia.Media; namespace Ursa.Controls; @@ -9,10 +11,10 @@ public class Clock: TemplatedControl { public const string PART_ClockTicks = "PART_ClockTicks"; - public static readonly StyledProperty TimeProperty = AvaloniaProperty.Register( - nameof(Time)); + public static readonly StyledProperty TimeProperty = AvaloniaProperty.Register( + nameof(Time), defaultBindingMode: BindingMode.TwoWay); - public TimeSpan Time + public DateTime Time { get => GetValue(TimeProperty); set => SetValue(TimeProperty, value); @@ -36,22 +38,89 @@ public class Clock: TemplatedControl set => SetValue(ShowMinuteTicksProperty, value); } - public static readonly StyledProperty HourHandMarginProperty = AvaloniaProperty.Register( - nameof(HourHandMargin)); + public static readonly StyledProperty HandBrushProperty = AvaloniaProperty.Register( + nameof(HandBrush)); - public double HourHandMargin + public IBrush? HandBrush { - get => GetValue(HourHandMarginProperty); - set => SetValue(HourHandMarginProperty, value); + get => GetValue(HandBrushProperty); + set => SetValue(HandBrushProperty, value); + } + + public static readonly StyledProperty ShowHourHandProperty = AvaloniaProperty.Register( + nameof(ShowHourHand), defaultValue: true); + + public bool ShowHourHand + { + get => GetValue(ShowHourHandProperty); + set => SetValue(ShowHourHandProperty, value); + } + + public static readonly StyledProperty ShowMinuteHandProperty = AvaloniaProperty.Register( + nameof(ShowMinuteHand), defaultValue: true); + + public bool ShowMinuteHand + { + get => GetValue(ShowMinuteHandProperty); + set => SetValue(ShowMinuteHandProperty, value); + } + + public static readonly StyledProperty ShowSecondHandProperty = AvaloniaProperty.Register( + nameof(ShowSecondHand), defaultValue: true); + + public bool ShowSecondHand + { + get => GetValue(ShowSecondHandProperty); + set => SetValue(ShowSecondHandProperty, value); + } + + + + public static readonly DirectProperty HourAngleProperty = AvaloniaProperty.RegisterDirect( + nameof(HourAngle), o => o.HourAngle); + private double _hourAngle; + public double HourAngle + { + get => _hourAngle; + private set => SetAndRaise(HourAngleProperty, ref _hourAngle, value); } - public static readonly StyledProperty MinuteHandMarginProperty = AvaloniaProperty.Register( - nameof(MinuteHandMargin)); - - public double MinuteHandMargin + public static readonly DirectProperty MinuteAngleProperty = AvaloniaProperty.RegisterDirect( + nameof(MinuteAngle), o => o.MinuteAngle); + private double _minuteAngle; + public double MinuteAngle { - get => GetValue(MinuteHandMarginProperty); - set => SetValue(MinuteHandMarginProperty, value); + get => _minuteAngle; + private set => SetAndRaise(MinuteAngleProperty, ref _minuteAngle, value); + } + + public static readonly DirectProperty SecondAngleProperty = AvaloniaProperty.RegisterDirect( + nameof(SecondAngle), o => o.SecondAngle); + + private double _secondAngle; + public double SecondAngle + { + get => _secondAngle; + private set => SetAndRaise(SecondAngleProperty, ref _secondAngle, value); + } + + static Clock() + { + TimeProperty.Changed.AddClassHandler((clock, args)=>clock.OnTimeChanged(args)); + } + + private void OnTimeChanged(AvaloniaPropertyChangedEventArgs args) + { + DateTime time = args.NewValue.Value; + var hour = time.Hour; + var minute = time.Minute; + var second = time.Second; + var hourAngle = 360.0 / 12 * hour + 360.0 / 12 / 60 * minute; + var minuteAngle = 360.0 / 60 * minute + 360.0 / 60 / 60 * second; + var secondAngle = 360.0 / 60 * second; + HourAngle = hourAngle; + MinuteAngle = minuteAngle; + SecondAngle = secondAngle; } protected override Size MeasureOverride(Size availableSize)