示例#1
0
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            var realizationRect = context.RealizationRect;
            int itemCount       = context.ItemCount;

            if (realizationRect.Width < itemCount * (ItemWidth + Spacing)) // TODO: Better math
            {
                int firstRealizedIndex = FirstRealizedIndexInRect(realizationRect, itemCount);
                int lastRealizedIndex  = LastRealizedIndexInRect(realizationRect, itemCount);
                Debug.WriteLine("Arrange:" + realizationRect.ToString());

                // Viewport + Buffer Rect.
                for (int currentIndex = firstRealizedIndex; currentIndex <= lastRealizedIndex; currentIndex++)
                {
                    var realIndex   = Math.Abs(currentIndex % context.ItemCount);
                    var element     = context.GetOrCreateElementAt(realIndex);
                    var arrangeRect = new Rect(currentIndex * (ItemWidth + Spacing), 0, ItemWidth, ItemHeight);
                    element.Arrange(arrangeRect);
                    Debug.WriteLine("   Arrange:" + currentIndex + " :" + arrangeRect);
                }
            }
            else
            {
                for (int i = 0; i < itemCount; i++)
                {
                    var element     = context.GetOrCreateElementAt(i);
                    var arrangeRect = new Rect(i * (ItemWidth + Spacing), 0, ItemWidth, ItemHeight);
                    element.Arrange(arrangeRect);
                    Debug.WriteLine("   Arrange:" + i + " :" + arrangeRect);
                }
            }

            return(finalSize);
        }
示例#2
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var realizationRect = context.RealizationRect;
            int itemCount       = context.ItemCount;

            if (realizationRect.Width == 0 || realizationRect.Width < itemCount * (ItemWidth + Spacing)) // TODO: Better math
            {
                int firstRealizedIndex = FirstRealizedIndexInRect(realizationRect, itemCount);
                int lastRealizedIndex  = LastRealizedIndexInRect(realizationRect, itemCount);
                Debug.WriteLine("Measure:" + realizationRect.ToString());

                // Viewport + Buffer Rect.
                for (int currentIndex = firstRealizedIndex; currentIndex <= lastRealizedIndex; currentIndex++)
                {
                    var realIndex = Math.Abs(currentIndex % context.ItemCount);
                    var element   = context.GetOrCreateElementAt(realIndex);
                    element.Measure(new Size(ItemWidth, ItemHeight));
                }

                return(new Size(((ItemWidth + Spacing) * context.ItemCount * 1000) - Spacing, ItemHeight));
            }
            else
            {
                for (int i = 0; i < itemCount; i++)
                {
                    var element = context.GetOrCreateElementAt(i);
                    element.Measure(new Size(ItemWidth, ItemHeight));
                }

                return(new Size((ItemWidth + Spacing) * context.ItemCount - Spacing, ItemHeight));
            }
        }
        private Size ArrangeColumn(VirtualizingLayoutContext context, GroupedLayoutState state, ColumnInfo colInfo, int col, int headerIndex, double startingY, bool widthChanged, out int nextHeaderIndex)
        {
            // Note that you MUST call GetOrCreateElement on any items that are in the realized region... that's how
            // the control tracks which elements it shouldn't dispose.

            double y = startingY;
            double x = col * colInfo.ColumnWidth + ColumnSpacing * col;
            int    i = headerIndex;

            var header   = state.GetItemAt(headerIndex);
            var headerEl = context.GetOrCreateElementAt(headerIndex);

            headerEl.Arrange(new Rect(x, y, colInfo.ColumnWidth, headerEl.DesiredSize.Height));
            y += headerEl.DesiredSize.Height + AfterHeaderSpacing;

            i++;

            while (i < context.ItemCount)
            {
                if (!(context.GetItemAt(i) is ViewItemTaskOrEvent))
                {
                    // End of column
                    break;
                }

                var item = state.GetItemAt(i);

                // Logic technically ignores height of item, but heights are short enough it shouldn't matter
                if (y < context.RealizationRect.Top ||
                    y > context.RealizationRect.Bottom)
                {
                    y += item.Height.GetValueOrDefault(40);
                }
                else
                {
                    var el = context.GetOrCreateElementAt(i);
                    //if (widthChanged || !item.Arranged)
                    {
                        el.Arrange(new Rect(x, y, colInfo.ColumnWidth, el.DesiredSize.Height));
                    }

                    y += el.DesiredSize.Height;
                }

                // Include item spacing
                y += ItemSpacing;

                i++;
            }

            // Remove last item spacing (since no item after it)
            y -= ItemSpacing;

            nextHeaderIndex = i;
            return(new Size(colInfo.ColumnWidth, y - startingY));
        }
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            if (context.RealizationRect.Width == 0 ||
                context.RealizationRect.Height == 0)
            {
                return(finalSize);
            }

            var viewRect = context.RealizationRect;
            var state    = (AutoFillLayoutState)context.LayoutState;

            Debug.Assert(context.ItemCount == state.ItemCount);

            for (int i = 0; i < context.ItemCount; i++)
            {
                var item   = state[i];
                var bounds = item.Bounds;

                if (viewRect.IsIntersect(bounds))
                {
                    var child = context.GetOrCreateElementAt(item.Index);
                    item.Element = child;
                    child.Arrange(bounds);
                }
            }
            return(finalSize);
        }
