/ImageWallControl/ImageWall.cs
# · C# · 240 lines · 195 code · 40 blank · 5 comment · 7 complexity · f355952dbd57e54b2a7c5c073a6d6e86 MD5 · raw file
- namespace ImageWallControl
- {
- using System;
- using System.Collections.Generic;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Media;
- using System.Windows.Media.Animation;
- using System.Windows.Media.Effects;
- using System.Windows.Shapes;
- using System.Windows.Threading;
- using BrushProviders;
-
- public class ImageWall : Panel
- {
- private const int Cols = 12;
- public const int FrameSize = 70;
- private const int MarginSize = 2;
- private const int Rows = 10;
- public const int SectionHeight = Rows*FrameSize;
- public const int SectionWidth = Cols*FrameSize;
-
- public static DependencyProperty BrushProviderProperty = DependencyProperty.Register(
- "BrushProvider",
- typeof (IBrushProvider),
- typeof (ImageWall),
- new PropertyMetadata(new RandomColorBrushProvider()));
-
- private readonly DispatcherTimer _timer = new DispatcherTimer();
- private bool[,] _positions;
-
- public ImageWall()
- {
- _timer.Interval = TimeSpan.FromSeconds(8.0);
- _timer.Tick += OnTick;
- Loaded += delegate { Refresh(); };
- }
-
- public IBrushProvider BrushProvider
- {
- get { return (IBrushProvider) GetValue(BrushProviderProperty); }
- set { SetValue(BrushProviderProperty, value); }
- }
-
- private void OnTick(object sender, EventArgs e)
- {
- var index = Random.Generator.Next(0, Children.Count - 1);
- var child = Children[index];
- var brush = BrushProvider.GetBrush();
-
- const float totalTime = 3.5f;
- var duration = new Duration(TimeSpan.FromSeconds(totalTime));
- var sb = new Storyboard
- {
- Duration = duration,
- };
-
- Animate.AnimateScaleX(child, sb, duration, totalTime);
- Animate.AnimateScaleY(child, sb, duration, totalTime);
- //Animate.AnimatedBlur(child, sb, duration, totalTime);
- Animate.AnimateBrush(child, sb, duration, totalTime, brush);
-
- sb.Begin();
- }
-
- public void Refresh()
- {
- _timer.Stop();
-
- _positions = new bool[Cols,Rows];
- Children.Clear();
- BrushProvider.Initialize(BrushProviderInitialized);
-
- _timer.Start();
- }
-
- private void BrushProviderInitialized(IEnumerable<Brush> brushes)
- {
- var bricks = Combine(
- GetLayouts(),
- brushes,
- (layout, brush) => new {layout, brush});
-
- foreach (var brick in bricks)
- {
- Children.Add(CreateBrick(brick.layout, brick.brush));
- }
- }
-
- public static IEnumerable<TResult> Combine<T1, T2, TResult>(IEnumerable<T1> first, IEnumerable<T2> second,
- Func<T1, T2, TResult> func)
- {
- using (var e1 = first.GetEnumerator())
- using (var e2 = second.GetEnumerator())
- {
- while (e1.MoveNext() && e2.MoveNext())
- {
- yield return func(e1.Current, e2.Current);
- }
- }
- }
-
- private IEnumerable<Layout> GetLayouts()
- {
- // large
- yield return new Layout {Size = 4, X = 0, Y = 0};
-
- //medium
- yield return new Layout {Size = 3, X = 9, Y = 0};
- yield return new Layout {Size = 3, X = 5, Y = 1};
- yield return new Layout {Size = 3, X = 8, Y = 3};
- yield return new Layout {Size = 3, X = 4, Y = 4};
- //yield return new Layout{Size=3,X=-1, Y=6};
- yield return new Layout {Size = 3, X = 2, Y = 7};
- yield return new Layout {Size = 3, X = 6, Y = 7};
-
- //small
- for (int x = 0; x < Cols; x++)
- {
- for (int y = 0; y < Rows; y++)
- {
- if (!_positions[x, y])
- {
- yield return new Layout {Size = 1, X = x, Y = y};
- }
- }
- }
- }
-
- private FrameworkElement CreateBrick(Layout layout, Brush brush)
- {
- var size = layout.Size;
- var x = layout.X;
- var y = layout.Y;
-
- MarkPosition(size, x, y);
-
- var fe = new Rectangle
- {
- Fill = brush,
- Width = FrameSize*size,
- Height = FrameSize*size,
- RenderTransform = new CompositeTransform {ScaleX = 0, ScaleY = 0},
- RenderTransformOrigin = new Point(0.5, 0.5),
- Effect = new BlurEffect {Radius = 0}
- };
-
- Canvas.SetLeft(fe, FrameSize*x);
- Canvas.SetTop(fe, FrameSize*y);
-
- AttachLoadingAnimation(fe, Random.Generator.NextDouble());
-
- return fe;
- }
-
- private static void AttachLoadingAnimation(Rectangle fe, double offset)
- {
- var offsetInMs = (int) (1000*offset);
- var beginTime = new TimeSpan(0, 0, 0, 0, offsetInMs);
-
- var duration = new Duration(TimeSpan.FromSeconds(1.5));
- var sb = new Storyboard
- {
- Duration = new Duration(TimeSpan.FromSeconds(5)),
- BeginTime = beginTime
- };
-
- var animX = CreateScaleAnimation(duration, beginTime);
- var animY = CreateScaleAnimation(duration, beginTime);
-
- sb.Children.Add(animX);
- sb.Children.Add(animY);
-
- Storyboard.SetTarget(animX, fe);
- Storyboard.SetTarget(animY, fe);
-
- Storyboard.SetTargetProperty(animX,
- new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleX)"));
- Storyboard.SetTargetProperty(animY,
- new PropertyPath("(UIElement.RenderTransform).(CompositeTransform.ScaleY)"));
-
- sb.Begin();
- }
-
- private static DoubleAnimation CreateScaleAnimation(Duration duration, TimeSpan beginTime)
- {
- return new DoubleAnimation
- {
- BeginTime = beginTime,
- Duration = duration,
- From = 0,
- To = 1,
- EasingFunction = new QuarticEase {EasingMode = EasingMode.EaseOut}
- };
- }
-
- private void MarkPosition(int size, int originX, int originY)
- {
- for (int x = originX; x < originX + size; x++)
- {
- for (int y = originY; y < originY + size; y++)
- {
- _positions[x, y] = true;
- }
- }
- }
-
- protected override Size MeasureOverride(Size availableSize)
- {
- return new Size(FrameSize*Cols, FrameSize*Rows);
- }
-
- protected override Size ArrangeOverride(Size finalSize)
- {
- foreach (FrameworkElement child in Children)
- {
- var x = Canvas.GetLeft(child) + MarginSize;
- var y = Canvas.GetTop(child) + MarginSize;
- var location = new Point(x, y);
-
- var w = child.Width - (2*MarginSize);
- var h = child.Height - (2*MarginSize);
-
- child.Arrange(new Rect(location, new Size(w, h)));
- }
- return new Size(FrameSize*Cols, FrameSize*Rows);
- }
-
- #region Nested type: Layout
-
- private struct Layout
- {
- public int Size;
- public int X;
- public int Y;
- }
-
- #endregion
- }
- }