windowsforms-115760-controls-and-libraries-treemap-layout-algorithms-examples-how-to-implement-a-custom-layout-algorithm.md
To implement a custom layout algorithm that can be used to place tree map items into a parent container and set their size, design a class implementing the ITreeMapLayoutAlgorithm interface and implement its ITreeMapLayoutAlgorithm.Calculate method.
using DevExpress.TreeMap;
using DevExpress.XtraTreeMap;
using System.Collections.Generic;
using System.Linq;
namespace CustomLayoutAlgorithmSample {
class CustomLayoutAlgorithm : ITreeMapLayoutAlgorithm, IComparer<ITreeMapItemLayout> {
public TreeMapLayoutDirection Direction {
get; set;
}
public event LayoutAlgorithmChangedEventHandler LayoutAlgorithmChanged;
public void Calculate(IEnumerable<ITreeMapItemLayout> items, double width, double height, int groupLevel) {
double unlayoutedItemsWeight = 0;
foreach(var item in items)
unlayoutedItemsWeight += item.Weight;
var sortedItems = items.ToList();
sortedItems.Sort(this);
TreeMapRect emptySpace = new TreeMapRect(0, 0, width, height);
foreach(var item in sortedItems) {
double itemWidth;
double itemHeight;
double newEmptySpaceX;
double newEmptySpaceY;
double newEmptySpaceWidth;
double newEmptySpaceHeight;
if(emptySpace.Width / emptySpace.Height > 1) {
itemWidth = emptySpace.Width * item.Weight / unlayoutedItemsWeight;
itemHeight = emptySpace.Height;
newEmptySpaceX = emptySpace.X + itemWidth;
newEmptySpaceY = emptySpace.Y;
newEmptySpaceHeight = emptySpace.Height;
newEmptySpaceWidth = emptySpace.Width - itemWidth;
newEmptySpaceWidth = newEmptySpaceWidth < 0 ? 0 : newEmptySpaceWidth;
}
else {
itemWidth = emptySpace.Width;
itemHeight = emptySpace.Height * item.Weight / unlayoutedItemsWeight;
newEmptySpaceX = emptySpace.X;
newEmptySpaceY = emptySpace.Y + itemHeight;
newEmptySpaceWidth = emptySpace.Width;
newEmptySpaceHeight = emptySpace.Height - itemHeight;
newEmptySpaceHeight = newEmptySpaceHeight < 0 ? 0 : newEmptySpaceHeight;
}
item.Layout = new TreeMapRect(emptySpace.X, emptySpace.Y, itemWidth, itemHeight);
emptySpace = new TreeMapRect(
newEmptySpaceX,
newEmptySpaceY,
newEmptySpaceWidth,
newEmptySpaceHeight);
unlayoutedItemsWeight -= item.Weight;
}
}
public int Compare(ITreeMapItemLayout x, ITreeMapItemLayout y) {
if(x.Weight > y.Weight) return -1;
else if(x.Weight < y.Weight) return 1;
else return 0;
}
}
}
using System;
using System.Windows.Forms;
namespace CustomLayoutAlgorithmSample {
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e) {
treeMap.LayoutAlgorithm = new CustomLayoutAlgorithm();
}
}
}
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Threading.Tasks
Imports System.Windows.Forms
Namespace CustomLayoutAlgorithmSample
Friend NotInheritable Class Program
Private Sub New()
End Sub
''' <summary>
''' The main entry point for the application.
''' </summary>
<STAThread> _
Shared Sub Main()
Application.EnableVisualStyles()
Application.SetCompatibleTextRenderingDefault(False)
Application.Run(New Form1())
End Sub
End Class
End Namespace
Imports DevExpress.TreeMap
Imports DevExpress.XtraTreeMap
Namespace CustomLayoutAlgorithmSample
Friend Class CustomLayoutAlgorithm
Implements ITreeMapLayoutAlgorithm, IComparer(Of ITreeMapItemLayout)
Public Property Direction() As TreeMapLayoutDirection
Public Event LayoutAlgorithmChanged As LayoutAlgorithmChangedEventHandler Implements ITreeMapLayoutAlgorithm.LayoutAlgorithmChanged
Public Sub Calculate(ByVal items As IEnumerable(Of ITreeMapItemLayout), ByVal width As Double, ByVal height As Double, ByVal groupLevel As Integer) Implements ITreeMapLayoutAlgorithm.Calculate
Dim unlayoutedItemsWeight As Double = 0
For Each item In items
unlayoutedItemsWeight += item.Weight
Next item
Dim sortedItems = items.ToList()
sortedItems.Sort(Me)
Dim emptySpace As New TreeMapRect(0, 0, width, height)
For Each item In sortedItems
Dim itemWidth As Double
Dim itemHeight As Double
Dim newEmptySpaceX As Double
Dim newEmptySpaceY As Double
Dim newEmptySpaceWidth As Double
Dim newEmptySpaceHeight As Double
If (emptySpace.Width > emptySpace.Height) Then
itemWidth = emptySpace.Width * item.Weight / unlayoutedItemsWeight
itemHeight = emptySpace.Height
newEmptySpaceX = emptySpace.X + itemWidth
newEmptySpaceY = emptySpace.Y
newEmptySpaceHeight = emptySpace.Height
newEmptySpaceWidth = emptySpace.Width - itemWidth
newEmptySpaceWidth = If(newEmptySpaceWidth < 0, 0, newEmptySpaceWidth)
Else
itemWidth = emptySpace.Width
itemHeight = emptySpace.Height * item.Weight / unlayoutedItemsWeight
newEmptySpaceX = emptySpace.X
newEmptySpaceY = emptySpace.Y + itemHeight
newEmptySpaceWidth = emptySpace.Width
newEmptySpaceHeight = emptySpace.Height - itemHeight
newEmptySpaceHeight = If(newEmptySpaceHeight < 0, 0, newEmptySpaceHeight)
End If
item.Layout = New TreeMapRect(emptySpace.X, emptySpace.Y, itemWidth, itemHeight)
emptySpace = New TreeMapRect(newEmptySpaceX, newEmptySpaceY, newEmptySpaceWidth, newEmptySpaceHeight)
unlayoutedItemsWeight -= item.Weight
Next item
End Sub
Public Function Compare(ByVal x As ITreeMapItemLayout, ByVal y As ITreeMapItemLayout) As Integer Implements IComparer(Of ITreeMapItemLayout).Compare
If x.Weight > y.Weight Then
Return -1
ElseIf x.Weight < y.Weight Then
Return 1
Else
Return 0
End If
End Function
End Class
End Namespace