WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 9dcd8dd

Browse files
committed
Revamp CircularGauge visuals and properties
Updated default values for angles, colors, and pointer cap radius in CircularGauge. Added ScaleRadius and ScaleLabelRadius properties for improved layout control. Refactored scale drawing logic for fixed center and consistent tick/label placement. Overhauled CircularGauge.axaml template for a more modern, visually rich gauge appearance, including metallic frame, glass overlay, and improved pointer rendering.
1 parent 14b9892 commit 9dcd8dd

File tree

2 files changed

+185
-90
lines changed

2 files changed

+185
-90
lines changed

src/CrissCross.Avalonia.UI/Controls/Gauges/CircularGauge.cs

Lines changed: 63 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ public class CircularGauge : TemplatedControl
4343
/// Property for <see cref="ScaleStartAngle"/>.
4444
/// </summary>
4545
public static readonly StyledProperty<double> ScaleStartAngleProperty =
46-
AvaloniaProperty.Register<CircularGauge, double>(nameof(ScaleStartAngle), 135.0);
46+
AvaloniaProperty.Register<CircularGauge, double>(nameof(ScaleStartAngle), 120.0);
4747

4848
/// <summary>
4949
/// Property for <see cref="ScaleSweepAngle"/>.
5050
/// </summary>
5151
public static readonly StyledProperty<double> ScaleSweepAngleProperty =
52-
AvaloniaProperty.Register<CircularGauge, double>(nameof(ScaleSweepAngle), 270.0);
52+
AvaloniaProperty.Register<CircularGauge, double>(nameof(ScaleSweepAngle), 300.0);
5353

5454
/// <summary>
5555
/// Property for <see cref="MajorDivisionsCount"/>.
@@ -73,7 +73,7 @@ public class CircularGauge : TemplatedControl
7373
/// Property for <see cref="PointerCapRadius"/>.
7474
/// </summary>
7575
public static readonly StyledProperty<double> PointerCapRadiusProperty =
76-
AvaloniaProperty.Register<CircularGauge, double>(nameof(PointerCapRadius), 10.0);
76+
AvaloniaProperty.Register<CircularGauge, double>(nameof(PointerCapRadius), 16.0);
7777

7878
/// <summary>
7979
/// Property for <see cref="PointerColor"/>.
@@ -85,25 +85,25 @@ public class CircularGauge : TemplatedControl
8585
/// Property for <see cref="ScaleColor"/>.
8686
/// </summary>
8787
public static readonly StyledProperty<IBrush> ScaleColorProperty =
88-
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(ScaleColor), Brushes.Gray);
88+
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(ScaleColor), Brushes.White);
8989

9090
/// <summary>
9191
/// Property for <see cref="OptimalRangeColor"/>.
9292
/// </summary>
9393
public static readonly StyledProperty<IBrush> OptimalRangeColorProperty =
94-
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(OptimalRangeColor), Brushes.Green);
94+
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(OptimalRangeColor), Brushes.Transparent);
9595

9696
/// <summary>
9797
/// Property for <see cref="BelowOptimalRangeColor"/>.
9898
/// </summary>
9999
public static readonly StyledProperty<IBrush> BelowOptimalRangeColorProperty =
100-
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(BelowOptimalRangeColor), Brushes.Yellow);
100+
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(BelowOptimalRangeColor), Brushes.Transparent);
101101

102102
/// <summary>
103103
/// Property for <see cref="AboveOptimalRangeColor"/>.
104104
/// </summary>
105105
public static readonly StyledProperty<IBrush> AboveOptimalRangeColorProperty =
106-
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(AboveOptimalRangeColor), Brushes.Red);
106+
AvaloniaProperty.Register<CircularGauge, IBrush>(nameof(AboveOptimalRangeColor), Brushes.Transparent);
107107

108108
/// <summary>
109109
/// Property for <see cref="OptimalRangeStartValue"/>.
@@ -145,9 +145,22 @@ public class CircularGauge : TemplatedControl
145145
/// Property for <see cref="PointerAngle"/>.
146146
/// </summary>
147147
public static readonly StyledProperty<double> PointerAngleProperty =
148-
AvaloniaProperty.Register<CircularGauge, double>(nameof(PointerAngle), 135.0);
148+
AvaloniaProperty.Register<CircularGauge, double>(nameof(PointerAngle), 120.0);
149+
150+
/// <summary>
151+
/// Property for <see cref="ScaleRadius"/>.
152+
/// </summary>
153+
public static readonly StyledProperty<double> ScaleRadiusProperty =
154+
AvaloniaProperty.Register<CircularGauge, double>(nameof(ScaleRadius), 75.0);
155+
156+
/// <summary>
157+
/// Property for <see cref="ScaleLabelRadius"/>.
158+
/// </summary>
159+
public static readonly StyledProperty<double> ScaleLabelRadiusProperty =
160+
AvaloniaProperty.Register<CircularGauge, double>(nameof(ScaleLabelRadius), 60.0);
149161

150162
private Canvas? _scaleCanvas;
163+
private double _oldValueAngle;
151164

152165
static CircularGauge()
153166
{
@@ -158,8 +171,9 @@ static CircularGauge()
158171
MinorDivisionsCountProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
159172
ScaleStartAngleProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
160173
ScaleSweepAngleProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
161-
RadiusProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
162-
BoundsProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
174+
ScaleRadiusProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
175+
ScaleLabelRadiusProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
176+
ScaleColorProperty.Changed.AddClassHandler<CircularGauge>((x, _) => x.RedrawScale());
163177
}
164178

165179
/// <summary>
@@ -360,6 +374,24 @@ public double PointerAngle
360374
set => SetValue(PointerAngleProperty, value);
361375
}
362376

