PageRenderTime 64ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/Xceed.Silverlight.ListBox/(Transitions)/RemovingItemTransitionAnimation.cs

http://extendedsilverlight.codeplex.com
C# | 326 lines | 226 code | 69 blank | 31 comment | 20 complexity | 839136bb3d4b40637daac036263b29c6 MD5 | raw file
  1. /************************************************************************
  2. Extended Silverlight Toolkit
  3. Copyright (C) 2010-2012 Xceed Software Inc.
  4. This program is provided to you under the terms of the Microsoft Public
  5. License (Ms-PL) as published at http://extendedsilverlight.codeplex.com/license
  6. Please purchase a commercial version of this toolkit if you are using
  7. it in a commercial product. The commercial versions support the project,
  8. and also include more features for each control, priority support,
  9. source code, updates, removed watermark, and a proprietary license.
  10. Visit http://xceed.com and follow @datagrid on Twitter.
  11. **********************************************************************/
  12. using System.Collections.Generic;
  13. using System.Linq;
  14. using System.Windows;
  15. using System.Windows.Controls;
  16. using System.Windows.Media.Animation;
  17. namespace Xceed.Silverlight.ListBox
  18. {
  19. internal class RemovingItemTransitionAnimation : TransitionAnimation
  20. {
  21. internal RemovingItemTransitionAnimation( ListBoxAnimationSettings animationSettings )
  22. : base( animationSettings.GetRemovingItemDuration() )
  23. {
  24. PowerEase opacityEasing = new PowerEase();
  25. opacityEasing.EasingMode = EasingMode.EaseOut;
  26. opacityEasing.Power = 6;
  27. PowerEase itemsRemovedEasing = new PowerEase();
  28. itemsRemovedEasing.EasingMode = EasingMode.EaseOut;
  29. itemsRemovedEasing.Power = 6;
  30. PowerEase otherItemsEasing = new PowerEase();
  31. otherItemsEasing.EasingMode = EasingMode.EaseInOut;
  32. otherItemsEasing.Power = 6;
  33. m_opacityEasing = opacityEasing;
  34. m_removedItemsMovementEasing = itemsRemovedEasing;
  35. m_otherItemsMovementEasing = otherItemsEasing;
  36. }
  37. internal double RemovePositionX
  38. {
  39. get;
  40. private set;
  41. }
  42. internal double RemovePositionY
  43. {
  44. get;
  45. private set;
  46. }
  47. internal double RemoveWidth
  48. {
  49. get;
  50. private set;
  51. }
  52. internal double RemoveHeight
  53. {
  54. get;
  55. private set;
  56. }
  57. internal Orientation Orientation
  58. {
  59. get;
  60. set;
  61. }
  62. internal override void AddContainer( ListBoxContainer container )
  63. {
  64. //Nothing to do
  65. }
  66. internal override LayoutChangeInfo CreateLayoutChangeInfo()
  67. {
  68. return new LayoutChangeInfo();
  69. }
  70. internal override void DetermineLayoutChangesCore( Dictionary<ListBoxContainer, LayoutChangeInfo> changedElements )
  71. {
  72. //For this transition animation, I need to assess the position ("pixels") where the remove is performed.
  73. //I also need to know total items travel to impact added containers correctly.
  74. double lowestRemovalX = double.MaxValue;
  75. double lowestRemovalY = double.MaxValue;
  76. double highestRemovalX = double.MinValue;
  77. double highestRemovalY = double.MinValue;
  78. IEnumerable<ListBoxContainer> removedElements = from kvp in changedElements
  79. let layoutChangeInfo = kvp.Value
  80. let removedContainer = kvp.Key
  81. where layoutChangeInfo.ChangeType == ChangeType.ElementRemoved
  82. select removedContainer;
  83. bool hadRemoval = false;
  84. foreach( ListBoxContainer container in removedElements )
  85. {
  86. Point containerPosition = container.ActualComputedPosition;
  87. double elementHeight = container.ActualElementHeight;
  88. double elementWidth = container.AbsoluteElementWidth;
  89. if( containerPosition.X < lowestRemovalX )
  90. {
  91. lowestRemovalX = containerPosition.X;
  92. }
  93. if( containerPosition.Y < lowestRemovalY )
  94. {
  95. lowestRemovalY = containerPosition.Y;
  96. }
  97. if( ( containerPosition.X + elementWidth ) > highestRemovalX )
  98. {
  99. highestRemovalX = containerPosition.X + elementWidth;
  100. }
  101. if( ( containerPosition.Y + elementHeight ) > highestRemovalY )
  102. {
  103. highestRemovalY = containerPosition.Y + elementHeight;
  104. }
  105. hadRemoval = true;
  106. }
  107. if( hadRemoval )
  108. {
  109. this.RemovePositionX = lowestRemovalX;
  110. this.RemovePositionY = lowestRemovalY;
  111. this.RemoveWidth = highestRemovalX - lowestRemovalX;
  112. this.RemoveHeight = highestRemovalY - lowestRemovalY;
  113. }
  114. }
  115. internal override bool PrepareContainerCore( ListBoxContainer container, LayoutChangeInfo changeInfo )
  116. {
  117. switch( changeInfo.ChangeType )
  118. {
  119. case ChangeType.ElementAdded:
  120. this.PrepareAddedElement( container, changeInfo );
  121. break;
  122. case ChangeType.ElementRemoved:
  123. this.PrepareRemovedElement( container, changeInfo );
  124. break;
  125. //If element is changed, don't change a thing.
  126. case ChangeType.ElementChanged:
  127. this.PrepareChangedElement( container, changeInfo );
  128. break;
  129. default:
  130. break;
  131. }
  132. //systematically return true. All elements flagged as changed are handled in this transition.
  133. return true;
  134. }
  135. internal override bool UpdateContainerCore( double normalizedElapsedTime, ListBoxContainer container )
  136. {
  137. if( container == null )
  138. throw new ListBoxInternalException();
  139. container.UpdateAnimations( normalizedElapsedTime );
  140. //There is no custom animations in this transition, only those handled by the EasingFunctions.
  141. //Since I have no custom timeline, I do not have to decide when its "finished". Returning false
  142. //will just make it so that the animation will proceed for every frame of every item.
  143. return false;
  144. }
  145. internal override void CleanContainerCore( ListBoxContainer container )
  146. {
  147. if( container == null )
  148. throw new ListBoxInternalException();
  149. }
  150. private void PrepareAddedElement( ListBoxContainer container, LayoutChangeInfo changeInfo )
  151. {
  152. if( changeInfo == null )
  153. throw new ListBoxInternalException();
  154. //In the case of an Remove action, added elements are those brought into the layout because some content is removed from the layout.
  155. //In that case, this class will animate them from the height of removal to their respective position
  156. SizeAnimation sizeAnimation = new SizeAnimation();
  157. OpacityAnimation opacityAnimation = new OpacityAnimation();
  158. PositionAnimation positionAnimation = new PositionAnimation();
  159. ( ( IAnimation )opacityAnimation ).AnimationDirection = AnimationDirection.ToReferencePosition;
  160. ( ( IAnimation )opacityAnimation ).EasingFunction = m_opacityEasing;
  161. ( ( IAnimation )opacityAnimation ).ParentTransition = this;
  162. ( ( IAnimation )sizeAnimation ).EasingFunction = m_otherItemsMovementEasing;
  163. ( ( IAnimation )sizeAnimation ).ParentTransition = this;
  164. ( ( IAnimation )positionAnimation ).EasingFunction = m_otherItemsMovementEasing;
  165. ( ( IAnimation )positionAnimation ).ParentTransition = this;
  166. if( this.Orientation == Orientation.Vertical )
  167. {
  168. positionAnimation.XChange = double.NaN;
  169. positionAnimation.YChange = this.RemoveHeight;
  170. sizeAnimation.MaximumHeightChange = -this.RemoveHeight;
  171. }
  172. else
  173. {
  174. positionAnimation.XChange = this.RemoveWidth;
  175. positionAnimation.YChange = double.NaN;
  176. sizeAnimation.MaximumWidthChange = -this.RemoveWidth;
  177. }
  178. sizeAnimation.WidthChange = double.NaN;
  179. sizeAnimation.HeightChange = double.NaN;
  180. opacityAnimation.OpacityChange = -changeInfo.OpacityChange;
  181. container.AddAnimation( sizeAnimation );
  182. container.AddAnimation( opacityAnimation );
  183. container.AddAnimation( positionAnimation );
  184. }
  185. private void PrepareChangedElement( ListBoxContainer container, LayoutChangeInfo changeInfo )
  186. {
  187. if( changeInfo == null )
  188. throw new ListBoxInternalException();
  189. //In the case of an Remove action, added elements are those brought into the layout because some content is removed from the layout.
  190. //In that case, this class will animate them from the height of removal to their respective position
  191. PositionAnimation positionAnimation = new PositionAnimation();
  192. SizeAnimation sizeAnimation = new SizeAnimation();
  193. RotateAnimation rotationAnimation = new RotateAnimation();
  194. ScaleAnimation scaleAnimation = new ScaleAnimation();
  195. ( ( IAnimation )positionAnimation ).EasingFunction = m_otherItemsMovementEasing;
  196. ( ( IAnimation )positionAnimation ).ParentTransition = this;
  197. ( ( IAnimation )sizeAnimation ).EasingFunction = m_otherItemsMovementEasing;
  198. ( ( IAnimation )sizeAnimation ).ParentTransition = this;
  199. ( ( IAnimation )rotationAnimation ).ParentTransition = this;
  200. ( ( IAnimation )rotationAnimation ).EasingFunction = m_otherItemsMovementEasing;
  201. ( ( IAnimation )scaleAnimation ).ParentTransition = this;
  202. ( ( IAnimation )scaleAnimation ).EasingFunction = m_otherItemsMovementEasing;
  203. positionAnimation.XChange = changeInfo.XChange;
  204. positionAnimation.YChange = changeInfo.YChange;
  205. rotationAnimation.AngleChange = changeInfo.AngleChange;
  206. if( this.Orientation == Orientation.Vertical )
  207. {
  208. sizeAnimation.MaximumHeightChange = -this.RemoveHeight;
  209. }
  210. else
  211. {
  212. sizeAnimation.MaximumWidthChange = -this.RemoveWidth;
  213. }
  214. sizeAnimation.WidthChange = double.NaN;
  215. sizeAnimation.HeightChange = double.NaN;
  216. scaleAnimation.ScaleChange = changeInfo.ScaleChange;
  217. container.AddAnimation( rotationAnimation );
  218. container.AddAnimation( positionAnimation );
  219. container.AddAnimation( sizeAnimation );
  220. container.AddAnimation( scaleAnimation );
  221. }
  222. private void PrepareRemovedElement( ListBoxContainer container, LayoutChangeInfo changeInfo )
  223. {
  224. //Removed items in the case of a Remove are items that are shifted out of view ( they are removed )
  225. if( changeInfo == null )
  226. throw new ListBoxInternalException();
  227. //Animation for these items is to push them away by the amount of inserted items.
  228. Point elementActualPosition = container.ActualComputedPosition;
  229. SizeAnimation sizeAnimation = new SizeAnimation();
  230. OpacityAnimation opacityAnimation = new OpacityAnimation();
  231. RotateAnimation rotateAnimation = new RotateAnimation();
  232. ( ( IAnimation )sizeAnimation ).EasingFunction = m_removedItemsMovementEasing;
  233. ( ( IAnimation )sizeAnimation ).ParentTransition = this;
  234. ( ( IAnimation )opacityAnimation ).EasingFunction = m_opacityEasing;
  235. ( ( IAnimation )opacityAnimation ).ParentTransition = this;
  236. ( ( IAnimation )opacityAnimation ).AnimationDirection = AnimationDirection.FromReferencePosition;
  237. ( ( IAnimation )rotateAnimation ).EasingFunction = m_removedItemsMovementEasing;
  238. ( ( IAnimation )rotateAnimation ).ParentTransition = this;
  239. rotateAnimation.AngleChange = changeInfo.AngleChange;
  240. sizeAnimation.WidthChange = double.NaN; // do not change its width
  241. sizeAnimation.HeightChange = double.NaN; // do not change its height.
  242. opacityAnimation.OpacityChange = changeInfo.OpacityChange;
  243. container.AddAnimation( rotateAnimation );
  244. container.AddAnimation( sizeAnimation );
  245. container.AddAnimation( opacityAnimation );
  246. }
  247. private IEasingFunction m_opacityEasing;
  248. private IEasingFunction m_removedItemsMovementEasing;
  249. private IEasingFunction m_otherItemsMovementEasing;
  250. }
  251. }