示例#5
0
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            // walk through the cache of containers and arrange
            var state = context.LayoutState as MosaicLayoutState;

            if (state.LayoutRects.Count < 1)
            {
                return(finalSize);
            }

            var firstItemIndex = state.FirstRealizedIndex;
            var lastItemIndex  = state.LastRealizedIndex;

            var finalWidth = finalSize.Width + 2;

            for (int i = firstItemIndex; i <= lastItemIndex; i++)
            {
                var container = context.GetOrCreateElementAt(i);
                container.Arrange(new Rect(
                                      state.LayoutRects[i].X * finalWidth,
                                      state.LayoutRects[i].Y,
                                      state.LayoutRects[i].Width * finalWidth,
                                      state.LayoutRects[i].Height));
            }

            return(finalSize);
        }
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var viewport = context.RealizationRect;

            if (availableSize.Width != m_lastAvailableWidth || cachedBoundsInvalid)
            {
                UpdateCachedBounds(availableSize);
                m_lastAvailableWidth = availableSize.Width;
            }

            // Initialize column offsets
            int numColumns = (int)(availableSize.Width / Width);

            if (m_columnOffsets.Count == 0)
            {
                for (int i = 0; i < numColumns; i++)
                {
                    m_columnOffsets.Add(0);
                }
            }

            m_firstIndex = GetStartIndex(viewport);
            int    currentIndex = m_firstIndex;
            double nextOffset   = -1.0;

            // Measure items from start index to when we hit the end of the viewport.
            while (currentIndex < context.ItemCount && nextOffset < viewport.Bottom)
            {
                var child = context.GetOrCreateElementAt(currentIndex);
                child.Measure(new Size(Width, availableSize.Height));

                if (currentIndex >= m_cachedBounds.Count)
                {
                    // We do not have bounds for this index. Lay it out and cache it.
                    int columnIndex = GetIndexOfLowestColumn(m_columnOffsets, out nextOffset);
                    m_cachedBounds.Add(new Rect(columnIndex * Width, nextOffset, Width, child.DesiredSize.Height));
                    m_columnOffsets[columnIndex] += child.DesiredSize.Height;
                }
                else
                {
                    if (currentIndex + 1 == m_cachedBounds.Count)
                    {
                        // Last element. Use the next offset.
                        GetIndexOfLowestColumn(m_columnOffsets, out nextOffset);
                    }
                    else
                    {
                        nextOffset = m_cachedBounds[currentIndex + 1].Top;
                    }
                }

                m_lastIndex = currentIndex;
                currentIndex++;
            }

            var extent = GetExtentSize(availableSize);

            return(extent);
        }
示例#7
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var itemCount = context.ItemCount;

            for (int i = 0; i < context.ItemCount; i++)
            {
                var container = context.GetOrCreateElementAt(i);
                container.Measure(new Size(ItemSize, ItemSize));
            }

            return(availableSize);
        }
示例#8
0
 protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
 {
     if (context.RealizationRect != default && context.ItemCount > 0)
     {
         for (var index = m_firstIndex; index <= m_lastIndex; index++)
         {
             var child = context.GetOrCreateElementAt(index);
             child.Arrange(m_cachedBounds[index]);
         }
     }
     return(finalSize);
 }
示例#9
0
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            if (!(context.LayoutState is LayoutState state))
            {
                return(Size.Empty);
            }

            for (int i = state.FirstIndex; i < state.LastIndex; i++)
            {
                var container = context.GetOrCreateElementAt(i);
                container.Arrange(state.LayoutRects[i]);
            }

            return(finalSize);
        }
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var state  = context.LayoutState as TimelineRailState;
            var scaler = Scaler;

            state.LayoutRects.Clear();
            int firstColumnIndex = context.ItemCount;
            int lastColumnIndex  = 0;
            int lastFrameIndex   = 0;
            int xFrameIndex      = (int)(context.RealizationRect.Left / scaler) - 1;
            int yFrameIndex      = (int)(context.RealizationRect.Right / scaler) + 1;

            for (int i = 0; i < context.ItemCount; i++)
            {
                var data = (TimelineRailItem)context.GetItemAt(i);
                firstColumnIndex = i;
                if (data.StartFrameIndex + data.ContinueFramesCount > xFrameIndex)
                {
                    break;
                }
            }
            for (int i = firstColumnIndex; i < context.ItemCount; i++)
            {
                var data = (TimelineRailItem)context.GetItemAt(i);
                lastColumnIndex = i + 1;//考虑不被执行的情况
                if (data.StartFrameIndex > yFrameIndex)
                {
                    break;
                }
            }
            for (int i = firstColumnIndex; i < lastColumnIndex; i++)
            {
                var data      = (TimelineRailItem)context.GetItemAt(i);
                var container = context.GetOrCreateElementAt(i);

                var rect = new Rect(data.StartFrameIndex * scaler, 0, data.ContinueFramesCount * scaler, c_railHeight);
                state.LayoutRects.Add(rect);
                container.Measure(new Size(rect.Width, c_railHeight));
            }

            for (int i = 0; i < context.ItemCount; i++)
            {
                var data = (TimelineRailItem)context.GetItemAt(i);
                lastFrameIndex = Math.Max(lastFrameIndex, data.StartFrameIndex + data.ContinueFramesCount);
            }
            state.FirstRealizedIndex = firstColumnIndex;
            return(new Size(lastFrameIndex * scaler, c_railHeight));
        }
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var state  = context.LayoutState as AnimationTagViewLayoutState;
            var scaler = Scaler;

            state.LayoutRects.Clear();
            int firstColumnIndex = context.ItemCount;
            int lastColumnIndex  = 0;
            int lastFrameIndex   = 0;
            int xFrameIndex      = (int)(context.RealizationRect.Left / scaler) - 1;
            int yFrameIndex      = (int)(context.RealizationRect.Right / scaler) + 1;

            for (int i = 0; i < context.ItemCount; i++)
            {
                var data = (AnimationTag)context.GetItemAt(i);
                firstColumnIndex = i;
                if (data.FrameIndex > xFrameIndex)
                {
                    break;
                }
            }
            for (int i = firstColumnIndex; i < context.ItemCount; i++)
            {
                var data = (AnimationTag)context.GetItemAt(i);
                lastColumnIndex = i + 1;//考虑不被执行的情况
                if (data.FrameIndex > yFrameIndex)
                {
                    break;
                }
            }
            for (int i = firstColumnIndex; i < lastColumnIndex; i++)
            {
                var data      = (AnimationTag)context.GetItemAt(i);
                var container = context.GetOrCreateElementAt(i);

                var rect = new Rect(data.FrameIndex * scaler, 4, 16, 16);
                state.LayoutRects.Add(rect);
                container.Measure(new Size(rect.Width, c_railHeight));
            }

            if (context.ItemCount > 0)
            {
                lastFrameIndex = ((AnimationTag)context.GetItemAt(context.ItemCount - 1)).FrameIndex;
            }

            state.FirstRealizedIndex = firstColumnIndex;
            return(new Size(lastFrameIndex * scaler + 300, c_railHeight));
        }
