add HoneycombPanel
This commit is contained in:
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user