Skip to content

Commit a14140d

Browse files
committed
Improve AnalogClockFace appearance and customizability
1 parent a48cf8c commit a14140d

File tree

8 files changed

+555
-168
lines changed

8 files changed

+555
-168
lines changed

BionicCode.Net/BionicCode.Controls.Net.Core.Wpf/AnalogClockFace.cs

Lines changed: 354 additions & 87 deletions
Large diffs are not rendered by default.

BionicCode.Net/BionicCode.Controls.Net.Core.Wpf/AnalogTimePicker.cs

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,33 +20,21 @@ public class AnalogTimePicker : Control
2020

2121
public static readonly DependencyProperty AnalogClockFaceProperty = DependencyProperty.Register(
2222
"AnalogClockFace",
23-
typeof(Canvas),
23+
typeof(FrameworkElement),
2424
typeof(AnalogTimePicker),
25-
new PropertyMetadata(default(Canvas), OnAnalogClockFaceChanged));
25+
new FrameworkPropertyMetadata(default(FrameworkElement), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange, AnalogTimePicker.OnAnalogClockFaceChanged));
2626

27-
public AnalogClockFace AnalogClockFace { get => (AnalogClockFace) GetValue(AnalogTimePicker.AnalogClockFaceProperty); set => SetValue(AnalogTimePicker.AnalogClockFaceProperty, value); }
27+
public FrameworkElement AnalogClockFace { get => (FrameworkElement) GetValue(AnalogTimePicker.AnalogClockFaceProperty); set => SetValue(AnalogTimePicker.AnalogClockFaceProperty, value); }
2828

2929
#endregion AnalogClockFace dependency property
3030

31-
#region AnalogClockFaceStyle dependency property
32-
33-
public static readonly DependencyProperty AnalogClockFaceStyleProperty = DependencyProperty.Register(
34-
"AnalogClockFaceStyle",
35-
typeof(Style),
36-
typeof(AnalogTimePicker),
37-
new PropertyMetadata(default));
38-
39-
public Style AnalogClockFaceStyle { get => (Style) GetValue(AnalogTimePicker.AnalogClockFaceStyleProperty); set => SetValue(AnalogTimePicker.AnalogClockFaceStyleProperty, value); }
40-
41-
#endregion AnalogClockFaceStyle dependency property
42-
4331
#region ClockDiameter dependency property
4432

4533
public static readonly DependencyProperty ClockDiameterProperty = DependencyProperty.Register(
4634
"ClockDiameter",
4735
typeof(double),
4836
typeof(AnalogTimePicker),
49-
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange));
37+
new FrameworkPropertyMetadata(default(double), FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsArrange, AnalogTimePicker.OnClockDiameterChanged));
5038

5139
public double ClockDiameter { get => (double) GetValue(AnalogTimePicker.ClockDiameterProperty); set => SetValue(AnalogTimePicker.ClockDiameterProperty, value); }
5240

@@ -83,10 +71,9 @@ public AnalogTimePicker()
8371
/// <inheritdoc />
8472
protected override Size MeasureOverride(Size constraint)
8573
{
86-
constraint = new Size(this.ClockDiameter, this.ClockDiameter);
87-
this.AnalogClockFace.Diameter = this.ClockDiameter;
74+
//constraint = new Size(this.ClockDiameter, this.ClockDiameter);
8875
//this.AnalogClockFace.Measure(constraint);
89-
base.MeasureOverride(constraint);
76+
constraint = base.MeasureOverride(constraint);
9077
return constraint;
9178
}
9279

@@ -97,8 +84,29 @@ private static void OnAnalogClockFaceChanged(DependencyObject d, DependencyPrope
9784
(d as AnalogTimePicker).OnAnalogClockFaceChanged();
9885
}
9986

