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( "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( "KeepVertical", typeof(bool), typeof(CirclePanel), new FrameworkPropertyMetadata(ValueBoxes.FalseBox, FrameworkPropertyMetadataOptions.AffectsMeasure)); public bool KeepVertical { get => (bool) GetValue(KeepVerticalProperty); set => SetValue(KeepVerticalProperty, value); } public static readonly DependencyProperty OffsetAngleProperty = DependencyProperty.Register( "OffsetAngle", typeof(double), typeof(CirclePanel), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.AffectsMeasure)); public double OffsetAngle { get => (double) GetValue(OffsetAngleProperty); set => SetValue(OffsetAngleProperty, value); } // ReSharper disable once RedundantAssignment protected override Size MeasureOverride(Size availableSize) { if (Children.Count == 0) return new Size(Diameter, Diameter); availableSize = new Size(Diameter, Diameter); var i = 0; var perDeg = 360.0 / Children.Count; var radius = Diameter / 2; foreach (UIElement element in Children) { element.Measure(availableSize); 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 + availableSize.Width / 2 - centerX; var rectY = y + availableSize.Height / 2 - centerY; element.Arrange(new Rect(rectX, rectY, element.DesiredSize.Width, element.DesiredSize.Height)); } return availableSize; } } }