Skip to content

Commit c55e171

Browse files
committed
Fix time calculations. Improved 7-segment display code
1 parent 997bad1 commit c55e171

21 files changed

+286
-141
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
2+
<s:Boolean x:Key="/Default/CodeInspection/NamespaceProvider/NamespaceFoldersToSkip/=clock/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
using System;
2+
using System.Windows;
3+
using System.Windows.Controls;
4+
using System.Windows.Threading;
5+
6+
namespace BionicCode.Controls.Net.Wpf
7+
{
8+
public class Clock : Control
9+
{
10+
#region Dependency Properties
11+
12+
#region ClockFace dependency property
13+
14+
public static readonly DependencyProperty ClockFaceProperty = DependencyProperty.Register(
15+
"ClockFace",
16+
typeof(ClockFace),
17+
typeof(Clock),
18+
new PropertyMetadata(default));
19+
20+
public ClockFace ClockFace { get => (ClockFace) GetValue(Clock.ClockFaceProperty); set => SetValue(Clock.ClockFaceProperty, value); }
21+
22+
#endregion ClockFace dependency property
23+
24+
#region CurrentDateTime dependency property
25+
26+
public static readonly DependencyProperty CurrentDateTimeProperty = DependencyProperty.Register(
27+
"CurrentDateTime",
28+
typeof(DateTime),
29+
typeof(Clock),
30+
new PropertyMetadata(default(DateTime), Clock.OnCurrentDateTimeChanged));
31+
32+
public DateTime CurrentDateTime { get => (DateTime) GetValue(Clock.CurrentDateTimeProperty); set => SetValue(Clock.CurrentDateTimeProperty, value); }
33+
34+
#endregion CurrentDateTime dependency property
35+
36+
#region TimeZone dependency property
37+
38+
public static readonly DependencyProperty TimeZoneProperty = DependencyProperty.Register(
39+
"TimeZone",
40+
typeof(TimeZoneInfo),
41+
typeof(Clock),
42+
new PropertyMetadata(TimeZoneInfo.Local));
43+
44+
public TimeZoneInfo TimeZone { get => (TimeZoneInfo) GetValue(Clock.TimeZoneProperty); set => SetValue(Clock.TimeZoneProperty, value); }
45+
46+
#endregion TimeZone dependency property
47+
48+
#region Resolution dependency property
49+
50+
public static readonly DependencyProperty ResolutionProperty = DependencyProperty.Register(
51+
"Resolution",
52+
typeof(TimeSpan),
53+
typeof(Clock),
54+
new PropertyMetadata(TimeSpan.FromSeconds(1)));
55+
56+
public TimeSpan Resolution { get => (TimeSpan) GetValue(Clock.ResolutionProperty); set => SetValue(Clock.ResolutionProperty, value); }
57+
58+
#endregion Resolution dependency property
59+
60+
#region Precision dependency property
61+
62+
public static readonly DependencyProperty PrecisionProperty = DependencyProperty.Register(
63+
"Precision",
64+
typeof(TimeSpan),
65+
typeof(Clock),
66+
new PropertyMetadata(TimeSpan.FromMilliseconds(50)));
67+
68+
public TimeSpan Precision { get => (TimeSpan) GetValue(Clock.PrecisionProperty); set => SetValue(Clock.PrecisionProperty, value); }
69+
70+
#endregion Precision dependency property
71+
72+
#region DispatcherPriority dependency property
73+
74+
public static readonly DependencyProperty DispatcherPriorityProperty = DependencyProperty.Register(
75+
"DispatcherPriority",
76+
typeof(DispatcherPriority),
77+
typeof(Clock),
78+
new PropertyMetadata(System.Windows.Threading.DispatcherPriority.Send));
79+
80+
public DispatcherPriority DispatcherPriority { get => (DispatcherPriority) GetValue(Clock.DispatcherPriorityProperty); set => SetValue(Clock.DispatcherPriorityProperty, value); }
81+
82+
#endregion DispatcherPriority dependency property
83+
84+
#region Meridiem read-only dependency property
85+
protected static readonly DependencyPropertyKey MeridiemPropertyKey = DependencyProperty.RegisterReadOnly(
86+
"Meridiem",
87+
typeof(Meridiem),
88+
typeof(Clock),
89+
new PropertyMetadata(default(Meridiem)));
90+
91+
public static readonly DependencyProperty MeridiemProperty = Clock.MeridiemPropertyKey.DependencyProperty;
92+
93+
public Meridiem Meridiem
94+
{
95+
get => (Meridiem) GetValue(Clock.MeridiemProperty);
96+
private set => SetValue(Clock.MeridiemPropertyKey, value);
97+
}
98+
99+
#endregion Meridiem read-only dependency property
100+
101+
#endregion Dependency Properties
102+
103+
public bool IsDaylightSavingTime => this.TimeZone.IsDaylightSavingTime(this.CurrentDateTime);
104+
105+
private DispatcherTimer Timer { get; }
106+
107+
static Clock()
108+
{
109+
FrameworkElement.DefaultStyleKeyProperty
110+
.OverrideMetadata(typeof(Clock), new FrameworkPropertyMetadata(typeof(Clock)));
111+
}
112+
113+
public Clock()
114+
{
115+
this.Timer = new DispatcherTimer(this.Precision, this.DispatcherPriority, OnTimerElapsed, this.Dispatcher);
116+
}
117+
118+
#region OnCurrentDateTimeChanged dependency property changed handler
119+
120+
private static void OnCurrentDateTimeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) =>
121+
(d as Clock).OnCurrentDateTimeChanged((DateTime) e.OldValue, (DateTime) e.NewValue);
122+
123+
protected virtual void OnCurrentDateTimeChanged(DateTime oldValue, DateTime newValue)
124+
{
125+
this.Meridiem = newValue.TimeOfDay < new TimeSpan(11, 59, 59)
126+
? Meridiem.AM
127+
: Meridiem.PM;
128+
}
129+
130+
#endregion OnCurrentDateTimeChanged dependency property changed handler
131+
132+
private void OnTimerElapsed(object sender, EventArgs e) => this.CurrentDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, this.TimeZone);
133+
}
134+
}

