Skip to main content

DevExpress v24.2 Update — Your Feedback Matters

Our What's New in v24.2 webpage includes product-specific surveys. Your response to our survey questions will help us measure product satisfaction for features released in this major update and help us refine our plans for our next major release.

Take the survey Not interested

How to: Implement a Custom Layout Algorithm

  • 3 minutes to read

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;
        }

    }
}