Skip to content

Commit 5a827d2

Browse files
committed
Improve rendering performance of AnalogClockFace
1 parent 7dd10f4 commit 5a827d2

File tree

2 files changed

+98
-76
lines changed

2 files changed

+98
-76
lines changed

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

Lines changed: 48 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,7 @@ private void InitializeClockFaceCanvas()
611611
this.ClockFaceCanvas = new Canvas
612612
{
613613
RenderTransform = this.ClockFaceScaleTransform,
614-
Background = Brushes.PaleVioletRed,
614+
Background = Brushes.Transparent,
615615
Width = this.Diameter,
616616
Height = this.Diameter,
617617
HorizontalAlignment = HorizontalAlignment.Left,
@@ -889,6 +889,8 @@ protected virtual void OnSelectedMinuteChanged(double oldValue, double newValue)
889889
this.HourHandTransform.Angle = angle;
890890
}
891891

892+
DrawArcFromZeroToCurrent();
893+
892894
if (this.IsUpdatingSelectedTime)
893895
{
894896
return;
@@ -1124,6 +1126,35 @@ protected virtual void DrawAnalogClock()
11241126
return;
11251127
}
11261128

1129+
DrawIntervals();
1130+
DrawClockFaceBackground();
1131+
DrawSelectionArcs();
1132+
1133+
if (this.IsDisplayDateEnabled)
1134+
{
1135+
AddDateElement();
1136+
}
1137+
1138+
AddClockHands();
1139+
OnClockFaceLoaded();
1140+
}
1141+
1142+
private void DrawSelectionArcs()
1143+
{
1144+
if (!this.IsMinuteSelectionArcEnabled)
1145+
{
1146+
return;
1147+
}
1148+
1149+
AddElementToClockFace(
1150+
this.SelectedMinuteArcRectangle,
1151+
new Point(),
1152+
1);
1153+
DrawArcFromZeroToCurrent();
1154+
}
1155+
1156+
private void DrawIntervals()
1157+
{
11271158
double steps = 60.0;
11281159
double degreeOfStep = 360.0 / steps;
11291160
this.IntervalMarkerCenterRadius = -1;
@@ -1139,32 +1170,17 @@ protected virtual void DrawAnalogClock()
11391170

11401171
DrawIntervalMarker(degreesOfCurrentStep, intervalMarker);
11411172

1142-
if (this.IsDisplayIntervalLabelsEnabled)
1173+
if (!this.IsDisplayIntervalLabelsEnabled)
11431174
{
1144-
FrameworkElement intervalMarkerLabel = CreateIntervalLabel(step);
1145-
if (intervalMarkerLabel != null)
1146-
{
1147-
DrawIntervalLabel(degreesOfCurrentStep, intervalMarkerLabel);
1148-
}
1175+
continue;
11491176
}
1150-
}
11511177

1152-
DrawClockFaceBackground();
1153-
if (this.IsMinuteSelectionArcEnabled)
1154-
{
1155-
AddElementToClockFace(
1156-
this.SelectedMinuteArcRectangle,
1157-
new Point());
1158-
DrawArcFromZeroToCurrent();
1159-
}
1160-
1161-
if (this.IsDisplayDateEnabled)
1162-
{
1163-
AddDateElement();
1178+
FrameworkElement intervalMarkerLabel = CreateIntervalLabel(step);
1179+
if (intervalMarkerLabel != null)
1180+
{
1181+
DrawIntervalLabel(degreesOfCurrentStep, intervalMarkerLabel);
1182+
}
11641183
}
1165-
1166-
AddClockHands();
1167-
OnClockFaceLoaded();
11681184
}
11691185

11701186
protected virtual void DrawAnalog24Clock()
@@ -1261,7 +1277,7 @@ private void AddDateElement()
12611277
return;
12621278
}
12631279

1264-
AddElementToClockFace(this.DateElement, new Point(Canvas.GetLeft(this.DateElement), Canvas.GetTop(this.DateElement)));
1280+
AddElementToClockFace(this.DateElement, new Point(Canvas.GetLeft(this.DateElement), Canvas.GetTop(this.DateElement)), 2);
12651281
}
12661282

