PageRenderTime 56ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/Odyssey/Odyssey/Controls/Primitives/QuickJumpWrapPanel.cs

#
C# | 271 lines | 217 code | 43 blank | 11 comment | 41 complexity | aaaa33c5f763509c399f51750c28b1ca MD5 | raw file
  1. using System;
  2. using System.Net;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Documents;
  6. using System.Windows.Ink;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using System.Windows.Media.Animation;
  10. using System.Windows.Shapes;
  11. using Odyssey.Controls.Internals;
  12. using System.Windows.Threading;
  13. using System.Collections.Generic;
  14. using Odyssey.Effects;
  15. namespace Odyssey.Controls.Primitives
  16. {
  17. /// <summary>
  18. /// Panel used with OdcListBox to display the alphabetic quick jump list.
  19. /// </summary>
  20. public class QuickJumpWrapPanel : OdcVirtualizingPanel
  21. {
  22. public QuickJumpWrapPanel()
  23. : base()
  24. {
  25. for (int i = 0; i < 28; i++)
  26. {
  27. quickJumpItems.Add(new QuickJumpListBoxItem());
  28. }
  29. for (int i = 0; i < 7; i++)
  30. {
  31. QuickJumpRowPanel panel = new QuickJumpRowPanel { ItemWidth = 112d, ItemHeight = 112d };
  32. QuickJumpSwivelEffect.SetIsElement(panel, true);
  33. panel.CacheMode = new BitmapCache();
  34. Children.Add(panel);
  35. rowPanels.Add(panel);
  36. }
  37. }
  38. private List<QuickJumpListBoxItem> quickJumpItems = new List<QuickJumpListBoxItem>();
  39. private int maxItems = 40;
  40. private DispatcherTimer timer;
  41. public double ItemWidth
  42. {
  43. get { return (double)GetValue(ItemWidthProperty); }
  44. set { SetValue(ItemWidthProperty, value); }
  45. }
  46. public static readonly DependencyProperty ItemWidthProperty =
  47. DependencyProperty.Register("ItemWidth", typeof(double), typeof(QuickJumpWrapPanel), new PropertyMetadata(112.0));
  48. public static readonly DependencyProperty ColumnCountProperty =
  49. DependencyProperty.Register("ColumnCount", typeof(int), typeof(QuickJumpWrapPanel), new PropertyMetadata(4));
  50. protected override void OnUnloaded(object sender, RoutedEventArgs e)
  51. {
  52. base.OnUnloaded(sender, e);
  53. StopTimer();
  54. }
  55. protected override Size MeasureOverride(Size availableSize)
  56. {
  57. double totalHeight = availableSize.Height;
  58. double totalWidth = availableSize.Width;
  59. IItemsControl itemsControl = ItemsControl;
  60. int count = itemsControl.ItemsSource != null ? itemsControl.ItemsSource.Count : 0;
  61. if (double.IsInfinity(totalHeight)) totalHeight = itemsControl.ItemHeight * count;
  62. if (double.IsInfinity(totalWidth)) totalWidth = 800d;
  63. if (IsInvalidated) Balance();
  64. totalHeight = totalHeight > 480d ? 800d : 480d;
  65. totalWidth = totalWidth > 480d ? 800d : 480d;
  66. return new Size(totalWidth, totalHeight);
  67. }
  68. protected override Size ArrangeOverride(Size finalSize)
  69. {
  70. int n = ItemsControl.ItemsSource.Count;
  71. double w = ItemWidth;
  72. double h = ItemsControl.ItemHeight;
  73. double h0 = finalSize.Height > 480d ? 800d : 480d;
  74. double w0 = finalSize.Width > 480d ? 800d : 480d;
  75. int numColumns = (int)Math.Floor(w0 / w);
  76. int numRows = (int)Math.Ceiling((double)n / numColumns);
  77. double left = (w0 - numColumns * w) / 2.0;
  78. double top = (h0 - numRows * h) / 2.0;
  79. int columnIndex = 0;
  80. n = elements.Count;
  81. int rowCount = 0;
  82. Rect rect = new Rect(left, top, w, h);
  83. if (n > 0)
  84. {
  85. QuickJumpRowPanel rowPanel = NextRowPanel(rowCount, ref rect, finalSize.Width);
  86. for (int i = 0; i < n; i++)
  87. {
  88. var child = elements[i];
  89. if (rowPanel != child.Parent)
  90. {
  91. if (child.Parent != null)
  92. {
  93. (child.Parent as Panel).Children.Remove(child);
  94. }
  95. rowPanel.Children.Add(child);
  96. }
  97. if (++columnIndex < numColumns)
  98. {
  99. rect.X += w;
  100. }
  101. else
  102. {
  103. rowCount++;
  104. columnIndex = 0;
  105. rect.X = left;
  106. rect.Y += h;
  107. if (i < n - 1)
  108. {
  109. rowPanel = NextRowPanel(rowCount, ref rect, finalSize.Width);
  110. }
  111. }
  112. }
  113. }
  114. rect = new Rect(left, top, w, h);
  115. foreach (var child in Children)
  116. {
  117. if (rect.Y <= finalSize.Height)
  118. {
  119. child.Arrange(rect);
  120. rect.Y = rect.Bottom;
  121. }
  122. else child.Arrange(new Rect());
  123. }
  124. return finalSize;
  125. }
  126. private QuickJumpRowPanel NextRowPanel(int rowCount, ref Rect rect, double width)
  127. {
  128. if (rowPanels.Count <= rowCount)
  129. {
  130. throw new ArgumentNullException("NextRowPanel");
  131. }
  132. else
  133. {
  134. QuickJumpRowPanel panel = rowPanels[rowCount];
  135. return panel;
  136. }
  137. }
  138. private List<QuickJumpRowPanel> rowPanels = new List<QuickJumpRowPanel>();
  139. private List<FrameworkElement> elements = new List<FrameworkElement>();
  140. private void Balance()
  141. {
  142. var itemsControl = ItemsControl;
  143. IsInvalidated = false;
  144. var items = itemsControl.ItemsSource;
  145. if (items != null)
  146. {
  147. int n = items.Count;
  148. if (maxItems > n) maxItems = n;
  149. else if (maxItems < n)
  150. {
  151. StartTimer();
  152. }
  153. OdcListBox lb = itemsControl as OdcListBox;
  154. for (int i = 0; i < maxItems; i++)
  155. {
  156. QuickJumpListBoxItem item = quickJumpItems[i];
  157. item.Content = item.DataContext = items[i];
  158. item.ListBox = lb;
  159. if (item.Parent == null) elements.Add(item);
  160. //bool isNew;
  161. //FrameworkElement item = itemsControl.GetItemContainer(i, out isNew);
  162. //if (isNew)
  163. //{
  164. // elements.Insert(i, item);
  165. // itemsControl.ItemContainerAttached(i, item);
  166. //}
  167. }
  168. }
  169. }
  170. private void StartTimer()
  171. {
  172. if (timer == null || !timer.IsEnabled)
  173. {
  174. if (timer == null)
  175. {
  176. timer = new DispatcherTimer
  177. {
  178. Interval = TimeSpan.FromMilliseconds(1.0)
  179. };
  180. timer.Tick += delegate
  181. {
  182. var itemsControl = ItemsControl;
  183. int n = ItemsControl != null && itemsControl.ItemsSource != null ? itemsControl.ItemsSource.Count : 0;
  184. int nextItems = maxItems + 4;
  185. if (nextItems >= n)
  186. {
  187. nextItems = n;
  188. StopTimer();
  189. }
  190. bool isNew;
  191. for (int i = maxItems; i < nextItems; i++)
  192. {
  193. FrameworkElement item = itemsControl.GetItemContainer(i, out isNew);
  194. this.Children.Add(item);
  195. }
  196. maxItems = nextItems;
  197. };
  198. }
  199. else StopTimer();
  200. timer.Start();
  201. }
  202. }
  203. private void StopTimer()
  204. {
  205. if (timer != null && timer.IsEnabled) timer.Stop();
  206. }
  207. protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
  208. {
  209. Invalidate();
  210. }
  211. private void SetLoadState(UIElement item)
  212. {
  213. Control ctrl = item as Control;
  214. if (ctrl != null)
  215. {
  216. VisualStateManager.GoToState(ctrl, VisualStates.LoadedState, true);
  217. }
  218. }
  219. public override void ScrollIntoView(int itemIndex)
  220. {
  221. }
  222. protected internal override void Reset()
  223. {
  224. // Children.Clear();
  225. base.Reset();
  226. }
  227. }
  228. }