add HoneycombPanel

This commit is contained in:
NaBian committed 2019-08-10 21:24:37 +08:00
1 parent 9856ff1225
commit 9c4fb33c55
29 files changed
+327 -33

No files matched your search

@@ -0,0 +1,166 @@
using System;
using System.Windows;
using System.Windows.Controls;
namespace HandyControl.Controls
{
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 base.ArrangeOverride(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;
}
}
}
}