12671283
private void DrawClockFaceBackground()
@@ -1296,7 +1312,7 @@ private void DrawArcFromZeroToCurrent()
12961312
this.SelectedMinuteArcPoint,
12971313
this.SelectionArcSize,
12981314
0,
1299-
true,
1315+
this.IsLargeSelectionMinuteArc,
13001316
SweepDirection.Clockwise,
13011317
false)
13021318
},
@@ -1320,7 +1336,7 @@ private void DrawIntervalLabel(double degreesOfCurrentStep, FrameworkElement int
13201336
Point cartesianPoint;
13211337
cartesianPoint = GetCartesianPointOfStep(degreesOfCurrentStep, this.IntervalMarkerCenterRadius + this.IntervalLabelRadiusOffset);
13221338
AlignElementCenterPointToRadius(ref cartesianPoint, intervalMarkerLabel);
1323-
AddCartesianElementToClockFace(intervalMarkerLabel, cartesianPoint);
1339+
AddCartesianElementToClockFace(intervalMarkerLabel, cartesianPoint, 2);
13241340
}
13251341

13261342
private void DrawIntervalMarker(
@@ -1334,7 +1350,7 @@ private void DrawIntervalMarker(
13341350
AlignElementCenterPointToRadius(ref cartesianPoint, intervalMarker);
13351351
}
13361352

1337-
AddCartesianElementToClockFace(intervalMarker, cartesianPoint);
1353+
AddCartesianElementToClockFace(intervalMarker, cartesianPoint, 2);
13381354
}
13391355

13401356
private static void RotateIntervalMarker(double degreesOfCurrentStep, FrameworkElement intervalMarker)
@@ -1443,15 +1459,15 @@ private void AddClockHands()
14431459
{
14441460
if (this.HourHandElement != null)
14451461
{
1446-
AddElementToClockFace(this.HourHandElement, new Point(Canvas.GetLeft(this.HourHandElement), Canvas.GetTop(this.HourHandElement)), Panel.GetZIndex(this.HourHandElement) + 2);
1462+
AddElementToClockFace(this.HourHandElement, new Point(Canvas.GetLeft(this.HourHandElement), Canvas.GetTop(this.HourHandElement)), Panel.GetZIndex(this.HourHandElement) + 3);
14471463
}
14481464
if (this.MinuteHandElement != null)
14491465
{
1450-
AddElementToClockFace(this.MinuteHandElement, new Point(Canvas.GetLeft(this.MinuteHandElement), Canvas.GetTop(this.MinuteHandElement)), Panel.GetZIndex(this.MinuteHandElement) + 3);
1466+
AddElementToClockFace(this.MinuteHandElement, new Point(Canvas.GetLeft(this.MinuteHandElement), Canvas.GetTop(this.MinuteHandElement)), Panel.GetZIndex(this.MinuteHandElement) + 4);
14511467
}
14521468
if (this.SecondHandElement != null)
14531469
{
1454-
AddElementToClockFace(this.SecondHandElement, new Point(Canvas.GetLeft(this.SecondHandElement), Canvas.GetTop(this.SecondHandElement)), Panel.GetZIndex(this.SecondHandElement) + 4);
1470+
AddElementToClockFace(this.SecondHandElement, new Point(Canvas.GetLeft(this.SecondHandElement), Canvas.GetTop(this.SecondHandElement)), Panel.GetZIndex(this.SecondHandElement) + 5);
14551471
}
14561472
}
14571473

@@ -1485,10 +1501,10 @@ private Point GetCartesianPointOfStep(double degreesOfCurrentStep, double radius
14851501
return cartesianPoint;
14861502
}
14871503

1488-
public void AddCartesianElementToClockFace(FrameworkElement clockElement, Point cartesianPoint)
1504+
public void AddCartesianElementToClockFace(FrameworkElement clockElement, Point cartesianPoint, int zIndex = 1)
14891505
{
14901506
Point screenPoint = cartesianPoint.ToScreenPoint(this.Diameter);
1491-
AddElementToClockFace(clockElement, screenPoint);
1507+
AddElementToClockFace(clockElement, screenPoint, zIndex);
14921508
}
14931509

14941510
public void AddElementToClockFace(FrameworkElement clockElement, Point screenPoint, int zIndex = 1)

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

Lines changed: 50 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,24 @@
99
<converter:PercentageToPixelConverter x:Key="PercentageToPixelConverter" />
1010

1111
<Style TargetType="wpf:AnalogClockFace">
12-
<Setter Property="IsDisplayIntervalLabelsEnabled" Value="True"/>
13-
<Setter Property="Is24HModeEnabled" Value="False"/>
14-
<Setter Property="IsDisplayDateEnabled" Value="True"/>
15-
<Setter Property="IsMinuteSelectionArcEnabled" Value="True"/>
12+
<Setter Property="IsDisplayIntervalLabelsEnabled" Value="True" />
13+
<Setter Property="Is24HModeEnabled" Value="False" />
14+
<Setter Property="IsDisplayDateEnabled" Value="True" />
15+
<Setter Property="IsMinuteSelectionArcEnabled" Value="True" />
1616