示例#12
0
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            var itemCount      = context.ItemCount;
            var radius         = GetCircleRadius(finalSize) - ItemSize / 2.0;
            var angleIncrement = 2 * Math.PI / itemCount;
            var angle          = 0.0;

            for (int i = 0; i < context.ItemCount; i++)
            {
                var container = context.GetOrCreateElementAt(i);
                var x         = Math.Sin(angle) * radius - ItemSize / 2.0 + finalSize.Width / 2.0;
                var y         = -Math.Cos(angle) * radius - ItemSize / 2.0 + finalSize.Height / 2.0;
                container.Arrange(new Rect(x, y, ItemSize, ItemSize));
                angle += angleIncrement;
            }

            return(finalSize);
        }
示例#13
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var realizationRect    = context.RealizationRect;
            int itemCount          = context.ItemCount;
            int firstRealizedIndex = FirstRealizedIndexInRect(realizationRect, itemCount);
            int lastRealizedIndex  = LastRealizedIndexInRect(realizationRect, itemCount);

            Debug.WriteLine("Measure:" + realizationRect.ToString());

            // Viewport + Buffer Rect.
            for (int currentIndex = firstRealizedIndex; currentIndex <= lastRealizedIndex; currentIndex++)
            {
                var realIndex = Math.Abs(currentIndex % context.ItemCount);
                var element   = context.GetOrCreateElementAt(realIndex);
                element.Measure(new Size(ItemWidth, ItemHeight));
            }

            return(new Size(ItemWidth * context.ItemCount * 1000, ItemHeight));
        }
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            var realizationRect = context.RealizationRect;
            int itemCount       = context.ItemCount;
            var firstRow        = FirstRealizedRowIndexInRect(realizationRect, itemCount);
            var firstCol        = FirsttRealizedColumnIndexInRect(realizationRect, itemCount);
            var lastRow         = LastRealizedRowIndexInRect(realizationRect, itemCount);
            var lastCol         = LastRealizedColumnIndexInRect(realizationRect, itemCount);

            Debug.WriteLine("Arrange:" + realizationRect.ToString());

            // Viewport + Buffer Rect.
            for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++)
            {
                for (int colIndex = firstCol; colIndex <= lastCol; colIndex++)
                {
                    var realIndex = GetElementIndex(rowIndex, colIndex, context.ItemCount);
                    if (realIndex >= 0 && realIndex < itemCount)
                    {
                        var element = context.GetOrCreateElementAt(realIndex);
                        if (EnlargeFocusedItem && FocusManager.GetFocusedElement() == element)
                        {
                            var widthDiff   = FocusedItemWidth - ItemWidth;
                            var heightDiff  = FocusedItemHeight - ItemHeight;
                            var arrangeRect = new Rect(colIndex * (ItemWidth + Spacing) - widthDiff / 2, rowIndex * (ItemHeight + Spacing) - heightDiff / 2, FocusedItemWidth, FocusedItemHeight);
                            element.Arrange(arrangeRect);
                            Debug.WriteLine("   Arrange:" + realIndex + " :" + arrangeRect);
                            Canvas.SetZIndex(element, 1);
                        }
                        else
                        {
                            var arrangeRect = new Rect(colIndex * (ItemWidth + Spacing), rowIndex * (ItemHeight + Spacing), ItemWidth, ItemHeight);
                            element.Arrange(arrangeRect);
                            Debug.WriteLine("   Arrange:" + realIndex + " :" + arrangeRect);
                            Canvas.SetZIndex(element, 0);
                        }
                    }
                }
            }

            return(finalSize);
        }
示例#15
0
        /// <inheritdoc/>
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            if ((context.RealizationRect.Width == 0) && (context.RealizationRect.Height == 0))
            {
                return(finalSize);
            }

            var state = (StaggeredLayoutState)context.LayoutState;

            // Cycle through each column and arrange the items that are within the realization bounds
            for (int columnIndex = 0; columnIndex < state.NumberOfColumns; columnIndex++)
            {
                StaggeredColumnLayout layout = state.GetColumnLayout(columnIndex);
                for (int i = 0; i < layout.Count; i++)
                {
                    StaggeredItem item = layout[i];

                    double bottom = item.Top + item.Height;
                    if (bottom < context.RealizationRect.Top)
                    {
                        // element is above the realization bounds
                        continue;
                    }

                    if (item.Top <= context.RealizationRect.Bottom)
                    {
                        double itemHorizontalOffset = (state.ColumnWidth * columnIndex) + (ColumnSpacing * columnIndex);

                        Rect      bounds  = new Rect(itemHorizontalOffset, item.Top, state.ColumnWidth, item.Height);
                        UIElement element = context.GetOrCreateElementAt(item.Index);
                        element.Arrange(bounds);
                    }
                    else
                    {
                        break;
                    }
                }
            }

            return(finalSize);
        }
