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