17-
<Setter Property="MinuteHandRadius" Value="{Binding RelativeSource={RelativeSource Self}, Path=Diameter, Converter={StaticResource PercentageToPixelConverter}, ConverterParameter=35}"/>
18-
<Setter Property="SecondHandRadius" Value="{Binding RelativeSource={RelativeSource Self}, Path=Diameter, Converter={StaticResource PercentageToPixelConverter}, ConverterParameter=23}"/>
17+
<Setter Property="MinuteHandRadius"
18+
Value="{Binding RelativeSource={RelativeSource Self}, Path=Diameter, Converter={StaticResource PercentageToPixelConverter}, ConverterParameter=35}" />
19+
<Setter Property="SecondHandRadius"
20+
Value="{Binding RelativeSource={RelativeSource Self}, Path=Diameter, Converter={StaticResource PercentageToPixelConverter}, ConverterParameter=23}" />
1921
<!--<Setter Property="Diameter" Value="100"/>-->
20-
<Setter Property="HourHandRadius" Value="200"/>
22+
<Setter Property="HourHandRadius" Value="200" />
2123
<!--<Setter Property="SelectedHour" Value="3"/>
2224
<Setter Property="SelectedMinute" Value="50"/>
2325
<Setter Property="SelectedSecond" Value="30"/>-->
2426
<Setter Property="IntervalLabelRadiusOffset" Value="-11" />
2527
<Setter Property="MinuteSelectionArcBrush">
2628
<Setter.Value>
27-
<SolidColorBrush Color="DodgerBlue" Opacity="0.6"/>
29+
<SolidColorBrush Color="DodgerBlue" Opacity="0.6" />
2830
</Setter.Value>
2931
</Setter>
3032
<Setter Property="Background" Value="Transparent" />
@@ -35,23 +37,30 @@
3537
<Setter Property="DateElement">
3638
<Setter.Value>
3739
<StackPanel Canvas.Left="62" Canvas.Top="45">
38-
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=SelectedTime.Date.DayOfWeek}"
39-
Foreground="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}"
40-
Padding="0"
41-
FontSize="4"/>
42-
<Line X1="0" Y1="0" X2="19" Y2="0" Stroke="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}" StrokeThickness="0.5"/>
40+
<TextBlock
41+
Text="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=SelectedTime.Date.DayOfWeek}"
42+
Foreground="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}"
43+
Padding="0"
44+
FontSize="4" />
45+
<Line X1="0" Y1="0" X2="19" Y2="0"
46+
Stroke="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}"
47+
StrokeThickness="0.5" />
4348
<StackPanel Orientation="Horizontal" Margin="0,1,0,0">
44-
<TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=SelectedTime.Date.Day}"
45-
Background="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}" Foreground="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Background}"
46-
Padding="2,0"
47-
FontWeight="ExtraBold"
48-
FontSize="4"/>
49-
<Border BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}" BorderThickness="0.5">
49+
<TextBlock
50+
Text="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=SelectedTime.Date.Day}"
51+
Background="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}"
52+
Foreground="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Background}"
53+
Padding="2,0"
54+
FontWeight="ExtraBold"
55+
FontSize="4" />
56+
<Border
57+
BorderBrush="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}"
58+
BorderThickness="0.5">
5059
<TextBlock
5160
Text="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=SelectedTime.Date, StringFormat='{}{0:MMM}'}"
5261
Background="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Background}"
5362
Foreground="{Binding RelativeSource={RelativeSource AncestorType=wpf:AnalogClockFace}, Path=Foreground}"
54-
Padding="2,0" FontSize="4"/>
63+
Padding="2,0" FontSize="4" />
5564
</Border>
5665
</StackPanel>
5766
</StackPanel>
@@ -74,91 +83,88 @@
7483
</Setter>
7584
<Setter Property="HourHandElement">
7685
<Setter.Value>
77-
<Line Panel.ZIndex="0"
78-
X1="50"
86+
<Line X1="50"
7987
Y1="62"
8088
X2="50"
8189
Y2="20"
8290
Stroke="AntiqueWhite"
83-
StrokeThickness="1" >
91+
StrokeThickness="1">
8492
<Line.Effect>
85-
<DropShadowEffect Opacity="1" RenderingBias="Quality" ShadowDepth="3"/>
93+
<DropShadowEffect Opacity="1" RenderingBias="Quality" ShadowDepth="3" />
8694
</Line.Effect>
8795
</Line>
8896

