aboutsummaryrefslogtreecommitdiff
path: root/MediaBrowser.UI.Controls/VirtualizingWrapPanel.cs
diff options
context:
space:
mode:
Diffstat (limited to 'MediaBrowser.UI.Controls/VirtualizingWrapPanel.cs')
-rw-r--r--MediaBrowser.UI.Controls/VirtualizingWrapPanel.cs735
1 files changed, 0 insertions, 735 deletions
diff --git a/MediaBrowser.UI.Controls/VirtualizingWrapPanel.cs b/MediaBrowser.UI.Controls/VirtualizingWrapPanel.cs
deleted file mode 100644
index e9753ccea..000000000
--- a/MediaBrowser.UI.Controls/VirtualizingWrapPanel.cs
+++ /dev/null
@@ -1,735 +0,0 @@
-using System;
-using System.Collections.Specialized;
-using System.ComponentModel;
-using System.Windows;
-using System.Windows.Controls;
-using System.Windows.Controls.Primitives;
-using System.Windows.Media;
-
-namespace MediaBrowser.UI.Controls
-{
- /// <summary>
- /// http://www.codeproject.com/Articles/75847/Virtualizing-WrapPanel
- /// Positions child elements in sequential position from left to right, breaking content
- /// to the next line at the edge of the containing box. Subsequent ordering happens
- /// sequentially from top to bottom or from right to left, depending on the value of
- /// the Orientation property.
- /// </summary>
- [DefaultProperty("Orientation")]
- public class VirtualizingWrapPanel : VirtualizingPanel, IScrollInfo
- {
- /// <summary>
- /// Identifies the ItemHeight dependency property.
- /// </summary>
- public static readonly DependencyProperty ItemHeightProperty = DependencyProperty.Register("ItemHeight", typeof(double), typeof(VirtualizingWrapPanel), new PropertyMetadata(100.0, new PropertyChangedCallback(VirtualizingWrapPanel.OnAppearancePropertyChanged)));
- /// <summary>
- /// Identifies the Orientation dependency property.
- /// </summary>
- public static readonly DependencyProperty OrientationProperty = DependencyProperty.Register("Orientation", typeof(Orientation), typeof(VirtualizingWrapPanel), new PropertyMetadata(Orientation.Horizontal, new PropertyChangedCallback(VirtualizingWrapPanel.OnAppearancePropertyChanged)));
- /// <summary>
- /// Identifies the ItemWidth dependency property.
- /// </summary>
- public static readonly DependencyProperty ItemWidthProperty = DependencyProperty.Register("ItemWidth", typeof(double), typeof(VirtualizingWrapPanel), new PropertyMetadata(100.0, new PropertyChangedCallback(VirtualizingWrapPanel.OnAppearancePropertyChanged)));
- /// <summary>
- /// Identifies the ScrollStep dependency property.
- /// </summary>
- public static readonly DependencyProperty ScrollStepProperty = DependencyProperty.Register("ScrollStep", typeof(double), typeof(VirtualizingWrapPanel), new PropertyMetadata(10.0, new PropertyChangedCallback(VirtualizingWrapPanel.OnAppearancePropertyChanged)));
- private bool canHorizontallyScroll;
- private bool canVerticallyScroll;
- private Size contentExtent = new Size(0.0, 0.0);
- private Point contentOffset = default(Point);
- private ScrollViewer scrollOwner;
- private Size viewport = new Size(0.0, 0.0);
- private int previousItemCount;
- /// <summary>
- /// Gets or sets a value that specifies the height of all items that are
- /// contained within a VirtualizingWrapPanel. This is a dependency property.
- /// </summary>
- public double ItemHeight
- {
- get
- {
- return (double)base.GetValue(VirtualizingWrapPanel.ItemHeightProperty);
- }
- set
- {
- base.SetValue(VirtualizingWrapPanel.ItemHeightProperty, value);
- }
- }
- /// <summary>
- /// Gets or sets a value that specifies the width of all items that are
- /// contained within a VirtualizingWrapPanel. This is a dependency property.
- /// </summary>
- public double ItemWidth
- {
- get
- {
- return (double)base.GetValue(VirtualizingWrapPanel.ItemWidthProperty);
- }
- set
- {
- base.SetValue(VirtualizingWrapPanel.ItemWidthProperty, value);
- }
- }
- /// <summary>
- /// Gets or sets a value that specifies the dimension in which child
- /// content is arranged. This is a dependency property.
- /// </summary>
- public Orientation Orientation
- {
- get
- {
- return (Orientation)base.GetValue(VirtualizingWrapPanel.OrientationProperty);
- }
- set
- {
- base.SetValue(VirtualizingWrapPanel.OrientationProperty, value);
- }
- }
- /// <summary>
- /// Gets or sets a value that indicates whether scrolling on the horizontal axis is possible.
- /// </summary>
- public bool CanHorizontallyScroll
- {
- get
- {
- return this.canHorizontallyScroll;
- }
- set
- {
- if (this.canHorizontallyScroll != value)
- {
- this.canHorizontallyScroll = value;
- base.InvalidateMeasure();
- }
- }
- }
- /// <summary>
- /// Gets or sets a value that indicates whether scrolling on the vertical axis is possible.
- /// </summary>
- public bool CanVerticallyScroll
- {
- get
- {
- return this.canVerticallyScroll;
- }
- set
- {
- if (this.canVerticallyScroll != value)
- {
- this.canVerticallyScroll = value;
- base.InvalidateMeasure();
- }
- }
- }
- /// <summary>
- /// Gets or sets a ScrollViewer element that controls scrolling behavior.
- /// </summary>
- public ScrollViewer ScrollOwner
- {
- get
- {
- return this.scrollOwner;
- }
- set
- {
- this.scrollOwner = value;
- }
- }
- /// <summary>
- /// Gets the vertical offset of the scrolled content.
- /// </summary>
- public double VerticalOffset
- {
- get
- {
- return this.contentOffset.Y;
- }
- }
- /// <summary>
- /// Gets the vertical size of the viewport for this content.
- /// </summary>
- public double ViewportHeight
- {
- get
- {
- return this.viewport.Height;
- }
- }
- /// <summary>
- /// Gets the horizontal size of the viewport for this content.
- /// </summary>
- public double ViewportWidth
- {
- get
- {
- return this.viewport.Width;
- }
- }
- /// <summary>
- /// Gets or sets a value for mouse wheel scroll step.
- /// </summary>
- public double ScrollStep
- {
- get
- {
- return (double)base.GetValue(VirtualizingWrapPanel.ScrollStepProperty);
- }
- set
- {
- base.SetValue(VirtualizingWrapPanel.ScrollStepProperty, value);
- }
- }
- /// <summary>
- /// Gets the vertical size of the extent.
- /// </summary>
- public double ExtentHeight
- {
- get
- {
- return this.contentExtent.Height;
- }
- }
- /// <summary>
- /// Gets the horizontal size of the extent.
- /// </summary>
- public double ExtentWidth
- {
- get
- {
- return this.contentExtent.Width;
- }
- }
- /// <summary>
- /// Gets the horizontal offset of the scrolled content.
- /// </summary>
- public double HorizontalOffset
- {
- get
- {
- return this.contentOffset.X;
- }
- }
- /// <summary>
- /// Scrolls down within content by one logical unit.
- /// </summary>
- public void LineDown()
- {
- this.SetVerticalOffset(this.VerticalOffset + this.ScrollStep);
- }
- /// <summary>
- /// Scrolls left within content by one logical unit.
- /// </summary>
- public void LineLeft()
- {
- this.SetHorizontalOffset(this.HorizontalOffset - this.ScrollStep);
- }
- /// <summary>
- /// Scrolls right within content by one logical unit.
- /// </summary>
- public void LineRight()
- {
- this.SetHorizontalOffset(this.HorizontalOffset + this.ScrollStep);
- }
- /// <summary>
- /// Scrolls up within content by one logical unit.
- /// </summary>
- public void LineUp()
- {
- this.SetVerticalOffset(this.VerticalOffset - this.ScrollStep);
- }
- /// <summary>
- /// Forces content to scroll until the coordinate space of a Visual object is visible.
- /// </summary>
- public Rect MakeVisible(Visual visual, Rect rectangle)
- {
- this.MakeVisible(visual as UIElement);
- return rectangle;
- }
- /// <summary>
- /// Scrolls down within content after a user clicks the wheel button on a mouse.
- /// </summary>
- public void MouseWheelDown()
- {
- this.SetVerticalOffset(this.VerticalOffset + this.ScrollStep);
- }
- /// <summary>
- /// Scrolls left within content after a user clicks the wheel button on a mouse.
- /// </summary>
- public void MouseWheelLeft()
- {
- this.SetHorizontalOffset(this.HorizontalOffset - this.ScrollStep);
- }
- /// <summary>
- /// Scrolls right within content after a user clicks the wheel button on a mouse.
- /// </summary>
- public void MouseWheelRight()
- {
- this.SetHorizontalOffset(this.HorizontalOffset + this.ScrollStep);
- }
- /// <summary>
- /// Scrolls up within content after a user clicks the wheel button on a mouse.
- /// </summary>
- public void MouseWheelUp()
- {
- this.SetVerticalOffset(this.VerticalOffset - this.ScrollStep);
- }
- /// <summary>
- /// Scrolls down within content by one page.
- /// </summary>
- public void PageDown()
- {
- this.SetVerticalOffset(this.VerticalOffset + this.ViewportHeight);
- }
- /// <summary>
- /// Scrolls left within content by one page.
- /// </summary>
- public void PageLeft()
- {
- this.SetHorizontalOffset(this.HorizontalOffset - this.ViewportHeight);
- }
- /// <summary>
- /// Scrolls right within content by one page.
- /// </summary>
- public void PageRight()
- {
- this.SetHorizontalOffset(this.HorizontalOffset + this.ViewportHeight);
- }
- /// <summary>
- /// Scrolls up within content by one page.
- /// </summary>
- public void PageUp()
- {
- this.SetVerticalOffset(this.VerticalOffset - this.viewport.Height);
- }
- /// <summary>
- /// Sets the amount of vertical offset.
- /// </summary>
- public void SetVerticalOffset(double offset)
- {
- if (offset < 0.0 || this.ViewportHeight >= this.ExtentHeight)
- {
- offset = 0.0;
- }
- else
- {
- if (offset + this.ViewportHeight >= this.ExtentHeight)
- {
- offset = this.ExtentHeight - this.ViewportHeight;
- }
- }
- this.contentOffset.Y = offset;
- if (this.ScrollOwner != null)
- {
- this.ScrollOwner.InvalidateScrollInfo();
- }
- base.InvalidateMeasure();
- }
- /// <summary>
- /// Sets the amount of horizontal offset.
- /// </summary>
- public void SetHorizontalOffset(double offset)
- {
- if (offset < 0.0 || this.ViewportWidth >= this.ExtentWidth)
- {
- offset = 0.0;
- }
- else
- {
- if (offset + this.ViewportWidth >= this.ExtentWidth)
- {
- offset = this.ExtentWidth - this.ViewportWidth;
- }
- }
- this.contentOffset.X = offset;
- if (this.ScrollOwner != null)
- {
- this.ScrollOwner.InvalidateScrollInfo();
- }
- base.InvalidateMeasure();
- }
- /// <summary>
- /// Note: Works only for vertical.
- /// </summary>
- internal void PageLast()
- {
- this.contentOffset.Y = this.ExtentHeight;
- if (this.ScrollOwner != null)
- {
- this.ScrollOwner.InvalidateScrollInfo();
- }
- base.InvalidateMeasure();
- }
- /// <summary>
- /// Note: Works only for vertical.
- /// </summary>
- internal void PageFirst()
- {
- this.contentOffset.Y = 0.0;
- if (this.ScrollOwner != null)
- {
- this.ScrollOwner.InvalidateScrollInfo();
- }
- base.InvalidateMeasure();
- }
- /// <summary>
- /// When items are removed, remove the corresponding UI if necessary.
- /// </summary>
- /// <param name="sender"></param>
- /// <param name="args"></param>
- protected override void OnItemsChanged(object sender, ItemsChangedEventArgs args)
- {
- switch (args.Action)
- {
- case NotifyCollectionChangedAction.Remove:
- case NotifyCollectionChangedAction.Replace:
- case NotifyCollectionChangedAction.Move:
- base.RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
- return;
- case NotifyCollectionChangedAction.Reset:
- {
- ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);
- if (itemsControl != null)
- {
- if (this.previousItemCount != itemsControl.Items.Count)
- {
- if (this.Orientation == Orientation.Horizontal)
- {
- this.SetVerticalOffset(0.0);
- }
- else
- {
- this.SetHorizontalOffset(0.0);
- }
- }
- this.previousItemCount = itemsControl.Items.Count;
- }
- return;
- }
- default:
- return;
- }
- }
- /// <summary>
- /// Measure the children.
- /// </summary>
- /// <param name="availableSize">The available size.</param>
- /// <returns>The desired size.</returns>
- protected override Size MeasureOverride(Size availableSize)
- {
- this.InvalidateScrollInfo(availableSize);
- int firstVisibleIndex;
- int lastVisibleIndex;
- if (this.Orientation == Orientation.Horizontal)
- {
- this.GetVerticalVisibleRange(out firstVisibleIndex, out lastVisibleIndex);
- }
- else
- {
- this.GetHorizontalVisibleRange(out firstVisibleIndex, out lastVisibleIndex);
- }
- UIElementCollection children = base.Children;
- IItemContainerGenerator generator = base.ItemContainerGenerator;
- if (generator != null)
- {
- GeneratorPosition startPos = generator.GeneratorPositionFromIndex(firstVisibleIndex);
- int childIndex = (startPos.Offset == 0) ? startPos.Index : (startPos.Index + 1);
- if (childIndex == -1)
- {
- this.RefreshOffset();
- }
- using (generator.StartAt(startPos, GeneratorDirection.Forward, true))
- {
- int itemIndex = firstVisibleIndex;
- while (itemIndex <= lastVisibleIndex)
- {
- bool newlyRealized;
- UIElement child = generator.GenerateNext(out newlyRealized) as UIElement;
- if (newlyRealized)
- {
- if (childIndex >= children.Count)
- {
- base.AddInternalChild(child);
- }
- else
- {
- base.InsertInternalChild(childIndex, child);
- }
- generator.PrepareItemContainer(child);
- }
- if (child != null)
- {
- child.Measure(new Size(this.ItemWidth, this.ItemHeight));
- }
- itemIndex++;
- childIndex++;
- }
- }
- this.CleanUpChildren(firstVisibleIndex, lastVisibleIndex);
- }
- if (IsCloseTo(availableSize.Height, double.PositiveInfinity) || IsCloseTo(availableSize.Width, double.PositiveInfinity))
- {
- return base.MeasureOverride(availableSize);
- }
-
- var itemsControl = ItemsControl.GetItemsOwner(this);
- var numItems = itemsControl.Items.Count;
-
- var width = availableSize.Width;
- var height = availableSize.Height;
-
- if (Orientation == Orientation.Vertical)
- {
- var numRows = Math.Floor(availableSize.Height / ItemHeight);
-
- height = numRows * ItemHeight;
-
- var requiredColumns = Math.Ceiling(numItems / numRows);
-
- width = Math.Min(requiredColumns * ItemWidth, width);
- }
- else
- {
- var numColumns = Math.Floor(availableSize.Width / ItemWidth);
-
- width = numColumns * ItemWidth;
-
- //if (numItems > 0 && numItems < numColumns)
- //{
- // width = Math.Min(numColumns, numItems) * ItemWidth;
- //}
-
- var requiredRows = Math.Ceiling(numItems / numColumns);
-
- height = Math.Min(requiredRows * ItemHeight, height);
- }
-
- return new Size(width, height);
- }
-
- /// <summary>
- /// Arranges the children.
- /// </summary>
- /// <param name="finalSize">The available size.</param>
- /// <returns>The used size.</returns>
- protected override Size ArrangeOverride(Size finalSize)
- {
- bool isHorizontal = this.Orientation == Orientation.Horizontal;
- this.InvalidateScrollInfo(finalSize);
- int i = 0;
- foreach (object item in base.Children)
- {
- this.ArrangeChild(isHorizontal, finalSize, i++, item as UIElement);
- }
- return finalSize;
- }
- private static void OnAppearancePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
- {
- UIElement panel = d as UIElement;
- if (panel != null)
- {
- panel.InvalidateMeasure();
- }
- }
- private void MakeVisible(UIElement element)
- {
- ItemContainerGenerator generator = base.ItemContainerGenerator.GetItemContainerGeneratorForPanel(this);
- if (element != null && generator != null)
- {
- for (int itemIndex = generator.IndexFromContainer(element); itemIndex == -1; itemIndex = generator.IndexFromContainer(element))
- {
- element = element.ParentOfType<UIElement>();
- }
- ScrollViewer scrollViewer = element.ParentOfType<ScrollViewer>();
- if (scrollViewer != null)
- {
- GeneralTransform elementTransform = element.TransformToVisual(scrollViewer);
- Rect elementRectangle = elementTransform.TransformBounds(new Rect(new Point(0.0, 0.0), element.RenderSize));
-
- if (this.Orientation == Orientation.Horizontal)
- {
- var padding = ItemHeight / 3;
-
- if (elementRectangle.Bottom > this.ViewportHeight)
- {
- this.SetVerticalOffset(this.contentOffset.Y + elementRectangle.Bottom - this.ViewportHeight + padding);
- return;
- }
- if (elementRectangle.Top < 0.0)
- {
- this.SetVerticalOffset(this.contentOffset.Y + elementRectangle.Top - padding);
- return;
- }
- }
- else
- {
- var padding = ItemWidth / 3;
-
- if (elementRectangle.Right > this.ViewportWidth)
- {
- this.SetHorizontalOffset(this.contentOffset.X + elementRectangle.Right - this.ViewportWidth + padding);
- return;
- }
- if (elementRectangle.Left < 0.0)
- {
- this.SetHorizontalOffset(this.contentOffset.X + elementRectangle.Left - padding);
- }
- }
- }
- }
- }
- private void GetVerticalVisibleRange(out int firstVisibleItemIndex, out int lastVisibleItemIndex)
- {
- int childrenPerRow = this.GetVerticalChildrenCountPerRow(this.contentExtent);
- firstVisibleItemIndex = (int)Math.Floor(this.VerticalOffset / this.ItemHeight) * childrenPerRow;
- lastVisibleItemIndex = (int)Math.Ceiling((this.VerticalOffset + this.ViewportHeight) / this.ItemHeight) * childrenPerRow - 1;
- this.AdjustVisibleRange(ref firstVisibleItemIndex, ref lastVisibleItemIndex);
- }
- private void GetHorizontalVisibleRange(out int firstVisibleItemIndex, out int lastVisibleItemIndex)
- {
- int childrenPerRow = this.GetHorizontalChildrenCountPerRow(this.contentExtent);
- firstVisibleItemIndex = (int)Math.Floor(this.HorizontalOffset / this.ItemWidth) * childrenPerRow;
- lastVisibleItemIndex = (int)Math.Ceiling((this.HorizontalOffset + this.ViewportWidth) / this.ItemWidth) * childrenPerRow - 1;
- this.AdjustVisibleRange(ref firstVisibleItemIndex, ref lastVisibleItemIndex);
- }
- private void AdjustVisibleRange(ref int firstVisibleItemIndex, ref int lastVisibleItemIndex)
- {
- firstVisibleItemIndex--;
- lastVisibleItemIndex++;
- ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);
- if (itemsControl != null)
- {
- if (firstVisibleItemIndex < 0)
- {
- firstVisibleItemIndex = 0;
- }
- if (lastVisibleItemIndex >= itemsControl.Items.Count)
- {
- lastVisibleItemIndex = itemsControl.Items.Count - 1;
- }
- }
- }
- private void CleanUpChildren(int minIndex, int maxIndex)
- {
- UIElementCollection children = base.Children;
- IItemContainerGenerator generator = base.ItemContainerGenerator;
- for (int i = children.Count - 1; i >= 0; i--)
- {
- GeneratorPosition pos = new GeneratorPosition(i, 0);
- int itemIndex = generator.IndexFromGeneratorPosition(pos);
- if (itemIndex < minIndex || itemIndex > maxIndex)
- {
- generator.Remove(pos, 1);
- base.RemoveInternalChildRange(i, 1);
- }
- }
- }
- private void ArrangeChild(bool isHorizontal, Size finalSize, int index, UIElement child)
- {
- if (child == null)
- {
- return;
- }
- int count = isHorizontal ? this.GetVerticalChildrenCountPerRow(finalSize) : this.GetHorizontalChildrenCountPerRow(finalSize);
- int itemIndex = base.ItemContainerGenerator.IndexFromGeneratorPosition(new GeneratorPosition(index, 0));
- int row = isHorizontal ? (itemIndex / count) : (itemIndex % count);
- int column = isHorizontal ? (itemIndex % count) : (itemIndex / count);
- Rect rect = new Rect((double)column * this.ItemWidth, (double)row * this.ItemHeight, this.ItemWidth, this.ItemHeight);
- if (isHorizontal)
- {
- rect.Y -= this.VerticalOffset;
- }
- else
- {
- rect.X -= this.HorizontalOffset;
- }
- child.Arrange(rect);
- }
- private void InvalidateScrollInfo(Size availableSize)
- {
- ItemsControl ownerItemsControl = ItemsControl.GetItemsOwner(this);
- if (ownerItemsControl != null)
- {
- Size extent = this.GetExtent(availableSize, ownerItemsControl.Items.Count);
- if (extent != this.contentExtent)
- {
- this.contentExtent = extent;
- this.RefreshOffset();
- }
- if (availableSize != this.viewport)
- {
- this.viewport = availableSize;
- this.InvalidateScrollOwner();
- }
- }
- }
- private void RefreshOffset()
- {
- if (this.Orientation == Orientation.Horizontal)
- {
- this.SetVerticalOffset(this.VerticalOffset);
- return;
- }
- this.SetHorizontalOffset(this.HorizontalOffset);
- }
- private void InvalidateScrollOwner()
- {
- if (this.ScrollOwner != null)
- {
- this.ScrollOwner.InvalidateScrollInfo();
- }
- }
- private Size GetExtent(Size availableSize, int itemCount)
- {
- if (this.Orientation == Orientation.Horizontal)
- {
- int childrenPerRow = this.GetVerticalChildrenCountPerRow(availableSize);
- return new Size((double)childrenPerRow * this.ItemWidth, this.ItemHeight * Math.Ceiling((double)itemCount / (double)childrenPerRow));
- }
- int childrenPerRow2 = this.GetHorizontalChildrenCountPerRow(availableSize);
- return new Size(this.ItemWidth * Math.Ceiling((double)itemCount / (double)childrenPerRow2), (double)childrenPerRow2 * this.ItemHeight);
- }
- private int GetVerticalChildrenCountPerRow(Size availableSize)
- {
- int childrenCountPerRow;
- if (availableSize.Width == double.PositiveInfinity)
- {
- childrenCountPerRow = base.Children.Count;
- }
- else
- {
- childrenCountPerRow = Math.Max(1, (int)Math.Floor(availableSize.Width / this.ItemWidth));
- }
- return childrenCountPerRow;
- }
- private int GetHorizontalChildrenCountPerRow(Size availableSize)
- {
- int childrenCountPerRow;
- if (availableSize.Height == double.PositiveInfinity)
- {
- childrenCountPerRow = base.Children.Count;
- }
- else
- {
- childrenCountPerRow = Math.Max(1, (int)Math.Floor(availableSize.Height / this.ItemHeight));
- }
- return childrenCountPerRow;
- }
-
- private static bool IsCloseTo(double value1, double value2)
- {
- return AreClose(value1, value2);
- }
-
- private static bool AreClose(double value1, double value2)
- {
- if (value1 == value2)
- {
- return true;
- }
- double num = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * 2.2204460492503131E-16;
- double num2 = value1 - value2;
- return -num < num2 && num > num2;
- }
- }
-} \ No newline at end of file