/ViewOnTv/Client/ViewOnClient/UI/Control/Panel/VirtualizingVerticalWrapPanel.cs
# · C# · 386 lines · 328 code · 51 blank · 7 comment · 28 complexity · e54f2ebefab14ad1f236e7833a523793 MD5 · raw file
- using System;
- using System.Collections.Generic;
- using System.Text;
- using System.Windows.Controls;
- using System.Windows.Controls.Primitives;
- using System.Windows;
- using System.Windows.Media;
- using System.Diagnostics;
-
- namespace ViewOn.UI.Control
- {
- public class VirtualizingVerticalWrapPanel : VirtualizingPanel, IScrollInfo
- {
- public VirtualizingVerticalWrapPanel()
- {
- renderTransform = new TranslateTransform();
- this.RenderTransform = renderTransform;
- }
- protected override System.Windows.Size MeasureOverride(
- Size constraint)
- {
- // How big an area have we got to play with?
- bool invalidate = (viewport != constraint);
- viewport = constraint;
-
- // How big would things like to be? Note - this is "rough"
- // because it changes when we animate the current picture.
- DetermineStandardItemSize();
-
- // How big is our entire area then?
- int itemsPerLine = ItemsPerLine;
-
- Size newExtent = new Size(constraint.Width,
- Math.Ceiling((double)ItemCount / (double)itemsPerLine) * itemHeight);
-
- invalidate = (invalidate) || (newExtent != extent);
- extent = newExtent;
-
- RealizeVisibleItems();
-
- foreach (UIElement element in this.InternalChildren)
- {
- element.Measure(maxSize);
- }
-
- if (invalidate && (scrollOwner != null))
- {
- scrollOwner.InvalidateScrollInfo();
- }
- return (constraint);
- }
- private int ItemsPerLine
- {
- get
- {
- return ((int)(viewport.Width / itemWidth));
- }
- }
- private int FirstItemVisibleInViewport
- {
- get
- {
- int firstItem =
- (int)((verticalOffset / itemHeight) * ItemsPerLine);
-
- return (firstItem);
- }
- }
- private int LastItemVisibleInViewport
- {
- get
- {
- double lines = (viewport.Height / itemHeight);
- double items = lines * ItemsPerLine;
-
- int lastItem = FirstItemVisibleInViewport +
- (int)Math.Ceiling(items);
-
- lastItem--;
-
- lastItem = Math.Min(lastItem, ItemCount - 1);
-
- return (lastItem);
- }
- }
- private void RealizeVisibleItems()
- {
- IItemContainerGenerator generator = this.ItemContainerGenerator;
-
- int i = 0;
-
- for (i = FirstItemVisibleInViewport;
- i <= LastItemVisibleInViewport; i++)
- {
- GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
-
- // Should be visible
- if (pos.Offset != 0)
- {
- // Virtualised so we need to fix.
- using (generator.StartAt(pos, GeneratorDirection.Forward))
- {
- UIElement element = generator.GenerateNext() as UIElement;
- generator.PrepareItemContainer(element);
-
- pos = generator.GeneratorPositionFromIndex(i);
-
- this.InsertInternalChild(pos.Index, element);
- }
- }
- }
- i = FirstItemVisibleInViewport - 1;
-
- while (i >= 0)
- {
- GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
-
- if (pos.Offset == 0)
- {
- this.RemoveInternalChildRange(pos.Index, 1);
- generator.Remove(pos, 1);
- }
- else
- {
- break;
- }
- i--;
- }
-
- i = LastItemVisibleInViewport + 1;
-
- while (i < this.ItemCount)
- {
- GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
-
- if (pos.Offset == 0)
- {
- this.RemoveInternalChildRange(pos.Index, 1);
- generator.Remove(pos, 1);
- }
- else
- {
- break;
- }
- i++;
- }
- }
- private void RealizeFirstItem()
- {
- IItemContainerGenerator generator = this.ItemContainerGenerator;
- GeneratorPosition pos = generator.GeneratorPositionFromIndex(0);
-
- using (generator.StartAt(pos, GeneratorDirection.Forward))
- {
- UIElement element = generator.GenerateNext() as UIElement;
-
- generator.PrepareItemContainer(element);
-
- this.AddInternalChild(element);
- }
- }
- private void DetermineStandardItemSize()
- {
- if ((itemWidth == 0) || (itemHeight == 0))
- {
- if (this.InternalChildren.Count == 0)
- {
- RealizeFirstItem();
- }
- UIElement element = this.InternalChildren[0];
- element.Measure(maxSize);
-
- itemWidth = element.DesiredSize.Width;
- itemHeight = element.DesiredSize.Height;
- }
- }
- private int ItemCount
- {
- get
- {
- int count = 0;
-
- ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);
-
- if ((itemsControl != null) && (itemsControl.Items != null))
- {
- count = itemsControl.Items.Count;
- }
- return (count);
- }
- }
- protected override System.Windows.Size ArrangeOverride(
- System.Windows.Size finalSize)
- {
- double xPos = 0.0d;
- double yPos = verticalOffset;
- double maxHeightOnLine = 0.0d;
-
- foreach (UIElement element in this.InternalChildren)
- {
- Rect itemSize = new Rect(element.DesiredSize);
-
- if ((xPos + itemSize.Width) > finalSize.Width)
- {
- xPos = 0.0d;
- yPos = yPos + maxHeightOnLine;
- maxHeightOnLine = 0.0d;
- }
- element.Arrange(new Rect(xPos, yPos,
- itemSize.Width, itemSize.Height));
-
- maxHeightOnLine = Math.Max(maxHeightOnLine, itemSize.Height);
-
- xPos += itemSize.Width;
- }
- return (finalSize);
- }
- #region IScrollInfo Members
-
- public bool CanHorizontallyScroll
- {
- get
- {
- return (false);
- }
- set
- {
- }
- }
-
- private bool canVScroll;
-
- public bool CanVerticallyScroll
- {
- get
- {
- return (canVScroll);
- }
- set
- {
- canVScroll = value;
- }
- }
-
- public double ExtentHeight
- {
- get
- {
- return (extent.Height);
- }
- }
-
- public double ExtentWidth
- {
- get
- {
- return (extent.Width);
- }
- }
-
- public double HorizontalOffset
- {
- get
- {
- return (0.0d);
- }
- }
- public void LineDown()
- {
- SetVerticalOffset(verticalOffset + 1);
- }
- public void LineLeft()
- {
- }
- public void LineRight()
- {
- }
- public void LineUp()
- {
- SetVerticalOffset(verticalOffset - 1);
- }
- public System.Windows.Rect MakeVisible(
- System.Windows.Media.Visual visual, System.Windows.Rect rectangle)
- {
- throw new Exception("The method or operation is not implemented.");
- }
- public void MouseWheelDown()
- {
- SetVerticalOffset(verticalOffset + itemHeight);
- }
- public void MouseWheelLeft()
- {
- }
- public void MouseWheelRight()
- {
- }
- public void MouseWheelUp()
- {
- SetVerticalOffset(verticalOffset - itemHeight);
- }
- public void PageDown()
- {
- SetVerticalOffset(verticalOffset + itemHeight);
- }
- public void PageLeft()
- {
- }
- public void PageRight()
- {
- }
- public void PageUp()
- {
- SetVerticalOffset(verticalOffset - itemHeight);
- }
- public ScrollViewer ScrollOwner
- {
- get
- {
- return (scrollOwner);
- }
- set
- {
- scrollOwner = value;
- }
- }
-
- public void SetHorizontalOffset(double offset)
- {
- // We don't horizontally scroll
- }
-
- public void SetVerticalOffset(double offset)
- {
- offset = Math.Max(0.0d, offset);
-
- offset = Math.Min(extent.Height - viewport.Height,
- offset);
-
- verticalOffset = offset;
-
- renderTransform.Y = 0 - verticalOffset;
-
- RealizeVisibleItems();
-
- if (scrollOwner != null)
- {
- scrollOwner.InvalidateScrollInfo();
- }
- }
-
- public double VerticalOffset
- {
- get
- {
- return (verticalOffset);
- }
- }
-
- public double ViewportHeight
- {
- get
- {
- return (viewport.Height);
- }
- }
-
- public double ViewportWidth
- {
- get
- {
- return (viewport.Width);
- }
- }
-
- #endregion
-
- private ScrollViewer scrollOwner;
- private Size extent;
- private Size viewport;
- private double verticalOffset;
- private TranslateTransform renderTransform;
- private double itemWidth;
- private double itemHeight;
- private readonly Size maxSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
- }
- }