/// <summary>
        /// 子要素に必要なレイアウトのサイズを測定し、パネルのサイズを決定する。
        /// </summary>
        /// <param name="availableSize">子要素に与えることができる使用可能なサイズ。</param>
        /// <returns>レイアウト時にこのパネルが必要とするサイズ。</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
            var maxSize = default(Size);

            try
            {
                this.containerLayouts.Clear();

                var isAutoWidth    = double.IsNaN(this.ItemWidth);
                var isAutoHeight   = double.IsNaN(this.ItemHeight);
                var childAvailable = new Size(isAutoWidth
                                              ? double.PositiveInfinity
                                              : this.ItemWidth, isAutoHeight
                                                                ? double.PositiveInfinity
                                                                : this.ItemHeight);
                var isHorizontal = this.Orientation == Orientation.Horizontal;

                var childrenCount = this.InternalChildren.Count;

                var itemsControl = ItemsControl.GetItemsOwner(this);
                if (itemsControl != null)
                {
                    childrenCount = itemsControl.Items.Count;
                }

                var generator = new ChildGenerator(this);

                var x        = 0.0;
                var y        = 0.0;
                var lineSize = default(Size);

                for (int i = 0; i < childrenCount; i++)
                {
                    var childSize = this.ContainerSizeForIndex(i);

                    // ビューポートとの交差判定用に仮サイズで x, y を調整
                    var isWrapped = isHorizontal
                                    ? lineSize.Width + childSize.Width > availableSize.Width
                                    : lineSize.Height + childSize.Height > availableSize.Height;
                    if (isWrapped)
                    {
                        x = isHorizontal
                            ? 0
                            : x + lineSize.Width;
                        y = isHorizontal
                            ? y + lineSize.Height
                            : 0;
                    }

                    // 子要素がビューポート内であれば子要素を生成しサイズを再計測
                    var itemRect     = new Rect(x, y, childSize.Width, childSize.Height);
                    var viewportRect = new Rect(this.offset, availableSize);
                    if (itemRect.IntersectsWith(viewportRect))
                    {
                        var child = generator.GetOrCreateChild(i);
                        child.Measure(childAvailable);
                        childSize = this.ContainerSizeForIndex(i);
                    }

                    // 確定したサイズを記憶
                    this.containerLayouts[i] = new Rect(x, y, childSize.Width, childSize.Height);

                    // lineSize, maxSize を計算
                    isWrapped = isHorizontal
                                ? lineSize.Width + childSize.Width > availableSize.Width
                                : lineSize.Height + childSize.Height > availableSize.Height;
                    if (isWrapped)
                    {
                        maxSize.Width = isHorizontal
                                        ? Math.Max(lineSize.Width, maxSize.Width)
                                        : maxSize.Width + lineSize.Width;
                        maxSize.Height = isHorizontal
                                         ? maxSize.Height + lineSize.Height
                                         : Math.Max(lineSize.Height, maxSize.Height);
                        lineSize = childSize;

                        isWrapped = isHorizontal
                                    ? childSize.Width > availableSize.Width
                                    : childSize.Height > availableSize.Height;
                        if (isWrapped)
                        {
                            maxSize.Width = isHorizontal
                                            ? Math.Max(childSize.Width, maxSize.Width)
                                            : maxSize.Width + childSize.Width;
                            maxSize.Height = isHorizontal
                                             ? maxSize.Height + childSize.Height
                                             : Math.Max(childSize.Height, maxSize.Height);
                            lineSize = default(Size);
                        }
                    }
                    else
                    {
                        lineSize.Width = isHorizontal
                                         ? lineSize.Width + childSize.Width
                                         : Math.Max(childSize.Width, lineSize.Width);
                        lineSize.Height = isHorizontal
                                          ? Math.Max(childSize.Height, lineSize.Height)
                                          : lineSize.Height + childSize.Height;
                    }

                    x = isHorizontal
                        ? lineSize.Width
                        : maxSize.Width;
                    y = isHorizontal
                        ? maxSize.Height
                        : lineSize.Height;
                }

                maxSize.Width = isHorizontal
                                ? Math.Max(lineSize.Width, maxSize.Width)
                                : maxSize.Width + lineSize.Width;
                maxSize.Height = isHorizontal
                                 ? maxSize.Height + lineSize.Height
                                 : Math.Max(lineSize.Height, maxSize.Height);

                this.extent   = maxSize;
                this.viewport = availableSize;

                generator.CleanupChildren();
                generator?.Dispose();

                if (this.ScrollOwner != null)
                {
                    this.ScrollOwner.InvalidateScrollInfo();
                }
            }
            catch { }

            return(maxSize);
        }
