feat: add auto tick sample.
This commit is contained in:
@@ -5,10 +5,14 @@
|
|||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||||
xmlns:u="https://irihi.tech/ursa"
|
xmlns:u="https://irihi.tech/ursa"
|
||||||
|
xmlns:vm="clr-namespace:Ursa.Demo.ViewModels"
|
||||||
|
x:DataType="vm:ClockDemoViewModel"
|
||||||
|
x:CompileBindings="True"
|
||||||
d:DesignHeight="450"
|
d:DesignHeight="450"
|
||||||
d:DesignWidth="800"
|
d:DesignWidth="800"
|
||||||
|
|
||||||
mc:Ignorable="d">
|
mc:Ignorable="d">
|
||||||
<Grid>
|
<Grid>
|
||||||
<u:Clock HorizontalAlignment="Left"></u:Clock>
|
<u:Clock HorizontalAlignment="Left" Time="{Binding Time}"></u:Clock>
|
||||||
</Grid>
|
</Grid>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,15 +5,55 @@
|
|||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<!-- Add Resources Here -->
|
<!-- Add Resources Here -->
|
||||||
<ControlTheme x:Key="{x:Type u:Clock}" TargetType="u:Clock">
|
<ControlTheme x:Key="{x:Type u:Clock}" TargetType="u:Clock">
|
||||||
|
<Setter Property="HandBrush" Value="{DynamicResource SemiGrey6}"/>
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:Clock">
|
<ControlTemplate TargetType="u:Clock">
|
||||||
<Grid>
|
<Grid>
|
||||||
<u:ClockTicks HorizontalAlignment="{TemplateBinding HorizontalAlignment}" HourTickForeground="{DynamicResource SemiGrey6}" MinuteTickForeground="{DynamicResource SemiGrey4}" />
|
<u:ClockTicks
|
||||||
<Rectangle Width="8" Height="100" Fill="White" />
|
ShowHourTicks="{TemplateBinding ShowHourTicks}"
|
||||||
<Rectangle Width="4" />
|
ShowMinuteTicks="{TemplateBinding ShowMinuteTicks}"
|
||||||
<iri:PureCircle
|
HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
|
||||||
Diameter="16"
|
HourTickForeground="{DynamicResource SemiGrey6}"
|
||||||
Background="Red" />
|
MinuteTickForeground="{DynamicResource SemiGrey4}" />
|
||||||
|
<UniformGrid Rows="2" IsVisible="{TemplateBinding ShowHourHand}">
|
||||||
|
<Border
|
||||||
|
Width="16"
|
||||||
|
Margin="0,16,0,0"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="{TemplateBinding HandBrush}"
|
||||||
|
CornerRadius="8" />
|
||||||
|
<UniformGrid.RenderTransform>
|
||||||
|
<RotateTransform Angle="{Binding HourAngle, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||||
|
</UniformGrid.RenderTransform>
|
||||||
|
</UniformGrid>
|
||||||
|
<UniformGrid Rows="2" IsVisible="{TemplateBinding ShowMinuteHand}">
|
||||||
|
<Border
|
||||||
|
Width="8"
|
||||||
|
Margin="0,8,0,0"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="{TemplateBinding HandBrush}"
|
||||||
|
CornerRadius="4" />
|
||||||
|
<UniformGrid.RenderTransform>
|
||||||
|
<RotateTransform Angle="{Binding MinuteAngle, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||||
|
</UniformGrid.RenderTransform>
|
||||||
|
</UniformGrid>
|
||||||
|
<UniformGrid Rows="2" IsVisible="{TemplateBinding ShowSecondHand}">
|
||||||
|
<Border
|
||||||
|
Width="4"
|
||||||
|
Margin="0,4,0,0"
|
||||||
|
VerticalAlignment="Stretch"
|
||||||
|
Background="{TemplateBinding HandBrush}"
|
||||||
|
CornerRadius="4" />
|
||||||
|
<UniformGrid.RenderTransform>
|
||||||
|
<RotateTransform Angle="{Binding SecondAngle, RelativeSource={RelativeSource TemplatedParent}}" />
|
||||||
|
</UniformGrid.RenderTransform>
|
||||||
|
</UniformGrid>
|
||||||
|
<Ellipse
|
||||||
|
Width="20"
|
||||||
|
Height="20"
|
||||||
|
Fill="White"
|
||||||
|
Stroke="{DynamicResource SemiBlue5}"
|
||||||
|
StrokeThickness="3" />
|
||||||
</Grid>
|
</Grid>
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using Avalonia;
|
using Avalonia;
|
||||||
using Avalonia.Controls.Metadata;
|
using Avalonia.Controls.Metadata;
|
||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
|
using Avalonia.Data;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
@@ -9,10 +11,10 @@ public class Clock: TemplatedControl
|
|||||||
{
|
{
|
||||||
public const string PART_ClockTicks = "PART_ClockTicks";
|
public const string PART_ClockTicks = "PART_ClockTicks";
|
||||||
|
|
||||||
public static readonly StyledProperty<TimeSpan> TimeProperty = AvaloniaProperty.Register<Clock, TimeSpan>(
|
public static readonly StyledProperty<DateTime> TimeProperty = AvaloniaProperty.Register<Clock, DateTime>(
|
||||||
nameof(Time));
|
nameof(Time), defaultBindingMode: BindingMode.TwoWay);
|
||||||
|
|
||||||
public TimeSpan Time
|
public DateTime Time
|
||||||
{
|
{
|
||||||
get => GetValue(TimeProperty);
|
get => GetValue(TimeProperty);
|
||||||
set => SetValue(TimeProperty, value);
|
set => SetValue(TimeProperty, value);
|
||||||
@@ -36,22 +38,89 @@ public class Clock: TemplatedControl
|
|||||||
set => SetValue(ShowMinuteTicksProperty, value);
|
set => SetValue(ShowMinuteTicksProperty, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<double> HourHandMarginProperty = AvaloniaProperty.Register<Clock, double>(
|
public static readonly StyledProperty<IBrush?> HandBrushProperty = AvaloniaProperty.Register<Clock, IBrush?>(
|
||||||
nameof(HourHandMargin));
|
nameof(HandBrush));
|
||||||
|
|
||||||
public double HourHandMargin
|
public IBrush? HandBrush
|
||||||
{
|
{
|
||||||
get => GetValue(HourHandMarginProperty);
|
get => GetValue(HandBrushProperty);
|
||||||
set => SetValue(HourHandMarginProperty, value);
|
set => SetValue(HandBrushProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> ShowHourHandProperty = AvaloniaProperty.Register<Clock, bool>(
|
||||||
|
nameof(ShowHourHand), defaultValue: true);
|
||||||
|
|
||||||
|
public bool ShowHourHand
|
||||||
|
{
|
||||||
|
get => GetValue(ShowHourHandProperty);
|
||||||
|
set => SetValue(ShowHourHandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> ShowMinuteHandProperty = AvaloniaProperty.Register<Clock, bool>(
|
||||||
|
nameof(ShowMinuteHand), defaultValue: true);
|
||||||
|
|
||||||
|
public bool ShowMinuteHand
|
||||||
|
{
|
||||||
|
get => GetValue(ShowMinuteHandProperty);
|
||||||
|
set => SetValue(ShowMinuteHandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly StyledProperty<bool> ShowSecondHandProperty = AvaloniaProperty.Register<Clock, bool>(
|
||||||
|
nameof(ShowSecondHand), defaultValue: true);
|
||||||
|
|
||||||
|
public bool ShowSecondHand
|
||||||
|
{
|
||||||
|
get => GetValue(ShowSecondHandProperty);
|
||||||
|
set => SetValue(ShowSecondHandProperty, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static readonly DirectProperty<Clock, double> HourAngleProperty = AvaloniaProperty.RegisterDirect<Clock, double>(
|
||||||
|
nameof(HourAngle), o => o.HourAngle);
|
||||||
|
private double _hourAngle;
|
||||||
|
public double HourAngle
|
||||||
|
{
|
||||||
|
get => _hourAngle;
|
||||||
|
private set => SetAndRaise(HourAngleProperty, ref _hourAngle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static readonly StyledProperty<double> MinuteHandMarginProperty = AvaloniaProperty.Register<Clock, double>(
|
public static readonly DirectProperty<Clock, double> MinuteAngleProperty = AvaloniaProperty.RegisterDirect<Clock, double>(
|
||||||
nameof(MinuteHandMargin));
|
nameof(MinuteAngle), o => o.MinuteAngle);
|
||||||
|
private double _minuteAngle;
|
||||||
public double MinuteHandMargin
|
public double MinuteAngle
|
||||||
{
|
{
|
||||||
get => GetValue(MinuteHandMarginProperty);
|
get => _minuteAngle;
|
||||||
set => SetValue(MinuteHandMarginProperty, value);
|
private set => SetAndRaise(MinuteAngleProperty, ref _minuteAngle, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly DirectProperty<Clock, double> SecondAngleProperty = AvaloniaProperty.RegisterDirect<Clock, double>(
|
||||||
|
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, DateTime>((clock, args)=>clock.OnTimeChanged(args));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTimeChanged(AvaloniaPropertyChangedEventArgs<DateTime> 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)
|
protected override Size MeasureOverride(Size availableSize)
|
||||||
|
|||||||
Reference in New Issue
Block a user