8997
</Setter.Value>
9098
</Setter>
9199
<Setter Property="MinuteHandElement">
92100
<Setter.Value>
93-
<Line Panel.ZIndex="1"
94-
X1="50"
101+
<Line X1="50"
95102
Y1="62"
96103
X2="50"
97104
Y2="8"
98105
Stroke="AntiqueWhite"
99-
StrokeThickness="1" >
106+
StrokeThickness="1">
100107
<Line.Effect>
101-
<DropShadowEffect Opacity="1" RenderingBias="Quality" ShadowDepth="3"/>
108+
<DropShadowEffect Opacity="1" RenderingBias="Quality" ShadowDepth="3" />
102109
</Line.Effect>
103110
</Line>
104111
</Setter.Value>
105112
</Setter>
106113
<Setter Property="SecondHandElement">
107114
<Setter.Value>
108-
<Canvas Canvas.Left="0" Canvas.Top="0"
109-
Panel.ZIndex="2" Background="Aqua">
110-
<Line
111-
X1="50"
115+
<Canvas>
116+
<Line X1="50"
112117
Y1="62"
113118
X2="50"
114119
Y2="8"
115120
Stroke="DarkRed"
116-
StrokeThickness="0.5" >
121+
StrokeThickness="0.5">
117122
<Line.Effect>
118-
<DropShadowEffect Opacity="1" RenderingBias="Quality" ShadowDepth="3"/>
123+
<DropShadowEffect Opacity="1" RenderingBias="Quality" ShadowDepth="3" />
119124
</Line.Effect>
120125
</Line>
121-
<Ellipse Height="4"
122-
Width="4"
123-
Fill="AntiqueWhite"
124-
Canvas.Left="48"
126+
<Ellipse Height="4"
127+
Width="4"
128+
Fill="AntiqueWhite"
129+
Canvas.Left="48"
125130
Canvas.Top="48" Panel.ZIndex="2">
126131
<Ellipse.Effect>
127-
<DropShadowEffect Opacity="0.8" RenderingBias="Quality" ShadowDepth="3"/>
132+
<DropShadowEffect Opacity="0.7" RenderingBias="Quality" ShadowDepth="3" />
128133
</Ellipse.Effect>
129134
</Ellipse>
130135
</Canvas>
131136
</Setter.Value>
132137
</Setter>
133138
<Setter Property="FifteenMinuteIntervalElement">
134139
<Setter.Value>
135-
<Rectangle Height="4" Width="0.5" Fill="AntiqueWhite"
140+
<Rectangle Height="4" Width="0.5" Fill="AntiqueWhite"
136141
wpf:AnalogClockFace.IsCenterElementOnCircumferenceEnabled="False" />
137142
</Setter.Value>
138143
</Setter>
139144
<Setter Property="FiveMinuteIntervalElement">
140145
<Setter.Value>
141-
<Rectangle Height="4" Width="0.5" Fill="AntiqueWhite"
146+
<Rectangle Height="4" Width="0.5" Fill="AntiqueWhite"
142147
wpf:AnalogClockFace.IsCenterElementOnCircumferenceEnabled="False" />
143148
</Setter.Value>
144149
</Setter>
145150
<Setter Property="MinuteIntervalElement">
146151
<Setter.Value>
147-
<Ellipse Height="1" Width="1" Fill="AntiqueWhite"/>
152+
<Ellipse Height="1" Width="1" Fill="AntiqueWhite" />
148153
</Setter.Value>
149154
</Setter>
150155
<Setter Property="Template">
151156
<Setter.Value>
152157
<ControlTemplate TargetType="wpf:AnalogClockFace">
153-
<Border>
158+
<Border BorderBrush="{TemplateBinding BorderBrush}"
159+
BorderThickness="{TemplateBinding BorderThickness}">
154160
<ContentPresenter />
155161
</Border>
156162
</ControlTemplate>
157163
</Setter.Value>
158164
</Setter>
159165
</Style>
160166

161-
<!--<Style TargetType="clock:AnalogClockFace">
167+
<!--<Style TargetType="clock:AnalogClockFace">
162168
<Setter Property="RenderOptions.BitmapScalingMode" Value="Fant" />
163169
--><!--<Setter Property="SnapsToDevicePixels" Value="True" />-->
164170
<!--<Setter Property="UseLayoutRounding" Value="True" />--><!--

0 commit comments

Comments
 (0)