示例#2
0
        protected override Size MeasureOverride(Size availableSize)
        {
            this.ContainerLayouts.Clear();

            var childAvailable = new Size(double.PositiveInfinity, double.PositiveInfinity);
            var childrenCount  = this.InternalChildren.Count;
            var itemsControl   = ItemsControl.GetItemsOwner(this);
            var x        = 0.0;
            var y        = 0.0;
            var lineSize = default(Size);
            var maxSize  = default(Size);

            if (itemsControl != null)
            {
                childrenCount = itemsControl.Items.Count;
            }

            using (var generator = new ChildGenerator(this))
            {
                for (var position = 0; position < childrenCount; position++)
                {
                    var childSize = this.ContainerSizeForIndex(position);
                    var isWrapped = lineSize.Width + childSize.Width > availableSize.Width;
                    if (isWrapped)
                    {
                        x = 0;
                        y = y + lineSize.Height;
                    }

                    var itemRect     = new Rect(x, y, childSize.Width, childSize.Height);
                    var viewportRect = new Rect(this.Offset, availableSize);
                    if (itemRect.IntersectsWith(viewportRect))
                    {
                        var child = generator.GetOrCreateChild(position);
                        if (child == null)
                        {
                            break;
                        }
                        child.Measure(childAvailable);
                        childSize = this.ContainerSizeForIndex(position);
                    }

                    this.ContainerLayouts[position] = new Rect(x, y, childSize.Width, childSize.Height);

                    isWrapped = lineSize.Width + childSize.Width > availableSize.Width;
                    if (isWrapped)
                    {
                        maxSize.Width  = Math.Max(lineSize.Width, maxSize.Width);
                        maxSize.Height = maxSize.Height + lineSize.Height;
                        lineSize       = childSize;

                        isWrapped = childSize.Width > availableSize.Width;
                        if (isWrapped)
                        {
                            maxSize.Width  = Math.Max(childSize.Width, maxSize.Width);
                            maxSize.Height = maxSize.Height + childSize.Height;
                            lineSize       = default(Size);
                        }
                    }
                    else
                    {
                        lineSize.Width  = lineSize.Width + childSize.Width;
                        lineSize.Height = Math.Max(childSize.Height, lineSize.Height);
                    }

                    x = lineSize.Width;
                    y = maxSize.Height;
                }

                maxSize.Width  = Math.Max(lineSize.Width, maxSize.Width);
                maxSize.Height = maxSize.Height + lineSize.Height;

                this.Extent   = maxSize;
                this.Viewport = availableSize;
            }

            if (this.ScrollOwner != null)
            {
                this.ScrollOwner.InvalidateScrollInfo();
            }

            return(maxSize);
        }
        /// <summary>
        /// 子要素に必要なレイアウトのサイズを測定し、パネルのサイズを決定する。
        /// </summary>
        /// <param name="availableSize">子要素に与えることができる使用可能なサイズ。</param>
        /// <returns>レイアウト時にこのパネルが必要とするサイズ。</returns>
        protected override Size MeasureOverride(Size availableSize)
        {
#if true
            //Debug.Assert(this.Orientation == Orientation.Horizontal);

            var isHorizontal = this.Orientation == Orientation.Horizontal;

            var maxSize = default(Size);
            if (GetLogicalWidth(availableSize) < 1) return maxSize;

            // ビューポートのサイズが変更された初期化
            var isChaigeViewPortSize = prevViewPortSize != availableSize;
            if (isChaigeViewPortSize)
            {
                System.Console.WriteLine("ViewPoirt:"+availableSize);
                containerLayouts.Clear();
            }

            // 変更前の1行の要素数
            var prevColumCount = Math.Max(1,Convert.ToInt32(GetLogicalWidth(prevViewPortSize)) / Convert.ToInt32(GetLogicalWidth(prevSize)));

            // 最初の操作インデックス取得
            var vy = Convert.ToInt32(this.offset.Y) / Convert.ToInt32(prevSize.Height);
            var vx = Convert.ToInt32(GetLogicalX(this.offset)) / Convert.ToInt32(prevSize.Width);
            var first = vx + vy * prevColumCount;

            // 最後のインデックス取得
            var vey = (Convert.ToInt32(GetLogicalY(this.offset)) + GetLogicalHeight(prevViewPortSize)) / Convert.ToInt32(GetLogicalHeight(prevSize)) + 2;
            var vex = (Convert.ToInt32(GetLogicalX(this.offset)) + GetLogicalWidth(prevViewPortSize)) / Convert.ToInt32(GetLogicalWidth(prevSize)) + 1;
            var end = Convert.ToInt32(vex + vey * prevColumCount) + 1;

            int childrenCount = 0;
            var itemsControl = ItemsControl.GetItemsOwner(this);
            if (itemsControl != null)
            {
                childrenCount = itemsControl.Items.Count;
            }
            if (childrenCount < 1) return maxSize;

            // TODO:TEST変更があった場合は大きく取るように修正
            if (isChaigeViewPortSize)
            {
                if (first < 1)
                {
                    first = 0;
                    end = 1000;
                }
                if (end >= childrenCount)
                {
                    end = childrenCount;
                    first = end -1000;
                }
            }

            // TODO:中にすべての要素が含まれている必要がある。

            // 補正した最終インデックス
            var firstIndex = Math.Max(0, first);
            var endIndex = Math.Min(end, childrenCount);
            System.Console.WriteLine("Index:{0},{1}",first, end);

            // 変更あとの1行の要素数
            var columCount = Math.Max(1, Convert.ToInt32(GetLogicalWidth(availableSize)) / Convert.ToInt32(GetLogicalWidth(prevSize)));

            var adjustViewPortOffset = this.offset;
            if (isChaigeViewPortSize)
            {
                var pvy = GetLogicalY(adjustViewPortOffset);

                pvy = pvy * prevColumCount / columCount;
                if (isHorizontal)
                {
                    adjustViewPortOffset.Y = pvy;
                }
                else
                {
                    adjustViewPortOffset.X = pvy;
                }
            }

            //var container = this.InternalChildren;
            //var childrenCount = container.Count;

            bool continium = false;

            var childSize = prevSize;

#if false // normal calc
            using (var generator = new ChildGenerator(this))
            {
                for (int i = firstIndex; i < endIndex; i++)
                {
                    // オフセット
                    var x = (int)((i % columCount) * childSize.Width);
                    var y = (int)((i / columCount) * childSize.Height);

                    // 子要素がビューポート内であれば子要素を生成しサイズを再計測
                    var itemRect = new Rect(x, y, childSize.Width, childSize.Height);
                    var viewportRect = new Rect(adjustViewPortOffset, availableSize);
                    if (itemRect.IntersectsWith(viewportRect))
                    {
                        var child = generator.GetOrCreateChild(i);
                        child.Measure(childSize);
                        childSize = this.ContainerSizeForIndex(i);

                        // 確定したサイズを記憶
                        this.containerLayouts[i]=  new Rect(x, y, childSize.Width, childSize.Height);

                        continium = true;
                        continue;
                    }

                    if (continium) break;
                }
            }

#else   // timelimit version.
            // measure phase
            var endCheckIndex = endIndex;
            for (int i = firstIndex; i < endCheckIndex; i++)
            {
                // オフセット
                var x = (int)((i % columCount) * GetLogicalWidth(childSize));
                var y = (int)((i / columCount) * GetLogicalHeight(childSize));

                // 子要素がビューポート内であれば子要素を生成しサイズを再計測
                var itemRect = new Rect(isHorizontal?x:y, isHorizontal ? y : x, childSize.Width, childSize.Height);
                var viewportRect = new Rect(adjustViewPortOffset, availableSize);
                if (itemRect.IntersectsWith(viewportRect))
                {
                    //var child = generator.GetOrCreateChild(i);
                    //child.Measure(childSize);
                    //childSize = this.ContainerSizeForIndex(i);

                    // 確定したサイズを記憶
                    this.containerLayouts[i]=  new Rect(isHorizontal ? x : y, isHorizontal ? y : x, childSize.Width, childSize.Height);

                    // インデックスの確定補正
                    if (!continium)
                    {
                        firstIndex = i;
                    }
                    endIndex = i;

                    continium = true;
                    continue;
                }

                if (continium) break;
            }

            using (var generator = new ChildGenerator(this, firstIndex, endIndex))
            {
                //continium = false;

                var limitTime = 250;

                var stopWatch = new Stopwatch();

                // create phase
                for (int i = firstIndex; i < endIndex; i++)
                {
                    // オフセット
                    //var x = (int)((i % columCount) * GetLogicalWidth(childSize));
                    //var y = (int)((i / columCount) * GetLogicalHeight(childSize));

                    // 子要素がビューポート内であれば子要素を生成しサイズを再計測
                    //var itemRect = new Rect(isHorizontal ? x : y, isHorizontal ? y : x, childSize.Width, childSize.Height);
                    //var viewportRect = new Rect(adjustViewPortOffset, availableSize);
                    //if (itemRect.IntersectsWith(viewportRect))
                    {

                        var child = generator.GetChild(i);
                        if (child == null)
                        {
                            stopWatch.Start();
                            child = generator.GetOrCreateChild(i);
                        }
                        //child.Measure(childSize);
                        //childSize = this.ContainerSizeForIndex(i);

                        // 確定したサイズを記憶
                        //this.containerLayouts[i] = new Rect(isHorizontal ? x : y, isHorizontal ? y : x, childSize.Width, childSize.Height);

                        // timelimit
                        stopWatch.Stop();
                        //if (stopWatch.ElapsedMilliseconds > limitTime)
                        if (stopWatch.ElapsedTicks > limitTime)
                        {
                            Console.WriteLine("request Measure");
                            Dispatcher.BeginInvoke((Action)(() =>
                            {
                                //System.Console.WriteLine("Measure");
                                InvalidateMeasure();
                            }));

                            break;
                        }

                        continium = true;
                        continue;
                    }

                    //if (continium) break;

                }

#endif
                generator.CleanupChildren();
            }

            var row = childrenCount / columCount + ((childrenCount % columCount == 0) ? 0 : 1);

            if (isHorizontal)
            {
                maxSize = new Size(availableSize.Width, Math.Max(row * childSize.Height, availableSize.Height));
            } else
            {
                maxSize = new Size(Math.Max(row * childSize.Width, availableSize.Width), availableSize.Height );
            }

            prevViewPortSize = availableSize;

            this.extent = maxSize;
            this.viewport = availableSize;

            //this.offset = adjustViewPortOffset;
            SetVerticalOffset(adjustViewPortOffset.Y);

            if (this.ScrollOwner != null)
                this.ScrollOwner.InvalidateScrollInfo();

            return maxSize;
#else
            this.containerLayouts.Clear();

            var isAutoWidth = double.IsNaN(this.ItemWidth);
            var isAutoHeight = double.IsNaN(this.ItemHeight);
            var childAvailable = new Size(isAutoWidth ? double.PositiveInfinity : this.ItemWidth, isAutoHeight ? double.PositiveInfinity : this.ItemHeight);
            var isHorizontal = this.Orientation == Orientation.Horizontal;

            var childrenCount = this.InternalChildren.Count;

            var itemsControl = ItemsControl.GetItemsOwner(this);
            if (itemsControl != null)
                childrenCount = itemsControl.Items.Count;

            var generator = new ChildGenerator(this);

            var x = 0.0;
            var y = 0.0;
            var lineSize = default(Size);
            var maxSize = default(Size);

            for (int i = 0; i < childrenCount; i++)
            {
                var childSize = this.ContainerSizeForIndex(i);

                // ビューポートとの交差判定用に仮サイズで x, y を調整
                var isWrapped = isHorizontal ?
                    lineSize.Width + childSize.Width > availableSize.Width :
                    lineSize.Height + childSize.Height > availableSize.Height;
                if (isWrapped)
                {
                    x = isHorizontal ? 0 : x + lineSize.Width;
                    y = isHorizontal ? y + lineSize.Height : 0;
                }

                // 子要素がビューポート内であれば子要素を生成しサイズを再計測
                var itemRect = new Rect(x, y, childSize.Width, childSize.Height);
                var viewportRect = new Rect(this.offset, availableSize);
                if (itemRect.IntersectsWith(viewportRect))
                {
                    var child = generator.GetOrCreateChild(i);
                    child.Measure(childAvailable);
                    childSize = this.ContainerSizeForIndex(i);
                }

                // 確定したサイズを記憶
                this.containerLayouts[i] = new Rect(x, y, childSize.Width, childSize.Height);

                // lineSize, maxSize を計算
                isWrapped = isHorizontal ?
                    lineSize.Width + childSize.Width > availableSize.Width :
                    lineSize.Height + childSize.Height > availableSize.Height;
                if (isWrapped)
                {
                    maxSize.Width = isHorizontal ? Math.Max(lineSize.Width, maxSize.Width) : maxSize.Width + lineSize.Width;
                    maxSize.Height = isHorizontal ? maxSize.Height + lineSize.Height : Math.Max(lineSize.Height, maxSize.Height);
                    lineSize = childSize;

                    isWrapped = isHorizontal ?
                        childSize.Width > availableSize.Width :
                        childSize.Height > availableSize.Height;
                    if (isWrapped)
                    {
                        maxSize.Width = isHorizontal ? Math.Max(childSize.Width, maxSize.Width) : maxSize.Width + childSize.Width;
                        maxSize.Height = isHorizontal ? maxSize.Height + childSize.Height : Math.Max(childSize.Height, maxSize.Height);
                        lineSize = default(Size);
                    }
                }
                else
                {
                    lineSize.Width = isHorizontal ? lineSize.Width + childSize.Width : Math.Max(childSize.Width, lineSize.Width);
                    lineSize.Height = isHorizontal ? Math.Max(childSize.Height, lineSize.Height) : lineSize.Height + childSize.Height;
                }

                x = isHorizontal ? lineSize.Width : maxSize.Width;
                y = isHorizontal ? maxSize.Height : lineSize.Height;
            }

            maxSize.Width = isHorizontal ? Math.Max(lineSize.Width, maxSize.Width) : maxSize.Width + lineSize.Width;
            maxSize.Height = isHorizontal ? maxSize.Height + lineSize.Height : Math.Max(lineSize.Height, maxSize.Height);

            this.extent = maxSize;
            this.viewport = availableSize;

            generator.CleanupChildren();
            generator.Dispose();

            if (this.ScrollOwner != null)
                this.ScrollOwner.InvalidateScrollInfo();

            return maxSize;

#endif
        }
        protected override Size MeasureOverride(Size availableSize)
        {
            this.containerLayouts.Clear();

            var isAutoWidth = double.IsNaN(this.ItemWidth);
            var isAutoHeight = double.IsNaN(this.ItemHeight);
            var childAvailable = new Size(isAutoWidth ? double.PositiveInfinity : this.ItemWidth, isAutoHeight ? double.PositiveInfinity : this.ItemHeight);
            var isHorizontal = this.Orientation == Orientation.Horizontal;

            var childrenCount = this.InternalChildren.Count;

            var itemsControl = ItemsControl.GetItemsOwner(this);
            if (itemsControl != null)
                childrenCount = itemsControl.Items.Count;

            var generator = new ChildGenerator(this);

            var x = 0.0;
            var y = 0.0;
            var lineSize = default(Size);
            var maxSize = default(Size);

            for (int i = 0; i < childrenCount; i++)
            {
                var childSize = this.ContainerSizeForIndex(i);

                var isWrapped = isHorizontal ?
                    lineSize.Width + childSize.Width > availableSize.Width :
                    lineSize.Height + childSize.Height > availableSize.Height;
                if (isWrapped)
                {
                    x = isHorizontal ? 0 : x + lineSize.Width;
                    y = isHorizontal ? y + lineSize.Height : 0;
                }

                var itemRect = new Rect(x, y, childSize.Width, childSize.Height);
                var viewportRect = new Rect(this.offset, availableSize);
                if (itemRect.IntersectsWith(viewportRect))
                {
                    var child = generator.GetOrCreateChild(i);
                    child.Measure(childAvailable);
                    childSize = this.ContainerSizeForIndex(i);
                }

                this.containerLayouts[i] = new Rect(x, y, childSize.Width, childSize.Height);

                isWrapped = isHorizontal ?
                    lineSize.Width + childSize.Width > availableSize.Width :
                    lineSize.Height + childSize.Height > availableSize.Height;
                if (isWrapped)
                {
                    maxSize.Width = isHorizontal ? Math.Max(lineSize.Width, maxSize.Width) : maxSize.Width + lineSize.Width;
                    maxSize.Height = isHorizontal ? maxSize.Height + lineSize.Height : Math.Max(lineSize.Height, maxSize.Height);
                    lineSize = childSize;

                    isWrapped = isHorizontal ?
                        childSize.Width > availableSize.Width :
                        childSize.Height > availableSize.Height;
                    if (isWrapped)
                    {
                        maxSize.Width = isHorizontal ? Math.Max(childSize.Width, maxSize.Width) : maxSize.Width + childSize.Width;
                        maxSize.Height = isHorizontal ? maxSize.Height + childSize.Height : Math.Max(childSize.Height, maxSize.Height);
                        lineSize = default(Size);
                    }
                }
                else
                {
                    lineSize.Width = isHorizontal ? lineSize.Width + childSize.Width : Math.Max(childSize.Width, lineSize.Width);
                    lineSize.Height = isHorizontal ? Math.Max(childSize.Height, lineSize.Height) : lineSize.Height + childSize.Height;
                }

                x = isHorizontal ? lineSize.Width : maxSize.Width;
                y = isHorizontal ? maxSize.Height : lineSize.Height;
            }

            maxSize.Width = isHorizontal ? Math.Max(lineSize.Width, maxSize.Width) : maxSize.Width + lineSize.Width;
            maxSize.Height = isHorizontal ? maxSize.Height + lineSize.Height : Math.Max(lineSize.Height, maxSize.Height);

            this.extent = maxSize;
            this.viewport = availableSize;

            generator.CleanupChildren();
            generator.Dispose();

            if (this.ScrollOwner != null)
                this.ScrollOwner.InvalidateScrollInfo();

            return maxSize;
        }