TimeControl.axaml.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using Avalonia;
  2. using Avalonia.Controls;
  3. using Avalonia.LogicalTree;
  4. using Avalonia.Markup.Xaml;
  5. using System;
  6. namespace ShakerApp.Views;
  7. public partial class TimeControl : UserControl
  8. {
  9. public TimeControl()
  10. {
  11. InitializeComponent();
  12. }
  13. protected override void OnAttachedToLogicalTree(LogicalTreeAttachmentEventArgs e)
  14. {
  15. base.OnAttachedToLogicalTree(e);
  16. this.HourControl.ValueChanged += HourControl_ValueChanged;
  17. this.MinuteControl.ValueChanged += MinuteControl_ValueChanged;
  18. this.SecondControl.ValueChanged += SecondControl_ValueChanged;
  19. }
  20. private void SecondControl_ValueChanged(object? sender, NumericUpDownValueChangedEventArgs e)
  21. {
  22. if (changed) return;
  23. if(!this.SecondControl.Value.HasValue)
  24. {
  25. SecondControl.Value = 0;
  26. }
  27. float s = MathF.Floor(((float)(this.SecondControl.Value!)) / this.Increment) * Increment;
  28. s = Math.Clamp(s, 0, 60 - Increment);
  29. this.changed = true;
  30. this.SecondControl.Value = (decimal)s;
  31. this.SetValue(TimeProperty,(float)((float)this.HourControl.Value! * 3600 + (float)MinuteControl.Value! * 60 + s));
  32. this.changed = false;
  33. }
  34. private void MinuteControl_ValueChanged(object? sender, NumericUpDownValueChangedEventArgs e)
  35. {
  36. if (changed) return;
  37. if(!this.MinuteControl.Value.HasValue)
  38. {
  39. this.MinuteControl.Value = 0;
  40. }
  41. byte m = (byte)MinuteControl.Value;
  42. m = Math.Clamp(m, (byte)0, (byte)59);
  43. this.changed = true;
  44. this.MinuteControl.Value = m;
  45. this.SetValue(TimeProperty, (float)((float)this.HourControl.Value! * 3600 + (float)MinuteControl.Value! * 60 + (float)this.SecondControl.Value!));
  46. this.changed = false;
  47. }
  48. private void HourControl_ValueChanged(object? sender, NumericUpDownValueChangedEventArgs e)
  49. {
  50. if (changed) return;
  51. if (!this.HourControl.Value.HasValue)
  52. {
  53. this.HourControl.Value = 0;
  54. }
  55. uint m = (uint)HourControl.Value;
  56. this.changed = true;
  57. this.HourControl.Value = m;
  58. this.SetValue(TimeProperty, ((float)this.HourControl.Value! * 3600 + (float)MinuteControl.Value! * 60 + (float)this.SecondControl.Value!));
  59. this.changed = false;
  60. }
  61. private bool changed = false;
  62. public static readonly StyledProperty<float> TimeProperty = AvaloniaProperty.Register<TimeControl, float>(nameof(Time), defaultBindingMode: Avalonia.Data.BindingMode.TwoWay, defaultValue: 0, coerce: static (obj, val) =>
  63. {
  64. if (obj is TimeControl control)
  65. {
  66. float time = val;
  67. if (control.changed) return val;
  68. control.changed = true;
  69. uint hour = (uint)time / 3600;
  70. byte minute = (byte)((uint)time / 60 % 60);
  71. float second = MathF.Floor((time - (control.Hour * 3600 + control.Minute * 60)) / control.Increment) * control.Increment;
  72. control.HourControl.Value = hour;
  73. control.MinuteControl.Value = minute;
  74. control.SecondControl.Value = (decimal)second;
  75. control.changed = false;
  76. }
  77. return val;
  78. });
  79. public float Time
  80. {
  81. get => GetValue(TimeProperty);
  82. set
  83. {
  84. var val = GetValue(TimeProperty);
  85. if (val == value) return;
  86. SetValue(TimeProperty, value);
  87. }
  88. }
  89. public static readonly StyledProperty<uint> HourProperty = AvaloniaProperty.Register<TimeControl, uint>(nameof(Hour), defaultValue: 0, coerce: (obj, val) =>
  90. {
  91. if (obj is TimeControl control)
  92. {
  93. control.SetValue(TimeProperty, control.Hour * 3600 + control.Minute * 60 + control.Second);
  94. }
  95. return val;
  96. });
  97. public uint Hour
  98. {
  99. get => GetValue(HourProperty);
  100. set
  101. {
  102. var val = GetValue(HourProperty);
  103. if (val == value) return;
  104. SetValue(HourProperty, value);
  105. }
  106. }
  107. public static readonly StyledProperty<byte> MinuteProperty = AvaloniaProperty.Register<TimeControl, byte>(nameof(Minute), defaultValue: 0, coerce:(obj,val)=>
  108. {
  109. byte temp = Math.Clamp(val, (byte)0, (byte)59);
  110. var control = (TimeControl)obj;
  111. control.SetValue(TimeProperty, control.Hour * 3600 + temp * 60 + control.Second);
  112. return temp;
  113. });
  114. public byte Minute
  115. {
  116. get => GetValue(MinuteProperty);
  117. set
  118. {
  119. var val = GetValue(MinuteProperty);
  120. if (val == value) return;
  121. SetValue(MinuteProperty, value);
  122. }
  123. }
  124. public static readonly StyledProperty<float> SecondProperty = AvaloniaProperty.Register<TimeControl, float>(nameof(Second), defaultValue: 0, coerce: (obj, val) =>
  125. {
  126. var control = (TimeControl)obj;
  127. float temp = Math.Clamp(val, 0f, 59f - control.Increment);
  128. control.SetValue(TimeProperty, control.Hour * 3600 + control.Minute * 60 + temp);
  129. return temp;
  130. });
  131. public float Second
  132. {
  133. get => GetValue(SecondProperty);
  134. set
  135. {
  136. var val = GetValue(SecondProperty);
  137. if (val == value) return;
  138. SetValue(SecondProperty, value);
  139. }
  140. }
  141. public static readonly StyledProperty<float> IncrementProperty = AvaloniaProperty.Register<TimeControl, float>(nameof(Increment), defaultValue:0.01f );
  142. public float Increment
  143. {
  144. get => GetValue(IncrementProperty);
  145. set => SetValue(IncrementProperty, value);
  146. }
  147. }