BionicCode.Net/BionicCode.Controls.Net.Wpf/ClockFace.cs renamed to BionicCode.Net/BionicCode.Controls.Net.Wpf/Clock/ClockFace.cs

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -275,19 +275,11 @@ private static object CoerceHours(DependencyObject d, object basevalue)
275275
: Math.Truncate(hourValue) % 12;
276276
double decimalPart = hourValue - Math.Truncate(hourValue);
277277
var decimalMinutes = decimalPart * 60;
278-
bool isOverflow = decimalMinutes >= 1.0;
279-
if (isOverflow)
280-
{
281-
this_.SelectedMinute = Math.Truncate(decimalMinutes);
282-
}
278+
this_.SelectedMinute = Math.Truncate(decimalMinutes);
283279

284280
decimalPart = decimalMinutes - Math.Truncate(decimalMinutes);
285-
var decimalSeconds = Math.Round(decimalPart * 60, MidpointRounding.AwayFromZero);
286-
isOverflow = decimalSeconds >= 1.0;
287-
if (isOverflow)
288-
{
289-
this_.SelectedSecond = decimalSeconds;
290-
}
281+
var decimalSeconds = Math.Truncate(decimalPart * 60);
282+
this_.SelectedSecond = decimalSeconds;
291283

292284
this_.IsUpdatingSelectedTimeComponent = false;
293285
return hours;
@@ -305,26 +297,18 @@ private static object CoerceMinutes(DependencyObject d, object basevalue)
305297
this_.IsUpdatingSelectedTimeComponent = true;
306298
var minuteValue = (double) basevalue;
307299
double decimalHours = minuteValue / 60;
308-
bool isOverflow = decimalHours >= 1.0;
309-
if (isOverflow)
310-
{
311-
this_.SelectedHour = this_.Is24HModeEnabled
312-
? Math.Truncate(decimalHours) % 24
313-
: Math.Truncate(decimalHours) % 12 == 0
314-
? 12
315-
: Math.Truncate(decimalHours) % 12;
316-
}
300+
this_.SelectedHour = this_.Is24HModeEnabled
301+
? Math.Truncate(decimalHours) % 24
302+
: Math.Truncate(decimalHours) % 12 == 0
303+
? 12
304+
: Math.Truncate(decimalHours) % 12;
317305

