FirstFloor.ModernUI.Windows.Controls.VirtualizingTilePanel.MeasureOverride C# (CSharp) Method

MeasureOverride() protected method

protected MeasureOverride ( Size availableSize ) : Size
availableSize System.Windows.Size
return System.Windows.Size
        protected override Size MeasureOverride(Size availableSize) {
            if (_itemsControl == null) {
                return new Size(double.IsInfinity(availableSize.Width) ? 0 : availableSize.Width,
                        double.IsInfinity(availableSize.Height) ? 0 : availableSize.Height);
            }

            if (double.IsInfinity(_itemWidth)) {
                _itemWidth = ItemWidth;
                _itemHeight = ItemHeight;

                if (double.IsInfinity(_itemWidth) || double.IsInfinity(_itemHeight)) {
                    try {
                        var itemSize = DetectItemSize(new Size(_itemWidth, _itemHeight));
                        _itemWidth = itemSize.Width;
                        _itemHeight = itemSize.Height;
                    } catch (Exception e) {
                        Logging.Write($"Exception: {e}");
                    }
                }
            }

            _isInMeasure = true;
            _childLayouts.Clear();

            var extentInfo = GetExtentInfo(availableSize);
            EnsureScrollOffsetIsWithinConstrains(extentInfo);
                
            var layoutInfo = GetLayoutInfo(availableSize, _itemWidth, _itemHeight, extentInfo);
            RecycleItems(layoutInfo);

            // Determine where the first item is in relation to previously realized items
            var generatorStartPosition = _itemsGenerator.GeneratorPositionFromIndex(layoutInfo.FirstRealizedItemIndex);
            var visualIndex = 0;

            var currentX = layoutInfo.FirstRealizedItemLeft;
            var currentY = layoutInfo.FirstRealizedItemTop;

            var orientation = Orientation;
            double offsetX, offsetY;
            switch (HorizontalContentAlignment) {
                case HorizontalAlignment.Left:
                case HorizontalAlignment.Stretch:
                    offsetX = 0d;
                    break;
                case HorizontalAlignment.Center:
                    if (orientation == Orientation.Horizontal) {
                        offsetX = (availableSize.Width - extentInfo.ItemsPerRow * _itemWidth) / 2d;
                    } else {
                        offsetX = Math.Max(availableSize.Width - extentInfo.TotalRows * _itemWidth, 0d) / 2d;
                    }
                    break;
                case HorizontalAlignment.Right:
                    if (orientation == Orientation.Horizontal) {
                        offsetX = availableSize.Width - extentInfo.ItemsPerRow * _itemWidth;
                    } else {
                        offsetX = Math.Max(availableSize.Width - extentInfo.TotalRows * _itemWidth, 0d);
                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            switch (VerticalContentAlignment) {
                case VerticalAlignment.Top:
                case VerticalAlignment.Stretch:
                    offsetY = 0d;
                    break;
                case VerticalAlignment.Center:
                    if (orientation == Orientation.Horizontal) {
                        offsetY = Math.Max(availableSize.Height - extentInfo.TotalRows * _itemHeight, 0d) / 2d;
                    } else {
                        offsetY = (availableSize.Height - extentInfo.ItemsPerRow * _itemHeight) / 2d;
                    }
                    break;
                case VerticalAlignment.Bottom:
                    if (orientation == Orientation.Horizontal) {
                        offsetY = Math.Max(availableSize.Height - extentInfo.TotalRows * _itemHeight, 0d);
                    } else {
                        offsetY = availableSize.Height - extentInfo.ItemsPerRow * _itemHeight;
                    }
                    break;
                default:
                    throw new ArgumentOutOfRangeException();
            }

            using (_itemsGenerator.StartAt(generatorStartPosition, GeneratorDirection.Forward, true)) {
                for (var itemIndex = layoutInfo.FirstRealizedItemIndex; itemIndex <= layoutInfo.LastRealizedItemIndex; itemIndex++, visualIndex++) {
                    bool newlyRealized;
                    var child = (UIElement)_itemsGenerator.GenerateNext(out newlyRealized);
                    SetVirtualItemIndex(child, itemIndex);

                    if (newlyRealized) {
                        InsertInternalChild(visualIndex, child);
                    } else {
                        // check if item needs to be moved into a new position in the Children collection
                        if (visualIndex < Children.Count) {
                            if (!ReferenceEquals(Children[visualIndex], child)) {
                                var childCurrentIndex = Children.IndexOf(child);

                                if (childCurrentIndex >= 0) {
                                    RemoveInternalChildRange(childCurrentIndex, 1);
                                }

                                InsertInternalChild(visualIndex, child);
                            }
                        } else {
                            // we know that the child can't already be in the children collection
                            // because we've been inserting children in correct visualIndex order,
                            // and this child has a visualIndex greater than the Children.Count
                            AddInternalChild(child);
                        }
                    }

                    // only prepare the item once it has been added to the visual tree
                    _itemsGenerator.PrepareItemContainer(child);

                    child.Measure(new Size(_itemWidth, _itemHeight));
                    _childLayouts.Add(child, new Rect(currentX + offsetX, currentY + offsetY, _itemWidth, _itemHeight));

                    if (orientation == Orientation.Horizontal) {
                        if (currentX + _itemWidth * 2 >= availableSize.Width) {
                            // wrap to a new line
                            currentY += _itemHeight;
                            currentX = 0;
                        } else {
                            currentX += _itemWidth;
                        }
                    } else {
                        if (currentY + _itemHeight * 2 >= availableSize.Height) {
                            // wrap to a new column
                            currentX += _itemWidth;
                            currentY = 0;
                        } else {
                            currentY += _itemHeight;
                        }
                    }
                }
            }

            RemoveRedundantChildren();
            UpdateScrollInfo(availableSize, extentInfo);

            var desiredSize = new Size(double.IsInfinity(availableSize.Width) ? 0 : availableSize.Width, double.IsInfinity(availableSize.Height) ? 0 : availableSize.Height);
            _isInMeasure = false;

            return desiredSize;
        }