Tile.cs 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546
  1. using System;
  2. using System.Windows.Input;
  3. using Windows.Foundation;
  4. using Windows.UI.Xaml;
  5. using Windows.UI.Xaml.Controls;
  6. using Windows.UI.Xaml.Input;
  7. using Windows.UI.Xaml.Media;
  8. using Windows.UI.Xaml.Media.Animation;
  9. using FormulaOneApp.Classic.Windows.Controls.Tile.Animations;
  10. namespace FormulaOneApp.Classic.Windows.Controls.Tile
  11. {
  12. [TemplatePart(Name = "PART_FrontContentPresenter", Type = typeof(Tile))]
  13. [TemplatePart(Name = "PART_BackContentPresenter", Type = typeof(Tile))]
  14. [TemplatePart(Name = "PART_OverlayContentPresenter", Type = typeof(Tile))]
  15. public class Tile : Control
  16. {
  17. public ICommand Command
  18. {
  19. get { return (ICommand)GetValue(CommandProperty); }
  20. set { SetValue(CommandProperty, value); }
  21. }
  22. // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
  23. public static readonly DependencyProperty CommandProperty =
  24. DependencyProperty.Register("Command", typeof(ICommand), typeof(Tile), new PropertyMetadata(null));
  25. public Object CommandParameter
  26. {
  27. get { return (Object)GetValue(CommandParameterProperty); }
  28. set { SetValue(CommandParameterProperty, value); }
  29. }
  30. // Using a DependencyProperty as the backing store for CommandParameter. This enables animation, styling, binding, etc...
  31. public static readonly DependencyProperty CommandParameterProperty =
  32. DependencyProperty.Register("CommandParameter", typeof(Object), typeof(Tile), new PropertyMetadata(null));
  33. private DispatcherTimer dispatcherTimer;
  34. public ContentPresenter FrontContentPresenter { get; private set; }
  35. public ContentPresenter BackContentPresenter { get; private set; }
  36. private Random random;
  37. //public TileAnimation TileAnimation { get; set; }
  38. public Boolean IsFrontSide { get; set; }
  39. public Tile()
  40. {
  41. this.DefaultStyleKey = typeof(Tile);
  42. this.IsFrontSide = true;
  43. var rnd = new Random();
  44. Int32 generateNumber = (Int32) rnd.Next(1, 9999);
  45. random = new Random(generateNumber);
  46. dispatcherTimer = new DispatcherTimer();
  47. dispatcherTimer.Interval = TimeSpan.FromSeconds(random.Next(3, 10));
  48. dispatcherTimer.Tick += DispatcherTimerOnTick;
  49. if (!this.IsAnimationEnabled)
  50. dispatcherTimer.Start();
  51. }
  52. private void DispatcherTimerOnTick(object sender, object o)
  53. {
  54. dispatcherTimer.Interval = TimeSpan.FromSeconds(random.Next(6, 10));
  55. if (this.TileAnimation == null)
  56. {
  57. dispatcherTimer.Stop();
  58. return;
  59. }
  60. Storyboard sb = this.TileAnimation.GetStoryboard(this);
  61. sb.Begin();
  62. }
  63. public Boolean IsAnimationEnabled
  64. {
  65. get { return (Boolean)GetValue(IsAnimationEnabledProperty); }
  66. set { SetValue(IsAnimationEnabledProperty, value); }
  67. }
  68. // Using a DependencyProperty as the backing store for isAnimationEnabled. This enables animation, styling, binding, etc...
  69. public static readonly DependencyProperty IsAnimationEnabledProperty =
  70. DependencyProperty.Register("IsAnimationEnabled", typeof(Boolean), typeof(Tile), new PropertyMetadata(true, OnAnimationEnabledChanged));
  71. private static void OnAnimationEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  72. {
  73. Tile tile = (Tile)d;
  74. Boolean isAnimationEnabled = (Boolean)e.NewValue;
  75. Boolean oldValue = (Boolean)e.OldValue;
  76. if (isAnimationEnabled == oldValue)
  77. return;
  78. if (isAnimationEnabled && !tile.dispatcherTimer.IsEnabled)
  79. tile.dispatcherTimer.Start();
  80. if (!isAnimationEnabled && tile.dispatcherTimer.IsEnabled)
  81. tile.dispatcherTimer.Stop();
  82. }
  83. public Object OverlayContent
  84. {
  85. get { return GetValue(OverlayContentProperty); }
  86. set { SetValue(OverlayContentProperty, value); }
  87. }
  88. // Using a DependencyProperty as the backing store for OverlayContent. This enables animation, styling, binding, etc...
  89. public static readonly DependencyProperty OverlayContentProperty =
  90. DependencyProperty.Register("OverlayContent", typeof(Object), typeof(Tile), new PropertyMetadata(null));
  91. public Object FrontContent
  92. {
  93. get { return GetValue(FrontContentProperty); }
  94. set { SetValue(FrontContentProperty, value); }
  95. }
  96. // Using a DependencyProperty as the backing store for FrontContent. This enables animation, styling, binding, etc...
  97. public static readonly DependencyProperty FrontContentProperty =
  98. DependencyProperty.Register("FrontContent", typeof(Object), typeof(Tile), new PropertyMetadata(null));
  99. public Object BackContent
  100. {
  101. get { return GetValue(BackContentProperty); }
  102. set { SetValue(BackContentProperty, value); }
  103. }
  104. // Using a DependencyProperty as the backing store for BackContent. This enables animation, styling, binding, etc...
  105. public static readonly DependencyProperty BackContentProperty =
  106. DependencyProperty.Register("BackContent", typeof(Object), typeof(Tile), new PropertyMetadata(null));
  107. public ITileAnimation TileAnimation
  108. {
  109. get { return (ITileAnimation)GetValue(TileAnimationProperty); }
  110. set { SetValue(TileAnimationProperty, value); }
  111. }
  112. // Using a DependencyProperty as the backing store for TileAnimation. This enables animation, styling, binding, etc...
  113. public static readonly DependencyProperty TileAnimationProperty =
  114. DependencyProperty.Register("TileAnimation", typeof(ITileAnimation),
  115. typeof(Tile),
  116. new PropertyMetadata(new UpAndDownTileAnimation()));
  117. protected override void OnApplyTemplate()
  118. {
  119. FrontContentPresenter = this.GetTemplateChild("PART_FrontContentPresenter") as ContentPresenter;
  120. BackContentPresenter = this.GetTemplateChild("PART_BackContentPresenter") as ContentPresenter;
  121. if (this.FrontContentPresenter != null)
  122. this.SetPlaneProjection(this.FrontContentPresenter);
  123. if (this.BackContentPresenter != null)
  124. this.SetPlaneProjection(this.BackContentPresenter);
  125. }
  126. protected override void OnTapped(TappedRoutedEventArgs e)
  127. {
  128. base.OnTapped(e);
  129. ExecuteCommand();
  130. }
  131. internal void ExecuteCommand()
  132. {
  133. if (this.Command == null) return;
  134. if (this.Command.CanExecute(this.CommandParameter))
  135. this.Command.Execute(this.CommandParameter);
  136. }
  137. private void AnimateRotationVertical()
  138. {
  139. var animDuration = new Duration(TimeSpan.FromMilliseconds(1000d));
  140. var storyboard = new Storyboard();
  141. var animationSnapFront = new DoubleAnimation
  142. {
  143. EnableDependentAnimation = true,
  144. From = 0,
  145. To = 180,
  146. Duration = animDuration,
  147. EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 8d }
  148. };
  149. var animationSnapFrontOpacity = new DoubleAnimation
  150. {
  151. EnableDependentAnimation = true,
  152. From = 1,
  153. To = 0,
  154. BeginTime = TimeSpan.FromMilliseconds(50d),
  155. Duration = new Duration(TimeSpan.FromMilliseconds(1d))
  156. };
  157. storyboard.Children.Add(animationSnapFront);
  158. storyboard.Children.Add(animationSnapFrontOpacity);
  159. Storyboard.SetTarget(animationSnapFront, this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  160. Storyboard.SetTargetProperty(animationSnapFront, "(UIElement.Projection).(PlaneProjection.RotationX)");
  161. Storyboard.SetTarget(animationSnapFrontOpacity, this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  162. Storyboard.SetTargetProperty(animationSnapFrontOpacity, "Opacity");
  163. var animationSnapBack = new DoubleAnimation
  164. {
  165. EnableDependentAnimation = true,
  166. From = 180,
  167. To = 0,
  168. Duration = animDuration,
  169. EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 8d }
  170. };
  171. var animationSnapBackOpacity = new DoubleAnimation
  172. {
  173. EnableDependentAnimation = true,
  174. From = 0,
  175. To = 1,
  176. BeginTime = TimeSpan.FromMilliseconds(50d),
  177. Duration = new Duration(TimeSpan.FromMilliseconds(1d))
  178. };
  179. storyboard.Children.Add(animationSnapBack);
  180. storyboard.Children.Add(animationSnapBackOpacity);
  181. Storyboard.SetTarget(animationSnapBack, !this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  182. Storyboard.SetTargetProperty(animationSnapBack, "(UIElement.Projection).(PlaneProjection.RotationX)");
  183. Storyboard.SetTarget(animationSnapBackOpacity, !this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  184. Storyboard.SetTargetProperty(animationSnapBackOpacity, "Opacity");
  185. this.IsFrontSide = !this.IsFrontSide;
  186. storyboard.Begin();
  187. }
  188. private void AnimateRotationHorizontal()
  189. {
  190. var animDuration = new Duration(TimeSpan.FromMilliseconds(1000d));
  191. var storyboard = new Storyboard();
  192. var animationSnapFront = new DoubleAnimation
  193. {
  194. EnableDependentAnimation = true,
  195. From = 0,
  196. To = 180,
  197. Duration = animDuration,
  198. EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 8d }
  199. };
  200. var animationSnapFrontOpacity = new DoubleAnimation
  201. {
  202. EnableDependentAnimation = true,
  203. From = 1,
  204. To = 0,
  205. BeginTime = TimeSpan.FromMilliseconds(50d),
  206. Duration = new Duration(TimeSpan.FromMilliseconds(1d))
  207. };
  208. storyboard.Children.Add(animationSnapFront);
  209. storyboard.Children.Add(animationSnapFrontOpacity);
  210. Storyboard.SetTarget(animationSnapFront, this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  211. Storyboard.SetTargetProperty(animationSnapFront, "(UIElement.Projection).(PlaneProjection.RotationY)");
  212. Storyboard.SetTarget(animationSnapFrontOpacity, this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  213. Storyboard.SetTargetProperty(animationSnapFrontOpacity, "Opacity");
  214. var animationSnapBack = new DoubleAnimation
  215. {
  216. EnableDependentAnimation = true,
  217. From = 180,
  218. To = 0,
  219. Duration = animDuration,
  220. EasingFunction = new ExponentialEase { EasingMode = EasingMode.EaseOut, Exponent = 8d }
  221. };
  222. var animationSnapBackOpacity = new DoubleAnimation
  223. {
  224. EnableDependentAnimation = true,
  225. From = 0,
  226. To = 1,
  227. BeginTime = TimeSpan.FromMilliseconds(50d),
  228. Duration = new Duration(TimeSpan.FromMilliseconds(1d))
  229. };
  230. storyboard.Children.Add(animationSnapBack);
  231. storyboard.Children.Add(animationSnapBackOpacity);
  232. Storyboard.SetTarget(animationSnapBack, !this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  233. Storyboard.SetTargetProperty(animationSnapBack, "(UIElement.Projection).(PlaneProjection.RotationY)");
  234. Storyboard.SetTarget(animationSnapBackOpacity, !this.IsFrontSide ? this.FrontContentPresenter : this.BackContentPresenter);
  235. Storyboard.SetTargetProperty(animationSnapBackOpacity, "Opacity");
  236. this.IsFrontSide = !this.IsFrontSide;
  237. storyboard.Begin();
  238. }
  239. //private void AnimateLeft()
  240. //{
  241. // var animDuration = new Duration(TimeSpan.FromMilliseconds(1000d));
  242. // var offset = this.BorderThickness.Right + this.BorderThickness.Left;
  243. // if (this.IsFrontSide)
  244. // {
  245. // var storyboard = new Storyboard();
  246. // storyboard = this.AddToStoryboard(storyboard, -this.ActualWidth + offset, 0d, animDuration,
  247. // this.backContentPresenter,
  248. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  249. // storyboard = this.AddToStoryboard(storyboard, 0d, this.ActualWidth - offset, animDuration,
  250. // this.frontContentPresenter,
  251. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  252. // this.IsFrontSide = false;
  253. // storyboard.Begin();
  254. // }
  255. // else
  256. // {
  257. // var storyboard = new Storyboard();
  258. // storyboard = this.AddToStoryboard(storyboard, -this.ActualWidth + offset, 0d, animDuration,
  259. // this.frontContentPresenter,
  260. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  261. // storyboard = this.AddToStoryboard(storyboard, 0d, this.ActualWidth - offset, animDuration,
  262. // this.backContentPresenter,
  263. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  264. // storyboard.Begin();
  265. // this.IsFrontSide = true;
  266. // }
  267. //}
  268. //private void AnimateRight()
  269. //{
  270. // var animDuration = new Duration(TimeSpan.FromMilliseconds(1000d));
  271. // var offset = this.BorderThickness.Right + this.BorderThickness.Left;
  272. // if (this.IsFrontSide)
  273. // {
  274. // var storyboard = new Storyboard();
  275. // storyboard = this.AddToStoryboard(storyboard, 0d, -this.ActualWidth + offset, animDuration,
  276. // this.frontContentPresenter,
  277. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  278. // storyboard = this.AddToStoryboard(storyboard, this.ActualWidth - offset, 0d, animDuration,
  279. // this.backContentPresenter,
  280. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  281. // this.IsFrontSide = false;
  282. // storyboard.Begin();
  283. // }
  284. // else
  285. // {
  286. // var storyboard = new Storyboard();
  287. // storyboard = this.AddToStoryboard(storyboard, 0d, -this.ActualWidth + offset, animDuration,
  288. // this.backContentPresenter,
  289. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  290. // storyboard = this.AddToStoryboard(storyboard, this.ActualWidth - offset, 0d, animDuration,
  291. // this.frontContentPresenter,
  292. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetX)");
  293. // storyboard.Begin();
  294. // this.IsFrontSide = true;
  295. // }
  296. //}
  297. //private void AnimateUp()
  298. //{
  299. // var animDuration = new Duration(TimeSpan.FromMilliseconds(1000d));
  300. // var offset = this.BorderThickness.Top + this.BorderThickness.Bottom;
  301. // if (this.IsFrontSide)
  302. // {
  303. // var storyboard = new Storyboard();
  304. // this.backContentPresenter.Visibility = Visibility.Visible;
  305. // storyboard = this.AddToStoryboard(storyboard, 0d, -this.ActualHeight + offset, animDuration,
  306. // this.frontContentPresenter,
  307. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  308. // storyboard = this.AddToStoryboard(storyboard, this.ActualHeight - offset, 0d, animDuration,
  309. // this.backContentPresenter,
  310. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  311. // storyboard.Completed += (sender1, o1) => this.frontContentPresenter.Visibility = Visibility.Collapsed;
  312. // this.IsFrontSide = false;
  313. // storyboard.Begin();
  314. // }
  315. // else
  316. // {
  317. // var storyboard = new Storyboard();
  318. // this.frontContentPresenter.Visibility = Visibility.Visible;
  319. // storyboard = this.AddToStoryboard(storyboard, 0d, -this.ActualHeight + offset, animDuration,
  320. // this.backContentPresenter,
  321. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  322. // storyboard = this.AddToStoryboard(storyboard, this.ActualHeight - offset, 0d, animDuration,
  323. // this.frontContentPresenter,
  324. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  325. // storyboard.Completed += (sender1, o1) => this.backContentPresenter.Visibility = Visibility.Collapsed;
  326. // storyboard.Begin();
  327. // this.IsFrontSide = true;
  328. // }
  329. //}
  330. //private void AnimateDown()
  331. //{
  332. // var animDuration = new Duration(TimeSpan.FromMilliseconds(1000d));
  333. // var offset = this.BorderThickness.Top + this.BorderThickness.Bottom;
  334. // if (this.IsFrontSide)
  335. // {
  336. // var storyboard = new Storyboard();
  337. // this.backContentPresenter.Visibility = Visibility.Visible;
  338. // storyboard = this.AddToStoryboard(storyboard, -this.ActualHeight + offset, 0d, animDuration,
  339. // this.backContentPresenter,
  340. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  341. // storyboard = this.AddToStoryboard(storyboard, 0d, this.ActualHeight - offset, animDuration,
  342. // this.frontContentPresenter,
  343. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  344. // storyboard.Completed += (sender1, o1) => this.frontContentPresenter.Visibility = Visibility.Collapsed;
  345. // this.IsFrontSide = false;
  346. // storyboard.Begin();
  347. // }
  348. // else
  349. // {
  350. // var storyboard = new Storyboard();
  351. // this.frontContentPresenter.Visibility = Visibility.Visible;
  352. // storyboard = this.AddToStoryboard(storyboard, -this.ActualHeight + offset, 0d, animDuration,
  353. // this.frontContentPresenter,
  354. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  355. // storyboard = this.AddToStoryboard(storyboard, 0d, this.ActualHeight - offset, animDuration,
  356. // this.backContentPresenter,
  357. // "(UIElement.Projection).(PlaneProjection.GlobalOffsetY)");
  358. // storyboard.Completed += (sender1, o1) => this.backContentPresenter.Visibility = Visibility.Collapsed;
  359. // storyboard.Begin();
  360. // this.IsFrontSide = true;
  361. // }
  362. //}
  363. private void SetPlaneProjection(UIElement contentGrid)
  364. {
  365. PlaneProjection planeProjection = new PlaneProjection();
  366. contentGrid.Projection = planeProjection;
  367. }
  368. private void ChangeBackGroundImage(ImageSource source, Grid contentGrid)
  369. {
  370. ImageBrush backGroundImage = new ImageBrush();
  371. backGroundImage.Stretch = Stretch.Fill;
  372. backGroundImage.ImageSource = source;
  373. contentGrid.Background = backGroundImage;
  374. }
  375. protected override Size MeasureOverride(Size availableSize)
  376. {
  377. // Clip to ensure items dont override container
  378. var size = base.MeasureOverride(availableSize);
  379. this.Clip = new RectangleGeometry { Rect = new Rect(0, 0, size.Width, size.Height) };
  380. return size;
  381. }
  382. }
  383. //public enum TileAnimation
  384. //{
  385. // UpAndDown,
  386. // Up,
  387. // Down,
  388. // LeftToRight,
  389. // RightToLeft,
  390. // Left,
  391. // Right,
  392. // RotationHorizontal,
  393. // RotationVertical,
  394. //}
  395. }