using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using HandyControl.Data; namespace HandyControl.Controls; public class CirclePanel : Panel { public static readonly DependencyProperty DiameterProperty = DependencyProperty.Register( nameof(Diameter), typeof(double), typeof(CirclePanel), new FrameworkPropertyMetadata(170.0, FrameworkPropertyMetadataOptions.AffectsMeasure)); public double Diameter { get => (double) GetValue(DiameterProperty); set => SetValue(DiameterProperty, value); } public static readonly DependencyProperty KeepVerticalProperty = DependencyProperty.Register( nameof(KeepVertical), typeof(bool), typeof(CirclePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsMeasure)); public bool KeepVertical { get => (bool) GetValue(KeepVerticalProperty); set => SetValue(KeepVerticalProperty, ValueBoxes.BooleanBox(value)); } public static readonly DependencyProperty OffsetAngleProperty = DependencyProperty.Register( nameof(OffsetAngle), typeof(double), typeof(CirclePanel), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsMeasure)); public double OffsetAngle { get => (double) GetValue(OffsetAngleProperty); set => SetValue(OffsetAngleProperty, value); } protected override Size MeasureOverride(Size availableSize) { var diameter = Diameter; if (Children.Count == 0) return new Size(diameter, diameter); var newSize = new Size(diameter, diameter); foreach (UIElement element in Children) { element.Measure(newSize); } return newSize; } protected override Size ArrangeOverride(Size finalSize) { var keepVertical = KeepVertical; var offsetAngle = OffsetAngle; var i = 0; var perDeg = 360.0 / Children.Count; var radius = Diameter / 2; foreach (UIElement element in Children) { var centerX = element.DesiredSize.Width / 2.0; var centerY = element.DesiredSize.Height / 2.0; var angle = perDeg * i++ + offsetAngle; var transform = new RotateTransform { CenterX = centerX, CenterY = centerY, Angle = keepVertical ? 0 : angle }; element.RenderTransform = transform; var r = Math.PI * angle / 180.0; var x = radius * Math.Cos(r); var y = radius * Math.Sin(r); var rectX = x + finalSize.Width / 2 - centerX; var rectY = y + finalSize.Height / 2 - centerY; element.Arrange(new Rect(rectX, rectY, element.DesiredSize.Width, element.DesiredSize.Height)); } return finalSize; } }