/ViewOnTv/Client/ViewOnClient/UI/Control/Panel/VirtualizingVerticalWrapPanel.cs

# · C# · 386 lines · 328 code · 51 blank · 7 comment · 28 complexity · e54f2ebefab14ad1f236e7833a523793 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Windows.Controls;
  5. using System.Windows.Controls.Primitives;
  6. using System.Windows;
  7. using System.Windows.Media;
  8. using System.Diagnostics;
  9. namespace ViewOn.UI.Control
  10. {
  11. public class VirtualizingVerticalWrapPanel : VirtualizingPanel, IScrollInfo
  12. {
  13. public VirtualizingVerticalWrapPanel()
  14. {
  15. renderTransform = new TranslateTransform();
  16. this.RenderTransform = renderTransform;
  17. }
  18. protected override System.Windows.Size MeasureOverride(
  19. Size constraint)
  20. {
  21. // How big an area have we got to play with?
  22. bool invalidate = (viewport != constraint);
  23. viewport = constraint;
  24. // How big would things like to be? Note - this is "rough"
  25. // because it changes when we animate the current picture.
  26. DetermineStandardItemSize();
  27. // How big is our entire area then?
  28. int itemsPerLine = ItemsPerLine;
  29. Size newExtent = new Size(constraint.Width,
  30. Math.Ceiling((double)ItemCount / (double)itemsPerLine) * itemHeight);
  31. invalidate = (invalidate) || (newExtent != extent);
  32. extent = newExtent;
  33. RealizeVisibleItems();
  34. foreach (UIElement element in this.InternalChildren)
  35. {
  36. element.Measure(maxSize);
  37. }
  38. if (invalidate && (scrollOwner != null))
  39. {
  40. scrollOwner.InvalidateScrollInfo();
  41. }
  42. return (constraint);
  43. }
  44. private int ItemsPerLine
  45. {
  46. get
  47. {
  48. return ((int)(viewport.Width / itemWidth));
  49. }
  50. }
  51. private int FirstItemVisibleInViewport
  52. {
  53. get
  54. {
  55. int firstItem =
  56. (int)((verticalOffset / itemHeight) * ItemsPerLine);
  57. return (firstItem);
  58. }
  59. }
  60. private int LastItemVisibleInViewport
  61. {
  62. get
  63. {
  64. double lines = (viewport.Height / itemHeight);
  65. double items = lines * ItemsPerLine;
  66. int lastItem = FirstItemVisibleInViewport +
  67. (int)Math.Ceiling(items);
  68. lastItem--;
  69. lastItem = Math.Min(lastItem, ItemCount - 1);
  70. return (lastItem);
  71. }
  72. }
  73. private void RealizeVisibleItems()
  74. {
  75. IItemContainerGenerator generator = this.ItemContainerGenerator;
  76. int i = 0;
  77. for (i = FirstItemVisibleInViewport;
  78. i <= LastItemVisibleInViewport; i++)
  79. {
  80. GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
  81. // Should be visible
  82. if (pos.Offset != 0)
  83. {
  84. // Virtualised so we need to fix.
  85. using (generator.StartAt(pos, GeneratorDirection.Forward))
  86. {
  87. UIElement element = generator.GenerateNext() as UIElement;
  88. generator.PrepareItemContainer(element);
  89. pos = generator.GeneratorPositionFromIndex(i);
  90. this.InsertInternalChild(pos.Index, element);
  91. }
  92. }
  93. }
  94. i = FirstItemVisibleInViewport - 1;
  95. while (i >= 0)
  96. {
  97. GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
  98. if (pos.Offset == 0)
  99. {
  100. this.RemoveInternalChildRange(pos.Index, 1);
  101. generator.Remove(pos, 1);
  102. }
  103. else
  104. {
  105. break;
  106. }
  107. i--;
  108. }
  109. i = LastItemVisibleInViewport + 1;
  110. while (i < this.ItemCount)
  111. {
  112. GeneratorPosition pos = generator.GeneratorPositionFromIndex(i);
  113. if (pos.Offset == 0)
  114. {
  115. this.RemoveInternalChildRange(pos.Index, 1);
  116. generator.Remove(pos, 1);
  117. }
  118. else
  119. {
  120. break;
  121. }
  122. i++;
  123. }
  124. }
  125. private void RealizeFirstItem()
  126. {
  127. IItemContainerGenerator generator = this.ItemContainerGenerator;
  128. GeneratorPosition pos = generator.GeneratorPositionFromIndex(0);
  129. using (generator.StartAt(pos, GeneratorDirection.Forward))
  130. {
  131. UIElement element = generator.GenerateNext() as UIElement;
  132. generator.PrepareItemContainer(element);
  133. this.AddInternalChild(element);
  134. }
  135. }
  136. private void DetermineStandardItemSize()
  137. {
  138. if ((itemWidth == 0) || (itemHeight == 0))
  139. {
  140. if (this.InternalChildren.Count == 0)
  141. {
  142. RealizeFirstItem();
  143. }
  144. UIElement element = this.InternalChildren[0];
  145. element.Measure(maxSize);
  146. itemWidth = element.DesiredSize.Width;
  147. itemHeight = element.DesiredSize.Height;
  148. }
  149. }
  150. private int ItemCount
  151. {
  152. get
  153. {
  154. int count = 0;
  155. ItemsControl itemsControl = ItemsControl.GetItemsOwner(this);
  156. if ((itemsControl != null) && (itemsControl.Items != null))
  157. {
  158. count = itemsControl.Items.Count;
  159. }
  160. return (count);
  161. }
  162. }
  163. protected override System.Windows.Size ArrangeOverride(
  164. System.Windows.Size finalSize)
  165. {
  166. double xPos = 0.0d;
  167. double yPos = verticalOffset;
  168. double maxHeightOnLine = 0.0d;
  169. foreach (UIElement element in this.InternalChildren)
  170. {
  171. Rect itemSize = new Rect(element.DesiredSize);
  172. if ((xPos + itemSize.Width) > finalSize.Width)
  173. {
  174. xPos = 0.0d;
  175. yPos = yPos + maxHeightOnLine;
  176. maxHeightOnLine = 0.0d;
  177. }
  178. element.Arrange(new Rect(xPos, yPos,
  179. itemSize.Width, itemSize.Height));
  180. maxHeightOnLine = Math.Max(maxHeightOnLine, itemSize.Height);
  181. xPos += itemSize.Width;
  182. }
  183. return (finalSize);
  184. }
  185. #region IScrollInfo Members
  186. public bool CanHorizontallyScroll
  187. {
  188. get
  189. {
  190. return (false);
  191. }
  192. set
  193. {
  194. }
  195. }
  196. private bool canVScroll;
  197. public bool CanVerticallyScroll
  198. {
  199. get
  200. {
  201. return (canVScroll);
  202. }
  203. set
  204. {
  205. canVScroll = value;
  206. }
  207. }
  208. public double ExtentHeight
  209. {
  210. get
  211. {
  212. return (extent.Height);
  213. }
  214. }
  215. public double ExtentWidth
  216. {
  217. get
  218. {
  219. return (extent.Width);
  220. }
  221. }
  222. public double HorizontalOffset
  223. {
  224. get
  225. {
  226. return (0.0d);
  227. }
  228. }
  229. public void LineDown()
  230. {
  231. SetVerticalOffset(verticalOffset + 1);
  232. }
  233. public void LineLeft()
  234. {
  235. }
  236. public void LineRight()
  237. {
  238. }
  239. public void LineUp()
  240. {
  241. SetVerticalOffset(verticalOffset - 1);
  242. }
  243. public System.Windows.Rect MakeVisible(
  244. System.Windows.Media.Visual visual, System.Windows.Rect rectangle)
  245. {
  246. throw new Exception("The method or operation is not implemented.");
  247. }
  248. public void MouseWheelDown()
  249. {
  250. SetVerticalOffset(verticalOffset + itemHeight);
  251. }
  252. public void MouseWheelLeft()
  253. {
  254. }
  255. public void MouseWheelRight()
  256. {
  257. }
  258. public void MouseWheelUp()
  259. {
  260. SetVerticalOffset(verticalOffset - itemHeight);
  261. }
  262. public void PageDown()
  263. {
  264. SetVerticalOffset(verticalOffset + itemHeight);
  265. }
  266. public void PageLeft()
  267. {
  268. }
  269. public void PageRight()
  270. {
  271. }
  272. public void PageUp()
  273. {
  274. SetVerticalOffset(verticalOffset - itemHeight);
  275. }
  276. public ScrollViewer ScrollOwner
  277. {
  278. get
  279. {
  280. return (scrollOwner);
  281. }
  282. set
  283. {
  284. scrollOwner = value;
  285. }
  286. }
  287. public void SetHorizontalOffset(double offset)
  288. {
  289. // We don't horizontally scroll
  290. }
  291. public void SetVerticalOffset(double offset)
  292. {
  293. offset = Math.Max(0.0d, offset);
  294. offset = Math.Min(extent.Height - viewport.Height,
  295. offset);
  296. verticalOffset = offset;
  297. renderTransform.Y = 0 - verticalOffset;
  298. RealizeVisibleItems();
  299. if (scrollOwner != null)
  300. {
  301. scrollOwner.InvalidateScrollInfo();
  302. }
  303. }
  304. public double VerticalOffset
  305. {
  306. get
  307. {
  308. return (verticalOffset);
  309. }
  310. }
  311. public double ViewportHeight
  312. {
  313. get
  314. {
  315. return (viewport.Height);
  316. }
  317. }
  318. public double ViewportWidth
  319. {
  320. get
  321. {
  322. return (viewport.Width);
  323. }
  324. }
  325. #endregion
  326. private ScrollViewer scrollOwner;
  327. private Size extent;
  328. private Size viewport;
  329. private double verticalOffset;
  330. private TranslateTransform renderTransform;
  331. private double itemWidth;
  332. private double itemHeight;
  333. private readonly Size maxSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
  334. }
  335. }