87+
private static void OnClockDiameterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
88+
{
89+
(d as AnalogTimePicker).OnClockDiameterChanged((double) e.OldValue, (double) e.NewValue);
90+
}
91+
92+
protected virtual void OnClockDiameterChanged(double oldValue, double newValue)
93+
{
94+
if (this.AnalogClockFace == null)
95+
{
96+
return;
97+
}
98+
this.AnalogClockFace.Width = newValue;
99+
this.AnalogClockFace.Height = newValue;
100+
}
101+
100102
protected virtual void OnAnalogClockFaceChanged()
101103
{
104+
if (this.AnalogClockFace == null)
105+
{
106+
return;
107+
}
108+
this.AnalogClockFace.Width = this.ClockDiameter;
109+
this.AnalogClockFace.Height = this.ClockDiameter;
102110
// this.AnalogClockFace.ClockFaceLoaded += OnClockFaceLoaded;
103111
}
104112

BionicCode.Net/BionicCode.Controls.Net.Core.Wpf/BionicCode.Controls.Net.Core.Wpf.xml

Lines changed: 9 additions & 30 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#region Info
2+
3+
// 2021/01/10 19:28
4+
// BionicCode.Controls.Net.Core.Wpf
5+
6+
#endregion
7+
8+
using System;
9+
using System.Globalization;
10+
using System.Windows.Data;
11+
12+
namespace BionicCode.Controls.Net.Core.Wpf.Converters
13+
{
14+
public class DiameterToRadiusConverter : IValueConverter
15+
{
16+
#region Implementation of IValueConverter
17+
18+
/// <inheritdoc />
19+
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) => value is double doubleValue ? doubleValue / 2 : value is string stringValue && double.TryParse(stringValue, out doubleValue) ? doubleValue / 2 : Binding.DoNothing;
20+
21+
/// <inheritdoc />
22+
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) => value is double doubleValue ? doubleValue * 2 : value is string stringValue && double.TryParse(stringValue, out doubleValue) ? doubleValue * 2 : Binding.DoNothing;
23+
24+
#endregion
25+
}
26+
}

BionicCode.Net/BionicCode.Controls.Net.Core.Wpf/Themes/AnalogClockFaceStyle.xaml

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,33 +8,38 @@
88
<converter:DividerValueConverter x:Key="DividerValueConverter" />
99

1010
<Style TargetType="wpf:AnalogClockFace">
11-
<Setter Property="SelectedHour" Value="400.5"/>
11+
<Setter Property="Background" Value="Transparent" />
12+
<Setter Property="FontSize" Value="16" />
13+
<Setter Property="FontStretch" Value="UltraExpanded" />
14+
<Setter Property="FontWeight" Value="UltraLight" />
15+
<Setter Property="Foreground" Value="{StaticResource ApplicationWhiteBrush}" />
16+
<Setter Property="SelectedHour" Value="3.0042"/>
1217
<Setter Property="HourHandElement">
1318
<Setter.Value>
14-
<Line X1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
15-
Y1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
16-
X2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
17-
Y2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius, Converter={StaticResource DividerValueConverter}, ConverterParameter=3}"
19+
<Line X1="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
20+
Y1="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
21+
X2="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
22+
Y2="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=12}"
1823
Stroke="{StaticResource ApplicationWhiteBrush}"
1924
StrokeThickness="3"/>
2025
</Setter.Value>
2126
</Setter>
2227
<Setter Property="MinuteHandElement">
2328
<Setter.Value>
24-
<Line X1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
25-
Y1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
26-
X2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
27-
Y2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius, Converter={StaticResource DividerValueConverter}, ConverterParameter=16}"
29+
<Line X1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
30+
Y1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
31+
X2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
32+
Y2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=28}"
2833
Stroke="{StaticResource ApplicationWhiteBrush}"
2934
StrokeThickness="3"/>
3035
</Setter.Value>
3136
</Setter>
3237
<Setter Property="SecondHandElement">
3338
<Setter.Value>
34-
<Line X1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
35-
Y1="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
36-
X2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius}"
37-
Y2="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Radius, Converter={StaticResource DividerValueConverter}, ConverterParameter=16}"
39+
<Line X1="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth}"
40+
Y1="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
41+
X2="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=2}"
42+
Y2="{Binding RelativeSource={RelativeSource AncestorType=Canvas}, Path=ActualWidth, Converter={StaticResource DividerValueConverter}, ConverterParameter=28}"
3843
Stroke="{StaticResource ApplicationWhiteBrush}"
3944
StrokeThickness="1"/>
4045
</Setter.Value>
@@ -46,14 +51,26 @@
4651
</Setter>
4752
<Setter Property="FiveMinuteIntervalElement">
4853
<Setter.Value>
49-
<Ellipse Height="4" Width="4" Fill="{StaticResource ApplicationWhiteBrush}"/>
54+
<Rectangle Height="8" Width="2" Fill="{StaticResource ApplicationWhiteBrush}"
55+
wpf:AnalogClockFace.IsCenterElementOnCircumferenceEnabled="False" />
5056
</Setter.Value>
5157
</Setter>
5258
<Setter Property="MinuteIntervalElement">
5359
<Setter.Value>
5460
<Ellipse Height="2" Width="2" Fill="{StaticResource ApplicationWhiteBrush}"/>
5561
</Setter.Value>
5662
</Setter>
63+
<Setter Property="Template">
64+
<Setter.Value>
65+
<ControlTemplate TargetType="wpf:AnalogClockFace">
66+
<Border Background="{TemplateBinding Background}"
67+
BorderBrush="{TemplateBinding BorderBrush}"
68+
BorderThickness="{TemplateBinding BorderThickness}">
69+
<Border x:Name="PART_ElementHost" />
70+
</Border>
71+
</ControlTemplate>
72+
</Setter.Value>
73+
</Setter>
5774
</Style>
5875