示例#16
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            if (!(context.LayoutState is LayoutState state))
            {
                return(Size.Empty);
            }
            var numColumns = (int)Math.Floor(availableSize.Width / Math.Min(DesiredItemSize, availableSize.Width));

            _itemSize = availableSize.Width / numColumns;
            var viewport = context.RealizationRect;

            _firstRowIndex = Math.Max(
                (int)(viewport.Y / DesiredItemSize) - 1,
                0);
            _lastRowIndex = Math.Min(
                (int)(viewport.Bottom / DesiredItemSize) + 1,
                (int)(context.ItemCount / numColumns));
            state.FirstIndex = _firstRowIndex * numColumns;
            for (int i = _firstRowIndex; i < _lastRowIndex; i++)
            {
                var firstItem = i * numColumns;
                var yoffset   = i * _itemSize;
                for (int j = 0; j < numColumns; j++)
                {
                    var itemIndex = j + firstItem;
                    var item      = context.GetOrCreateElementAt(itemIndex);
                    item.Measure(new Size(_itemSize, _itemSize));
                    if (itemIndex >= state.LayoutRects.Count)
                    {
                        state.LayoutRects.Add(new Rect(j * this._itemSize, yoffset, _itemSize, _itemSize));
                    }
                    else if (state.LayoutRects[itemIndex].Width != _itemSize)
                    {
                        state.LayoutRects[itemIndex] = new Rect(j * this._itemSize, yoffset, _itemSize, _itemSize);
                    }
                    state.LastIndex = itemIndex;
                }
            }

            return(new Size(_itemSize * numColumns, Math.Round(Convert.ToDouble(context.ItemCount) / Convert.ToDouble(numColumns)) * _itemSize));
        }
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var realizationRect = context.RealizationRect;
            int itemCount       = context.ItemCount;
            var firstRow        = FirstRealizedRowIndexInRect(realizationRect, itemCount);
            var firstCol        = FirsttRealizedColumnIndexInRect(realizationRect, itemCount);
            var lastRow         = LastRealizedRowIndexInRect(realizationRect, itemCount);
            var lastCol         = LastRealizedColumnIndexInRect(realizationRect, itemCount);

            Debug.WriteLine("Measure:" + realizationRect.ToString());

            // Viewport + Buffer Rect.
            for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++)
            {
                for (int colIndex = firstCol; colIndex <= lastCol; colIndex++)
                {
                    var realIndex = GetElementIndex(rowIndex, colIndex, context.ItemCount);
                    if (realIndex >= 0 && realIndex < itemCount)
                    {
                        var element = context.GetOrCreateElementAt(realIndex);
                        if (EnlargeFocusedItem && FocusManager.GetFocusedElement() == element)
                        {
                            element.Measure(new Size(FocusedItemWidth, FocusedItemHeight));
                        }
                        else
                        {
                            element.Measure(new Size(ItemWidth, ItemHeight));
                        }
                    }
                }
            }

            int numRowsOrColumns = (int)Math.Sqrt(context.ItemCount);

            return(new Size(ItemWidth * numRowsOrColumns, ItemHeight * numRowsOrColumns));
        }
        /// <inheritdoc />
        protected override Size ArrangeOverride(VirtualizingLayoutContext context, Size finalSize)
        {
            if (context.ItemCount > 0)
            {
                var parentMeasure     = new UvMeasure(Orientation, finalSize.Width, finalSize.Height);
                var spacingMeasure    = new UvMeasure(Orientation, HorizontalSpacing, VerticalSpacing);
                var realizationBounds = new UvBounds(Orientation, context.RealizationRect);

                var state = (WrapLayoutState)context.LayoutState;
                bool Arrange(WrapItem item, bool isLast = false)
                {
                    if (item.Measure.HasValue == false)
                    {
                        return(false);
                    }

                    if (item.Position == null)
                    {
                        return(false);
                    }

                    var desiredMeasure = item.Measure.Value;

                    if (desiredMeasure.U == 0)
                    {
                        return(true); // if an item is collapsed, avoid adding the spacing
                    }

                    UvMeasure position = item.Position.Value;

                    // Stretch the last item to fill the available space
                    if (isLast)
                    {
                        desiredMeasure.U = parentMeasure.U - position.U;
                    }

                    if (((position.V + desiredMeasure.V) >= realizationBounds.VMin) && (position.V <= realizationBounds.VMax))
                    {
                        // place the item
                        UIElement child = context.GetOrCreateElementAt(item.Index);
                        if (Orientation == Orientation.Horizontal)
                        {
                            child.Arrange(new Rect(position.U, position.V, desiredMeasure.U, desiredMeasure.V));
                        }
                        else
                        {
                            child.Arrange(new Rect(position.V, position.U, desiredMeasure.V, desiredMeasure.U));
                        }
                    }
                    else if (position.V > realizationBounds.VMax)
                    {
                        return(false);
                    }

                    return(true);
                }

                for (var i = 0; i < context.ItemCount; i++)
                {
                    bool continueArranging = Arrange(state.GetItemAt(i));
                    if (continueArranging == false)
                    {
                        break;
                    }
                }
            }

            return(finalSize);
        }
