PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/ImageWallControl/ImageWall.cs

#
C# | 240 lines | 195 code | 40 blank | 5 comment | 7 complexity | f355952dbd57e54b2a7c5c073a6d6e86 MD5 | raw file
  1. namespace ImageWallControl
  2. {
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Windows;
  6. using System.Windows.Controls;
  7. using System.Windows.Media;
  8. using System.Windows.Media.Animation;
  9. using System.Windows.Media.Effects;
  10. using System.Windows.Shapes;
  11. using System.Windows.Threading;
  12. using BrushProviders;
  13. public class ImageWall : Panel
  14. {
  15. private const int Cols = 12;
  16. public const int FrameSize = 70;
  17. private const int MarginSize = 2;
  18. private const int Rows = 10;
  19. public const int SectionHeight = Rows*FrameSize;
  20. public const int SectionWidth = Cols*FrameSize;
  21. public static DependencyProperty BrushProviderProperty = DependencyProperty.Register(
  22. "BrushProvider",
  23. typeof (IBrushProvider),
  24. typeof (ImageWall),
  25. new PropertyMetadata(new RandomColorBrushProvider()));
  26. private readonly DispatcherTimer _timer = new DispatcherTimer();
  27. private bool[,] _positions;
  28. public ImageWall()
  29. {
  30. _timer.Interval = TimeSpan.FromSeconds(8.0);
  31. _timer.Tick += OnTick;
  32. Loaded += delegate { Refresh(); };
  33. }
  34. public IBrushProvider BrushProvider
  35. {
  36. get { return (IBrushProvider) GetValue(BrushProviderProperty); }
  37. set { SetValue(BrushProviderProperty, value); }
  38. }
  39. private void OnTick(object sender, EventArgs e)
  40. {
  41. var index = Random.Generator.Next(0, Children.Count - 1);
  42. var child = Children[index];
  43. var brush = BrushProvider.GetBrush();
  44. const float totalTime = 3.5f;
  45. var duration = new Duration(TimeSpan.FromSeconds(totalTime));
  46. var sb = new Storyboard
  47. {
  48. Duration = duration,
  49. };
  50. Animate.AnimateScaleX(child, sb, duration, totalTime);
  51. Animate.AnimateScaleY(child, sb, duration, totalTime);
  52. //Animate.AnimatedBlur(child, sb, duration, totalTime);
  53. Animate.AnimateBrush(child, sb, duration, totalTime, brush);
  54. sb.Begin();
  55. }
  56. public void Refresh()
  57. {
  58. _timer.Stop();
  59. _positions = new bool[Cols,Rows];
  60. Children.Clear();
  61. BrushProvider.Initialize(BrushProviderInitialized);
  62. _timer.Start();
  63. }
  64. private void BrushProviderInitialized(IEnumerable<Brush> brushes)
  65. {
  66. var bricks = Combine(
  67. GetLayouts(),
  68. brushes,
  69. (layout, brush) => new {layout, brush});
  70. foreach (var brick in bricks)
  71. {
  72. Children.Add(CreateBrick(brick.layout, brick.brush));
  73. }
  74. }
  75. public static IEnumerable<TResult> Combine<T1, T2, TResult>(IEnumerable<T1> first, IEnumerable<T2> second,
  76. Func<T1, T2, TResult> func)
  77. {
  78. using (var e1 = first.GetEnumerator())
  79. using (var e2 = second.GetEnumerator())
  80. {
  81. while (e1.MoveNext() && e2.MoveNext())
  82. {
  83. yield return func(e1.Current, e2.Current);
  84. }
  85. }
  86. }
  87. private IEnumerable<Layout> GetLayouts()
  88. {
  89. // large
  90. yield return new Layout {Size = 4, X = 0, Y = 0};
  91. //medium
  92. yield return new Layout {Size = 3, X = 9, Y = 0};
  93. yield return new Layout {Size = 3, X = 5, Y = 1};
  94. yield return new Layout {Size = 3, X = 8, Y = 3};
  95. yield return new Layout {Size = 3, X = 4, Y = 4};
  96. //yield return new Layout{Size=3,X=-1, Y=6};
  97. yield return new Layout {Size = 3, X = 2, Y = 7};
  98. yield return new Layout {Size = 3, X = 6, Y = 7};
  99. //small
  100. for (int x = 0; x < Cols; x++)
  101. {
  102. for (int y = 0; y < Rows; y++)
  103. {
  104. if (!_positions[x, y])
  105. {
  106. yield return new Layout {Size = 1, X = x, Y = y};
  107. }
  108. }
  109. }
  110. }
  111. private FrameworkElement CreateBrick(Layout layout, Brush brush)
  112. {
  113. var size = layout.Size;
  114. var x = layout.X;
  115. var y = layout.Y;
  116. MarkPosition(size, x, y);
  117. var fe = new Rectangle
  118. {
  119. Fill = brush,
  120. Width = FrameSize*size,
  121. Height = FrameSize*size,
  122. RenderTransform = new CompositeTransform {ScaleX = 0, ScaleY = 0},
  123. RenderTransformOrigin = new Point(0.5, 0.5),
  124. Effect = new BlurEffect {Radius = 0}
  125. };
  126. Canvas.SetLeft(fe, FrameSize*x);
  127. Canvas.SetTop(fe, FrameSize*y);
  128. AttachLoadingAnimation(fe, Random.Generator.NextDouble());
  129. return fe;
  130. }
  131. private static void AttachLoadingAnimation(Rectangle fe, double offset)
  132. {
  133. var offsetInMs = (int) (1000*offset);
  134. var beginTime = new TimeSpan(0, 0, 0, 0, offsetInMs);
  135. var duration = new Duration(TimeSpan.FromSeconds(1.5));
  136. var sb = new Storyboard
  137. {
  138. Duration = new Duration(TimeSpan.FromSeconds(5)),
  139. BeginTime = beginTime
  140. };
  141. var animX = CreateScaleAnimation(duration, beginTime);
  142. var animY = CreateScaleAnimation(duration, beginTime);
  143. sb.Children.Add(animX);
  144. sb.Children.Add(animY);
  145. Storyboard.SetTarget(animX, fe);
  146. Storyboard.SetTarget(animY, fe);
  147. Storyboard.SetTargetProperty(animX,
  148. new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleX)"));
  149. Storyboard.SetTargetProperty(animY,
  150. new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleY)"));
  151. sb.Begin();
  152. }
  153. private static DoubleAnimation CreateScaleAnimation(Duration duration, TimeSpan beginTime)
  154. {
  155. return new DoubleAnimation
  156. {
  157. BeginTime = beginTime,
  158. Duration = duration,
  159. From = 0,
  160. To = 1,
  161. EasingFunction = new QuarticEase {EasingMode = EasingMode.EaseOut}
  162. };
  163. }
  164. private void MarkPosition(int size, int originX, int originY)
  165. {
  166. for (int x = originX; x < originX + size; x++)
  167. {
  168. for (int y = originY; y < originY + size; y++)
  169. {
  170. _positions[x, y] = true;
  171. }
  172. }
  173. }
  174. protected override Size MeasureOverride(Size availableSize)
  175. {
  176. return new Size(FrameSize*Cols, FrameSize*Rows);
  177. }
  178. protected override Size ArrangeOverride(Size finalSize)
  179. {
  180. foreach (FrameworkElement child in Children)
  181. {
  182. var x = Canvas.GetLeft(child) + MarginSize;
  183. var y = Canvas.GetTop(child) + MarginSize;
  184. var location = new Point(x, y);
  185. var w = child.Width - (2*MarginSize);
  186. var h = child.Height - (2*MarginSize);
  187. child.Arrange(new Rect(location, new Size(w, h)));
  188. }
  189. return new Size(FrameSize*Cols, FrameSize*Rows);
  190. }
  191. #region Nested type: Layout
  192. private struct Layout
  193. {
  194. public int Size;
  195. public int X;
  196. public int Y;
  197. }
  198. #endregion
  199. }
  200. }