318306
var decimalMinutes = minuteValue % 60;
319307
var minutes = Math.Truncate(decimalMinutes);
320308

321309
var decimalPart = decimalMinutes - Math.Truncate(decimalMinutes);
322-
double decimalSeconds = Math.Round(decimalPart * 60, MidpointRounding.AwayFromZero);
323-
isOverflow = decimalSeconds >= 1.0;
324-
if (isOverflow)
325-
{
326-
this_.SelectedSecond = decimalSeconds;
327-
}
310+
double decimalSeconds = Math.Truncate(decimalPart * 60);
311+
this_.SelectedSecond = decimalSeconds;
328312

329313
this_.IsUpdatingSelectedTimeComponent = false;
330314
return minutes;
@@ -342,26 +326,18 @@ private static object CoerceSeconds(DependencyObject d, object basevalue)
342326
this_.IsUpdatingSelectedTimeComponent = true;
343327
var secondsValue = (double) basevalue;
344328
double decimalHours = secondsValue / 3600;
345-
bool isOverflow = decimalHours >= 1.0;
346-
if (isOverflow)
347-
{
348-
this_.SelectedHour = this_.Is24HModeEnabled
349-
? Math.Truncate(decimalHours) % 24
350-
: Math.Truncate(decimalHours) % 12 == 0
351-
? 12
352-
: Math.Truncate(decimalHours) % 12;
353-
}
329+
this_.SelectedHour = this_.Is24HModeEnabled
330+
? Math.Truncate(decimalHours) % 24
331+
: Math.Truncate(decimalHours) % 12 == 0
332+
? 12
333+
: Math.Truncate(decimalHours) % 12;
354334

355335
var minutePart = secondsValue % 3600;
356336
double decimalMinutes = minutePart / 60;
357-
isOverflow = decimalMinutes >= 1.0;
358-
if (isOverflow)
359-
{
360-
this_.SelectedMinute = Math.Truncate(decimalMinutes);
361-
}
337+
this_.SelectedMinute = Math.Truncate(decimalMinutes);
362338

363339
double decimalSeconds = minutePart % 60;
364-
var seconds = Math.Round(decimalSeconds, MidpointRounding.AwayFromZero);
340+
var seconds = Math.Truncate(decimalSeconds);
365341

366342
this_.IsUpdatingSelectedTimeComponent = false;
367343
return seconds;

BionicCode.Net/BionicCode.Controls.Net.Wpf/DigitalClockFace.cs renamed to BionicCode.Net/BionicCode.Controls.Net.Wpf/Clock/DigitalClockFace.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ protected override void OnSelectedTimeChanged(DateTime oldValue, DateTime newVal
3131
{
3232
base.OnSelectedTimeChanged(oldValue, newValue);
3333

34-
double concatenatedTimeValues = this.SelectedHour * 10000
35-
+ this.SelectedMinute * 100
34+
double concatenatedTimeValues = this.SelectedHour * Math.Pow(10, 4)
35+
+ this.SelectedMinute * Math.Pow(10, 2)
3636
+ this.SelectedSecond;
3737
this.SegmentDisplayDriver.SetValue((int) concatenatedTimeValues);
3838
}

0 commit comments

Comments
 (0)