示例#19
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            availableSize.Width  = availableSize.Width /* - Padding.Left - Padding.Right*/;
            availableSize.Height = availableSize.Height /* - Padding.Top - Padding.Bottom*/;

            // For when width is even less than desired col width of even one column:
            _columnWidth = Math.Min(DesiredColumnWidth, availableSize.Width);
            int numColumns = (int)Math.Floor(availableSize.Width / _columnWidth);

            _columnWidth = availableSize.Width / numColumns;

            if (state == null || state.Width != context.RealizationRect.Width)
            {
                state = new StaggeredLayoutState(numColumns, _columnWidth, context.RealizationRect.Width);
            }

            if (context.ItemCount == 0)
            {
                return(new Size(availableSize.Width, 0));
            }

            // The viewport consists the current view, one view before, and one view after.
            double viewUpperBound = context.RealizationRect.Top;
            double viewLowerBound = context.RealizationRect.Bottom;

            int firstIndex = state.GetFirstItemInView(viewUpperBound);
            int lastIndex  = state.GetLastItemInView(viewLowerBound);

            int index = firstIndex;

            while (state.CacheCount < context.ItemCount)
            {
                Rect rect;
                bool cached = state.TryGetRect(lastIndex, out rect);
                if (cached)
                {
                    break;
                }

                // The culpit might be auto recycling. Supressing it solves the problem,
                // but defeats virtualization and raises runtime expections, so must fix it.

                // Okay, the real problem is the custom image control. Without that this implementation works just fine.
                // The culpit is the video control. Even using that alone produces the issue.
                // So might consider extract the first frame and put it in an image box.

                var child = context.GetOrCreateElementAt(lastIndex /*, ElementRealizationOptions.SuppressAutoRecycle*/);
                rect = state.CreateRectForChild(lastIndex, child);
                lastIndex++;
                if (rect.Top > viewLowerBound)
                {
                    break;
                }
            }

            while (index < lastIndex)
            {
                var  child = context.GetOrCreateElementAt(index);
                Rect rect;
                if (index < state.CacheCount)
                {
                    rect = state.GetRect(index);
                }
                else
                {
                    rect = state.CreateRectForChild(index, child);
                }

                // It turns out this measurement is pretty important for elements to stay within their bounds.
                child.Measure(new Size(rect.Width, rect.Height));
                // I know this is rather inelegant, but since ItemsRepeater has no click support whatsoever, so...
                SubscribeClickEvent(child);
                child.Arrange(rect);
                index++;
            }

            // Use this to reproduce bug.

            //var firstElement = context.GetOrCreateElementAt(0);
            //context.RecycleElement(firstElement);
            //firstElement = context.GetOrCreateElementAt(0);
            //firstElement.Measure(new Size(_columnWidth, availableSize.Height));
            //Rect r = state.GetRect(0);
            //firstElement.Arrange(r);

            double desiredHeight = state.GetTotalHeight();

            return(new Size(availableSize.Width, desiredHeight));
        }
示例#20
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            if (MinItemSize == Size.Empty)
            {
                var firstElement = context.GetOrCreateElementAt(0);
                firstElement.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));

                // setting the member value directly to skip invalidating layout
                _minItemSize = firstElement.DesiredSize;
            }

            // Determine which rows need to be realized.  We know every row will have the same height and
            // only contain 3 items.  Use that to determine the index for the first and last item that
            // will be within that realization rect.
            var firstRowIndex = Math.Max(
                (int)(context.RealizationRect.Y / (MinItemSize.Height + RowSpacing)) - 1,
                0);
            var lastRowIndex = Math.Min(
                (int)(context.RealizationRect.Bottom / (MinItemSize.Height + RowSpacing)) + 1,
                context.ItemCount / 3);

            // Determine which items will appear on those rows and what the rect will be for each item
            var state = context.LayoutState as ActivityFeedLayoutState;

            state.LayoutRects.Clear();

            // Save the index of the first realized item.  We'll use it as a starting point during arrange.
            state.FirstRealizedIndex = firstRowIndex * 3;

            // ideal item width that will expand/shrink to fill available space
            double desiredItemWidth = Math.Max(MinItemSize.Width, (availableSize.Width - ColumnSpacing * 3) / 4);

            // Foreach item between the first and last index,
            //     Call GetElementOrCreateElementAt which causes an element to either be realized or retrieved
            //       from a recycle pool
            //     Measure the element using an appropriate size
            //
            // Any element that was previously realized which we don't retrieve in this pass (via a call to
            // GetElementOrCreateAt) will be automatically cleared and set aside for later re-use.
            // Note: While this work fine, it does mean that more elements than are required may be
            // created because it isn't until after our MeasureOverride completes that the unused elements
            // will be recycled and available to use.  We could avoid this by choosing to track the first/last
            // index from the previous layout pass.  The diff between the previous range and current range
            // would represent the elements that we can pre-emptively make available for re-use by calling
            // context.RecycleElement(element).
            for (int rowIndex = firstRowIndex; rowIndex < lastRowIndex; rowIndex++)
            {
                int firstItemIndex      = rowIndex * 3;
                var boundsForCurrentRow = CalculateLayoutBoundsForRow(rowIndex, desiredItemWidth);

                for (int columnIndex = 0; columnIndex < 3; columnIndex++)
                {
                    var index     = firstItemIndex + columnIndex;
                    var rect      = boundsForCurrentRow[index % 3];
                    var container = context.GetOrCreateElementAt(index);

                    container.Measure(
                        new Size(boundsForCurrentRow[columnIndex].Width, boundsForCurrentRow[columnIndex].Height));

                    state.LayoutRects.Add(boundsForCurrentRow[columnIndex]);
                }
            }

            // Calculate and return the size of all the content (realized or not) by figuring out
            // what the bottom/right position of the last item would be.
            var extentHeight = (context.ItemCount / 3 - 1) * (MinItemSize.Height + RowSpacing) + MinItemSize.Height;

            // Report this as the desired size for the layout
            return(new Size(desiredItemWidth * 4 + ColumnSpacing * 2, extentHeight));
        }
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var requiredSize = new Size(Padding.Left + Padding.Right, Padding.Top + Padding.Bottom);

            if (context.ItemCount == 0 ||
                context.RealizationRect.Width == 0 ||
                context.RealizationRect.Height == 0)
            {
                return(requiredSize);
            }

            var state      = (AutoFillLayoutState)context.LayoutState;
            var clientSize = new Size(
                availableSize.Width - Padding.Left - Padding.Right,
                availableSize.Height - Padding.Top - Padding.Bottom);

            //Save layout properties
            //If changed every thing need redo
            if (state.SavePropertiesIfChange(Orientation, Padding,
                                             HorizontalSpacing, VerticalSpacing, availableSize))
            {
                state.Reset();
            }

            if (!state.Initialized)
            {
                if (Orientation == Orientation.Horizontal)
                {
                    state.Initialize(
                        new Rect(Padding.Left, Padding.Top,
                                 clientSize.Width + HorizontalSpacing, double.PositiveInfinity)
                        );
                }
                else
                {
                    state.Initialize(
                        new Rect(Padding.Left, Padding.Top,
                                 double.PositiveInfinity, clientSize.Height + VerticalSpacing)
                        );
                }
            }

            for (int i = 0; i < context.ItemCount; i++)
            {
                var item = state.GetOrCreateItemAt(i);

                bool measured = false;

                if (item.Bounds.IsEmpty())//measure empty
                {
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(clientSize);
                    item.Width  = item.Element.DesiredSize.Width;
                    item.Height = item.Element.DesiredSize.Height;
                    state.FitItem(item);
                    measured = true;
                }

                item.ShouldDisplay = context.RealizationRect.IsIntersect(item.Bounds);
                if (!item.ShouldDisplay)
                {
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }
                }
                else if (!measured)//measure in view rect
                {
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(clientSize);
                    var childSize = item.Element.DesiredSize;
                    if (item.Width != childSize.Width || item.Height != childSize.Height)  //size changed
                    {
                        item.Width  = childSize.Width;
                        item.Height = childSize.Height;
                        state.RemoveItemsFrom(i + 1);//remove after this
                        state.FitItem(item);
                    }
                }
            }

            var size = state.GetTotalSize();

            //var size = state.GetVirtualizedSize();
            requiredSize.Width  += size.Width;
            requiredSize.Height += size.Height;
            return(requiredSize);
        }
