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 ae7e024

Browse files
authored
Merge pull request #211 from reactivemarbles/AddNewControlsToAvaloniaUI
Revamp CircularGauge visuals and properties
2 parents 12d095f + 9dcd8dd commit ae7e024

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)