using System.Reflection;
using System.Windows.Controls;
using System.Windows;
using Telerik.Windows.Controls.GridView;

namespace TextWrappingGridView
{
    /// <summary>
    /// Panel that enables content wrapping
    /// </summary>
    public class ColumnWrapPanel : Panel
    {
        GridViewCell parentCell = null;
        GridViewRow parentRow = null;
        Size lastFinalSize = Size.Empty;

        private void EnsureParents()
        {
            if (parentCell == null)
                parentCell = this.GetVisualParent<GridViewCell>();

            if (parentRow == null)
                parentRow = this.GetVisualParent<GridViewRow>();
        }

        private double GetActualAvailableWidth()
        {
            double actualAvailableWidth = 0.0;

            if (this.parentCell == null || this.parentRow == null)
                return actualAvailableWidth;

            var pixelWidthPropertyInfo = typeof(Telerik.Windows.Controls.GridViewColumn).GetProperty("PixelWidth", BindingFlags.NonPublic | BindingFlags.Instance);
            actualAvailableWidth = (double) pixelWidthPropertyInfo.GetValue(parentCell.DataColumn, null);

            return actualAvailableWidth;
        }

        protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
        {
            this.EnsureParents();

            double actualAvailableWidth = this.GetActualAvailableWidth();
            Size actualAvailableSize = new Size(actualAvailableWidth, availableSize.Height);
            Size size = new Size();

            foreach (UIElement item in this.InternalChildren)
            {
                item.Measure(actualAvailableSize);

                size.Width += item.DesiredSize.Width;
                size.Height += item.DesiredSize.Height;
            }

            return size;
        }

        protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
        {
            if (finalSize != this.lastFinalSize)
            {
                this.lastFinalSize = finalSize;
                this.InvalidateMeasure();
            }

            foreach (UIElement item in this.InternalChildren)
            {
                item.Arrange(new Rect(0, 0, finalSize.Width, finalSize.Height));
            }

            return new Size(finalSize.Width, finalSize.Height);
        }
    }
}