示例#22
0
        /// <inheritdoc/>
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            if (context.ItemCount == 0)
            {
                return(new Size(availableSize.Width, 0));
            }

            if ((context.RealizationRect.Width == 0) && (context.RealizationRect.Height == 0))
            {
                return(new Size(availableSize.Width, 0.0));
            }

            var state = (StaggeredLayoutState)context.LayoutState;

            double availableWidth  = availableSize.Width;
            double availableHeight = availableSize.Height;

            double columnWidth = Math.Min(DesiredColumnWidth, availableWidth);

            if (columnWidth != state.ColumnWidth)
            {
                // The items will need to be remeasured
                state.Clear();
            }

            state.ColumnWidth = Math.Min(DesiredColumnWidth, availableWidth);
            int numColumns = Math.Max(1, (int)Math.Floor(availableWidth / state.ColumnWidth));

            // adjust for column spacing on all columns expect the first
            double totalWidth = state.ColumnWidth + ((numColumns - 1) * (state.ColumnWidth + ColumnSpacing));

            if (totalWidth > availableWidth)
            {
                numColumns--;
            }
            else if (double.IsInfinity(availableWidth))
            {
                availableWidth = totalWidth;
            }

            if (numColumns != state.NumberOfColumns)
            {
                // The items will not need to be remeasured, but they will need to go into new columns
                state.ClearColumns();
            }

            if (RowSpacing != state.RowSpacing)
            {
                // If the RowSpacing changes the height of the rows will be different.
                // The columns stores the height so we'll want to clear them out to
                // get the proper height
                state.ClearColumns();
                state.RowSpacing = RowSpacing;
            }

            var columnHeights  = new double[numColumns];
            var itemsPerColumn = new int[numColumns];
            var deadColumns    = new HashSet <int>();

            for (int i = 0; i < context.ItemCount; i++)
            {
                var columnIndex = GetColumnIndex(columnHeights);

                bool          measured = false;
                StaggeredItem item     = state.GetItemAt(i);
                if (item.Height == 0)
                {
                    // Item has not been measured yet. Get the element and store the values
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(new Size(state.ColumnWidth, availableHeight));
                    item.Height = item.Element.DesiredSize.Height;
                    measured    = true;
                }

                double spacing = itemsPerColumn[columnIndex] > 0 ? RowSpacing : 0;
                item.Top = columnHeights[columnIndex] + spacing;
                double bottom = item.Top + item.Height;
                columnHeights[columnIndex] = bottom;
                itemsPerColumn[columnIndex]++;
                state.AddItemToColumn(item, columnIndex);

                if (bottom < context.RealizationRect.Top)
                {
                    // The bottom of the element is above the realization area
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }
                }
                else if (item.Top > context.RealizationRect.Bottom)
                {
                    // The top of the element is below the realization area
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }

                    deadColumns.Add(columnIndex);
                }
                else if (measured == false)
                {
                    // We ALWAYS want to measure an item that will be in the bounds
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(new Size(state.ColumnWidth, availableHeight));
                    if (item.Height != item.Element.DesiredSize.Height)
                    {
                        // this item changed size; we need to recalculate layout for everything after this
                        state.RemoveFromIndex(i + 1);
                        item.Height = item.Element.DesiredSize.Height;
                        columnHeights[columnIndex] = item.Top + item.Height;
                    }
                }

                if (deadColumns.Count == numColumns)
                {
                    break;
                }
            }

            double desiredHeight = state.GetHeight();

            return(new Size(availableWidth, desiredHeight));
        }
        /// <inheritdoc />
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var totalMeasure      = UvMeasure.Zero;
            var parentMeasure     = new UvMeasure(Orientation, availableSize.Width, availableSize.Height);
            var spacingMeasure    = new UvMeasure(Orientation, HorizontalSpacing, VerticalSpacing);
            var realizationBounds = new UvBounds(Orientation, context.RealizationRect);
            var position          = UvMeasure.Zero;

            var state = (WrapLayoutState)context.LayoutState;

            if (state.Orientation != Orientation)
            {
                state.SetOrientation(Orientation);
            }

            if (spacingMeasure.Equals(state.Spacing) == false)
            {
                state.ClearPositions();
                state.Spacing = spacingMeasure;
            }

            if (state.AvailableU != parentMeasure.U)
            {
                state.ClearPositions();
                state.AvailableU = parentMeasure.U;
            }

            double currentV = 0;

            for (int i = 0; i < context.ItemCount; i++)
            {
                bool     measured = false;
                WrapItem item     = state.GetItemAt(i);
                if (item.Measure == null)
                {
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(availableSize);
                    item.Measure = new UvMeasure(Orientation, item.Element.DesiredSize.Width, item.Element.DesiredSize.Height);
                    measured     = true;
                }

                UvMeasure currentMeasure = item.Measure.Value;
                if (currentMeasure.U == 0)
                {
                    continue; // ignore collapsed items
                }

                if (item.Position == null)
                {
                    if (parentMeasure.U < position.U + currentMeasure.U)
                    {
                        // New Row
                        position.U  = 0;
                        position.V += currentV + spacingMeasure.V;
                        currentV    = 0;
                    }

                    item.Position = position;
                }

                position = item.Position.Value;

                double vEnd = position.V + currentMeasure.V;
                if (vEnd < realizationBounds.VMin)
                {
                    // Item is "above" the bounds
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }
                }
                else if (position.V > realizationBounds.VMax)
                {
                    // Item is "below" the bounds.
                    if (item.Element != null)
                    {
                        context.RecycleElement(item.Element);
                        item.Element = null;
                    }

                    // We don't need to measure anything below the bounds
                    break;
                }
                else if (measured == false)
                {
                    // Always measure elements that are within the bounds
                    item.Element = context.GetOrCreateElementAt(i);
                    item.Element.Measure(availableSize);

                    currentMeasure = new UvMeasure(Orientation, item.Element.DesiredSize.Width, item.Element.DesiredSize.Height);
                    if (currentMeasure.Equals(item.Measure) == false)
                    {
                        // this item changed size; we need to recalculate layout for everything after this
                        state.RemoveFromIndex(i + 1);
                        item.Measure = currentMeasure;

                        // did the change make it go into the new row?
                        if (parentMeasure.U < position.U + currentMeasure.U)
                        {
                            // New Row
                            position.U  = 0;
                            position.V += currentV + spacingMeasure.V;
                            currentV    = 0;
                        }

                        item.Position = position;
                    }
                }

                position.U += currentMeasure.U + spacingMeasure.U;
                currentV    = Math.Max(currentMeasure.V, currentV);
            }

            // update value with the last line
            // if the the last loop is(parentMeasure.U > currentMeasure.U + lineMeasure.U) the total isn't calculated then calculate it
            // if the last loop is (parentMeasure.U > currentMeasure.U) the currentMeasure isn't added to the total so add it here
            // for the last condition it is zeros so adding it will make no difference
            // this way is faster than an if condition in every loop for checking the last item
            totalMeasure.U = parentMeasure.U;

            // Propagating an infinite size causes a crash. This can happen if the parent is scrollable and infinite in the opposite
            // axis to the panel. Clearing to zero prevents the crash.
            // This is likely an incorrect use of the control by the developer, however we need stability here so setting a default that wont crash.
            if (double.IsInfinity(totalMeasure.U))
            {
                totalMeasure.U = 0.0;
            }

            totalMeasure.V = state.GetHeight();

            totalMeasure.U = Math.Ceiling(totalMeasure.U);
            return(Orientation == Orientation.Horizontal ? new Size(totalMeasure.U, totalMeasure.V) : new Size(totalMeasure.V, totalMeasure.U));
        }