377+
/// <summary>
378+
/// Gets or sets the scale radius.
379+
/// </summary>
380+
public double ScaleRadius
381+
{
382+
get => GetValue(ScaleRadiusProperty);
383+
set => SetValue(ScaleRadiusProperty, value);
384+
}
385+
386+
/// <summary>
387+
/// Gets or sets the scale label radius.
388+
/// </summary>
389+
public double ScaleLabelRadius
390+
{
391+
get => GetValue(ScaleLabelRadiusProperty);
392+
set => SetValue(ScaleLabelRadiusProperty, value);
393+
}
394+
363395
/// <inheritdoc/>
364396
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
365397
{
@@ -383,10 +415,9 @@ private void UpdatePointerAngle()
383415
}
384416

385417
var normalizedValue = (clampedValue - MinValue) / range;
418+
var newAngle = ScaleStartAngle + (normalizedValue * ScaleSweepAngle);
386419

387-
// Subtract 90 to convert from standard math angles (0=right) to screen angles (0=up)
388-
var newAngle = ScaleStartAngle + (normalizedValue * ScaleSweepAngle) - 90;
389-
420+
_oldValueAngle = PointerAngle;
390421
PointerAngle = newAngle;
391422
}
392423

@@ -398,36 +429,34 @@ private void RedrawScale()
398429

399430
private void DrawScale()
400431
{
401-
if (_scaleCanvas == null || Bounds.Width == 0 || Bounds.Height == 0)
432+
if (_scaleCanvas == null)
402433
{
403434
return;
404435
}
405436

406437
_scaleCanvas.Children.Clear();
407438

408-
// Use the actual bounds of the control for centering
409-
var centerX = Bounds.Width / 2;
410-
var centerY = Bounds.Height / 2;
411-
var actualRadius = Math.Min(centerX, centerY) - 10; // Leave margin for labels
412-
413-
var scaleRadius = actualRadius * 0.85;
414-
var majorTickLength = actualRadius * 0.12;
415-
var minorTickLength = actualRadius * 0.06;
439+
// Fixed center for the 200x200 canvas in the Viewbox
440+
const double centerX = 100;
441+
const double centerY = 100;
416442

417443
var majorTickUnitAngle = ScaleSweepAngle / MajorDivisionsCount;
418444
var majorTicksUnitValue = (MaxValue - MinValue) / MajorDivisionsCount;
419445

446+
var majorTickLength = 10.0;
447+
var minorTickLength = 5.0;
448+
420449
// Draw major and minor ticks
421450
for (var i = 0; i <= MajorDivisionsCount; i++)
422451
{
423452
var angle = ScaleStartAngle + (i * majorTickUnitAngle);
424453
var angleRadian = angle * Math.PI / 180;
425454

426-
// Major tick
427-
var startX = centerX + (scaleRadius * Math.Cos(angleRadian));
428-
var startY = centerY + (scaleRadius * Math.Sin(angleRadian));
429-
var endX = centerX + ((scaleRadius - majorTickLength) * Math.Cos(angleRadian));
430-
var endY = centerY + ((scaleRadius - majorTickLength) * Math.Sin(angleRadian));
455+
// Major tick - drawn as rotated rectangle centered at the tick position
456+
var startX = centerX + (ScaleRadius * Math.Cos(angleRadian));
457+
var startY = centerY + (ScaleRadius * Math.Sin(angleRadian));
458+
var endX = centerX + ((ScaleRadius - majorTickLength) * Math.Cos(angleRadian));
459+
var endY = centerY + ((ScaleRadius - majorTickLength) * Math.Sin(angleRadian));
431460

432461
var majorTick = new Line
433462
{
@@ -439,16 +468,17 @@ private void DrawScale()
439468
_scaleCanvas.Children.Add(majorTick);
440469

441470
// Scale label
442-
var labelRadius = scaleRadius - majorTickLength - 12;
471+
var labelRadius = ScaleLabelRadius;
443472
var labelX = centerX + (labelRadius * Math.Cos(angleRadian));
444473
var labelY = centerY + (labelRadius * Math.Sin(angleRadian));
445474

446475
var labelValue = MinValue + (i * majorTicksUnitValue);
447476
var label = new TextBlock
448477
{
449478
Text = labelValue.ToString($"F{Decimals}"),
450-
FontSize = 9,
479+
FontSize = 10,
451480
Foreground = ScaleColor,
481+
TextAlignment = TextAlignment.Center,
452482
};
453483

454484
// Offset label to center it on the position
@@ -465,10 +495,10 @@ private void DrawScale()
465495
var minorAngle = angle + (j * minorTickUnitAngle);
466496
var minorAngleRadian = minorAngle * Math.PI / 180;
467497

468-
var minorStartX = centerX + (scaleRadius * Math.Cos(minorAngleRadian));
469-
var minorStartY = centerY + (scaleRadius * Math.Sin(minorAngleRadian));
470-
var minorEndX = centerX + ((scaleRadius - minorTickLength) * Math.Cos(minorAngleRadian));
471-
var minorEndY = centerY + ((scaleRadius - minorTickLength) * Math.Sin(minorAngleRadian));
498+
var minorStartX = centerX + (ScaleRadius * Math.Cos(minorAngleRadian));
499+
var minorStartY = centerY + (ScaleRadius * Math.Sin(minorAngleRadian));
500+
var minorEndX = centerX + ((ScaleRadius - minorTickLength) * Math.Cos(minorAngleRadian));
501+
var minorEndY = centerY + ((ScaleRadius - minorTickLength) * Math.Sin(minorAngleRadian));
472502

473503
var minorTick = new Line
474504
{

0 commit comments

Comments
 (0)