|
- using System;
- using System.Windows;
- using System.Windows.Controls;
-
-
- namespace BPASmartClient.SCADAControl.Converters
- {
- public class HoneycombPanel : Panel
- {
- private double _unitLength;
-
- private HoneycombStuffer _stuffer;
-
- private static int GetXCount(int count)
- {
- if (count == 0) return 0;
-
- count -= 1;
-
- var index = (int)Math.Floor(Math.Pow((12.0 * count + 25) / 36, 0.5) - 5.0 / 6);
- var valeIndex = 3 * index * index + 5 * index;
- var centerValue = valeIndex + 2;
-
- return count >= centerValue
- ? 4 * index + 6
- : count > valeIndex
- ? 4 * index + 4
- : 4 * index + 2;
- }
-
- private static int GetYCount(int count)
- {
- if (count == 0) return 0;
-
- count -= 1;
-
- var index = (int)Math.Floor(Math.Pow(count / 3.0 + 0.25, 0.5) - 0.5);
- var valeIndex = 3 * index * index + 3 * index;
-
- return count > valeIndex
- ? 2 * index + 2
- : 2 * index;
- }
-
- /*
- * layout order
- *
- * ● ●
- * (7) (8)
- *
- * ● ● ●
- * (6) (1) (9)
- *
- * ● ● ● ...
- * (5) (0) (2)
- *
- * ● ● ...
- * (4) (3)
- *
- */
- protected override Size MeasureOverride(Size availableSize)
- {
- var maxSize = new Size();
-
- foreach (UIElement child in InternalChildren)
- {
- if (child != null)
- {
- child.Measure(availableSize);
- maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
- maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
- }
- }
-
- _unitLength = Math.Max(maxSize.Width, maxSize.Height) / 2;
-
- var xCount = GetXCount(InternalChildren.Count);
- var yCount = GetYCount(InternalChildren.Count);
-
- var availableWidth = xCount * _unitLength;
- var availableHeight = yCount * Math.Pow(3, 0.5) * _unitLength + _unitLength * 2;
-
- return new Size(availableWidth, availableHeight);
- }
-
- protected override Size ArrangeOverride(Size finalSize)
- {
- var childLength = _unitLength * 2;
- _stuffer = new HoneycombStuffer(new Rect(finalSize.Width / 2 - _unitLength,
- finalSize.Height / 2 - _unitLength, childLength, childLength));
-
- foreach (UIElement child in InternalChildren)
- {
- child.Arrange(_stuffer.Move());
- }
-
- return finalSize;
- }
-
- private class HoneycombStuffer
- {
- private int _turns;
-
- private int _maxIndex;
-
- private int _currentIndex = -1;
-
- private readonly double _offsetX;
-
- private readonly double _offsetY;
-
- private Rect _childBounds;
-
- private readonly double[] _offsetXArr;
-
- private readonly double[] _offsetYArr;
-
- public HoneycombStuffer(Rect childBounds)
- {
- _childBounds = childBounds;
- _offsetX = childBounds.Width / 2;
- _offsetY = Math.Pow(3, 0.5) * _offsetX;
-
- _offsetXArr = new[]
- {
- 2 * _offsetX,
- _offsetX,
- -_offsetX,
- -2 * _offsetX,
- -_offsetX,
- _offsetX
- };
-
- _offsetYArr = new[]
- {
- 0,
- _offsetY,
- _offsetY,
- 0,
- -_offsetY,
- -_offsetY
- };
- }
-
- public Rect Move()
- {
- _currentIndex++;
- if (_currentIndex > _maxIndex)
- {
- _turns++;
- _maxIndex = _turns * 6 - 1;
- _currentIndex = 0;
- _childBounds.Offset(_offsetX, -_offsetY);
- return _childBounds;
- }
-
- if (_turns > 0)
- {
- var index = _currentIndex / _turns;
- _childBounds.Offset(_offsetXArr[index], _offsetYArr[index]);
- }
-
- return _childBounds;
- }
- }
- }
- }
|