示例#24
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            var viewport = context.RealizationRect;

            if (availableSize.Width != m_lastAvailableWidth)
            {
                UpdateCachedBounds(availableSize);
                m_lastAvailableWidth = availableSize.Width;
            }

            // Initialize column offsets
            var numColumns  = (int)Math.Floor(availableSize.Width / Math.Min(DesiredColumnWidth, availableSize.Width));
            var columnWidth = availableSize.Width / numColumns;

            if (m_columnOffsets.Count == 0)
            {
                for (var i = 0; i < numColumns; i++)
                {
                    m_columnOffsets.Add(VerticalOffset);
                }
            }

            m_firstIndex = GetStartIndex(viewport);
            var currentIndex = m_firstIndex;
            var nextOffset   = -1.0;

            // Measure items from start index to when we hit the end of the viewport.
            while (currentIndex < context.ItemCount && nextOffset < viewport.Bottom)
            {
                var child = context.GetOrCreateElementAt(currentIndex);
                child.Measure(new Size(columnWidth, availableSize.Height));

                if (currentIndex >= m_cachedBounds.Count)
                {
                    // We do not have bounds for this index. Lay it out and cache it.
                    var columnIndex = GetIndexOfLowestColumn(m_columnOffsets, out nextOffset);
                    m_cachedBounds.Add(new Rect(columnIndex * columnWidth, nextOffset, columnWidth,
                                                child.DesiredSize.Height));
                    m_columnOffsets[columnIndex] += child.DesiredSize.Height;
                }
                //else if (child.DesiredSize.Height != m_cachedBounds[currentIndex].Height) // Item height has changed
                //{
                //    m_cachedBounds.RemoveRange(currentIndex, m_cachedBounds.Count - currentIndex);
                //    UpdateCachedBounds(availableSize);
                //    var columnIndex = GetIndexOfLowestColumn(m_columnOffsets, out nextOffset);
                //    m_cachedBounds.Add(new Rect(columnIndex * columnWidth, nextOffset, columnWidth,
                //        child.DesiredSize.Height));
                //    m_columnOffsets[columnIndex] += child.DesiredSize.Height;
                //}
                else if (currentIndex + 1 == m_cachedBounds.Count)
                {
                    // Last element. Use the next offset.
                    GetIndexOfLowestColumn(m_columnOffsets, out nextOffset);
                }
                else
                {
                    nextOffset = m_cachedBounds[currentIndex + 1].Top;
                }

                //child.Arrange(m_cachedBounds[currentIndex]);

                m_lastIndex = currentIndex;
                currentIndex++;
            }

            var extent = GetExtentSize(availableSize);

            return(extent);
        }