5976
</ResourceDictionary>

BionicCode.Net/BionicCode.Controls.Net.Core.Wpf/Themes/AnalogTimePickerStyle.xaml

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,7 @@
1313
<Setter Property="ClockDiameter" Value="400"/>
1414
<Setter Property="AnalogClockFace">
1515
<Setter.Value>
16-
<wpf:AnalogClockFace>
17-
<!--<wpf:AnalogClockFace.MinuteIntervalElement>
18-
<Ellipse Height="2" Width="2" Fill="{StaticResource ApplicationWhiteBrush}"/>
19-
</wpf:AnalogClockFace.MinuteIntervalElement>
20-
<wpf:AnalogClockFace.FiveMinuteIntervalElement>
21-
<Ellipse Height="4" Width="4" Fill="{StaticResource ApplicationWhiteBrush}"/>
22-
</wpf:AnalogClockFace.FiveMinuteIntervalElement>
23-
<wpf:AnalogClockFace.FifteenMinuteIntervalElement>
24-
<Ellipse Height="8" Width="8" Fill="{StaticResource ApplicationWhiteBrush}"/>
25-
</wpf:AnalogClockFace.FifteenMinuteIntervalElement>-->
26-
</wpf:AnalogClockFace>
16+
<wpf:AnalogClockFace />
2717
</Setter.Value>
2818
</Setter>
2919
<Setter Property="Template">

BionicCode.Net/BionicCode.Utilities.Net.Core.Wpf/Converter/DividerValueConverter.cs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,15 @@ public object ConvertBack(object value, Type targetType, object parameter, Cultu
3636
return Binding.DoNothing;
3737
}
3838

39-
double multiplier = 1;
40-
41-
if (parameter != null)
42-
{
43-
multiplier = ((double)parameter).Equals(0) ? 1 : (double)parameter;
44-
}
39+
double divisor = parameter is double doubleValue
40+
? doubleValue.Equals(0)
41+
? 1
42+
: doubleValue
43+
: parameter is string stringValue && double.TryParse(stringValue, out doubleValue)
44+
? doubleValue
45+
: 1;
4546

46-
return (double)value * multiplier;
47+
return (double)value * divisor;
4748
}
4849

4950
#endregion

0 commit comments

Comments
 (0)