终端一体化运控平台
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

168 lines
4.6 KiB

  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. namespace BPASmartClient.SCADAControl.Converters
  5. {
  6. public class HoneycombPanel : Panel
  7. {
  8. private double _unitLength;
  9. private HoneycombStuffer _stuffer;
  10. private static int GetXCount(int count)
  11. {
  12. if (count == 0) return 0;
  13. count -= 1;
  14. var index = (int)Math.Floor(Math.Pow((12.0 * count + 25) / 36, 0.5) - 5.0 / 6);
  15. var valeIndex = 3 * index * index + 5 * index;
  16. var centerValue = valeIndex + 2;
  17. return count >= centerValue
  18. ? 4 * index + 6
  19. : count > valeIndex
  20. ? 4 * index + 4
  21. : 4 * index + 2;
  22. }
  23. private static int GetYCount(int count)
  24. {
  25. if (count == 0) return 0;
  26. count -= 1;
  27. var index = (int)Math.Floor(Math.Pow(count / 3.0 + 0.25, 0.5) - 0.5);
  28. var valeIndex = 3 * index * index + 3 * index;
  29. return count > valeIndex
  30. ? 2 * index + 2
  31. : 2 * index;
  32. }
  33. /*
  34. * layout order
  35. *
  36. * ● ●
  37. * (7) (8)
  38. *
  39. * ● ● ●
  40. * (6) (1) (9)
  41. *
  42. * ● ● ● ...
  43. * (5) (0) (2)
  44. *
  45. * ● ● ...
  46. * (4) (3)
  47. *
  48. */
  49. protected override Size MeasureOverride(Size availableSize)
  50. {
  51. var maxSize = new Size();
  52. foreach (UIElement child in InternalChildren)
  53. {
  54. if (child != null)
  55. {
  56. child.Measure(availableSize);
  57. maxSize.Width = Math.Max(maxSize.Width, child.DesiredSize.Width);
  58. maxSize.Height = Math.Max(maxSize.Height, child.DesiredSize.Height);
  59. }
  60. }
  61. _unitLength = Math.Max(maxSize.Width, maxSize.Height) / 2;
  62. var xCount = GetXCount(InternalChildren.Count);
  63. var yCount = GetYCount(InternalChildren.Count);
  64. var availableWidth = xCount * _unitLength;
  65. var availableHeight = yCount * Math.Pow(3, 0.5) * _unitLength + _unitLength * 2;
  66. return new Size(availableWidth, availableHeight);
  67. }
  68. protected override Size ArrangeOverride(Size finalSize)
  69. {
  70. var childLength = _unitLength * 2;
  71. _stuffer = new HoneycombStuffer(new Rect(finalSize.Width / 2 - _unitLength,
  72. finalSize.Height / 2 - _unitLength, childLength, childLength));
  73. foreach (UIElement child in InternalChildren)
  74. {
  75. child.Arrange(_stuffer.Move());
  76. }
  77. return finalSize;
  78. }
  79. private class HoneycombStuffer
  80. {
  81. private int _turns;
  82. private int _maxIndex;
  83. private int _currentIndex = -1;
  84. private readonly double _offsetX;
  85. private readonly double _offsetY;
  86. private Rect _childBounds;
  87. private readonly double[] _offsetXArr;
  88. private readonly double[] _offsetYArr;
  89. public HoneycombStuffer(Rect childBounds)
  90. {
  91. _childBounds = childBounds;
  92. _offsetX = childBounds.Width / 2;
  93. _offsetY = Math.Pow(3, 0.5) * _offsetX;
  94. _offsetXArr = new[]
  95. {
  96. 2 * _offsetX,
  97. _offsetX,
  98. -_offsetX,
  99. -2 * _offsetX,
  100. -_offsetX,
  101. _offsetX
  102. };
  103. _offsetYArr = new[]
  104. {
  105. 0,
  106. _offsetY,
  107. _offsetY,
  108. 0,
  109. -_offsetY,
  110. -_offsetY
  111. };
  112. }
  113. public Rect Move()
  114. {
  115. _currentIndex++;
  116. if (_currentIndex > _maxIndex)
  117. {
  118. _turns++;
  119. _maxIndex = _turns * 6 - 1;
  120. _currentIndex = 0;
  121. _childBounds.Offset(_offsetX, -_offsetY);
  122. return _childBounds;
  123. }
  124. if (_turns > 0)
  125. {
  126. var index = _currentIndex / _turns;
  127. _childBounds.Offset(_offsetXArr[index], _offsetYArr[index]);
  128. }
  129. return _childBounds;
  130. }
  131. }
  132. }
  133. }