示例#25
0
        protected override Size MeasureOverride(VirtualizingLayoutContext context, Size availableSize)
        {
            if (context.ItemCount < 1)
            {
                return(new Size(0, 0));
            }

            // Item size is 96 + 2px of margin

            var state = context.LayoutState as MosaicLayoutState;

            if (state.LayoutRects.Count < 1)
            {
                state.LayoutRects.Clear();
                state.ActualWidth = availableSize.Width;

                var items = GetItems(context);

                var mosaic = MosaicMedia.Calculate(items);
                var top    = 0d;

                foreach (var row in mosaic)
                {
                    var left = 0d;

                    foreach (var item in row)
                    {
                        state.LayoutRects.Add(new Rect(left, top, item.Width, 98));
                        left += item.Width;
                    }

                    top += 98;
                }

                state.Rows         = mosaic;
                state.ExtentHeight = top - 2;
            }

            if (state.LayoutRects.Count < 1)
            {
                return(new Size(0, 0));
            }

            var firstRowIndex = Math.Min(Math.Max((int)(context.RealizationRect.Y / 98) - 1, 0), state.Rows.Count - 1);
            var lastRowIndex  = Math.Max(Math.Min((int)(context.RealizationRect.Bottom / 98) + 1, state.Rows.Count - 1), 0);

            var firstItemIndex = state.Rows[firstRowIndex][0].Index;
            var lastItemIndex  = state.Rows[lastRowIndex].Last().Index;

            var availableWidth = availableSize.Width + 2;

            for (int i = firstItemIndex; i <= lastItemIndex; i++)
            {
                var container = context.GetOrCreateElementAt(i);
                container.Measure(new Size(
                                      state.LayoutRects[i].Width * availableWidth,
                                      state.LayoutRects[i].Height));
            }

            state.FirstRealizedIndex = firstItemIndex;
            state.LastRealizedIndex  = lastItemIndex;

            // Report this as the desired size for the layout
            return(new Size(availableSize.Width, state.ExtentHeight));
        }
        internal void RecycleElementAt(int index)
        {
            UIElement element = _context.GetOrCreateElementAt(index);

            _context.RecycleElement(element);
        }
        private Size MeasureColumn(VirtualizingLayoutContext context, GroupedLayoutState state, Size availableSizeForElements, int headerIndex, double startingY, bool widthChanged, out int nextHeaderIndex)
        {
            // Note that you MUST call GetOrCreateElement on any items that are in the realized region... that's how
            // the control tracks which elements it shouldn't dispose.

            double y = startingY;
            int    i = headerIndex;

            var header = state.GetItemAt(headerIndex);

            //if (widthChanged || header.Height == null)
            {
                var headerEl = context.GetOrCreateElementAt(headerIndex);
                headerEl.Measure(availableSizeForElements);
                header.Height = headerEl.DesiredSize.Height;
            }

            y += header.Height.Value + AfterHeaderSpacing;

            i++;

            while (i < context.ItemCount)
            {
                if (!(context.GetItemAt(i) is ViewItemTaskOrEvent))
                {
                    // End of column
                    break;
                }

                var item = state.GetItemAt(i);

                // Logic technically ignores height of item, but heights are short enough it shouldn't matter
                if (y < context.RealizationRect.Top ||
                    y > context.RealizationRect.Bottom)
                {
                    y += item.Height.GetValueOrDefault(40);
                }
                else
                {
                    // Theoretically since tasks/events are removed and then added back when edited, we know they can never change size...
                    // Therefore we can store their measured size, and only call measure if their width changed or height unknown...
                    // However this didn't work in reality, not sure why.

                    //if (widthChanged || item.Height == null)
                    {
                        var itemEl = context.GetOrCreateElementAt(i);
                        itemEl.Measure(availableSizeForElements);
                        item.Height = itemEl.DesiredSize.Height;
                    }

                    y += item.Height.Value;
                }

                // Include item spacing
                y += ItemSpacing;

                i++;
            }

            // Remove last item spacing (since no item after it)
            y -= ItemSpacing;

            nextHeaderIndex = i;
            return(new Size(availableSizeForElements.Width, y - startingY));
        }