/// <summary> /// Restores the original projection and render transform of /// the targeted framework elements. /// </summary> private static void RestoreProjectionsAndTransforms() { if (_featheringTargets == null || !_pendingRestore) { return; } foreach (WeakReference r in _featheringTargets) { FrameworkElement element = r.Target as FrameworkElement; if (element == null) { continue; } Projection projection = TurnstileFeatherEffect.GetOriginalProjection(element); Transform transform = TurnstileFeatherEffect.GetOriginalRenderTransform(element); element.Projection = projection; element.RenderTransform = transform; } _pendingRestore = false; }
/// <summary> /// Unsubscribes an element from the private manager. /// </summary> /// <param name="target">The framework element.</param> private static void UnsubscribeFrameworkElement(FrameworkElement target) { // If element is subscribed, unsubscribe. if (TurnstileFeatherEffect.GetIsSubscribed(target)) { TurnstileFeatherEffect.SetParentPage(target, null); TurnstileFeatherEffect.SetIsSubscribed(target, false); } }
/// <summary> /// Adds a set of animations corresponding to the /// turnstile feather effect. /// </summary> /// <param name="storyboard"> /// The storyboard where the animations /// will be added.</param> /// <param name="beginTime"> /// The time at which the storyboard should begin.</param> /// <param name="mode"> /// The mode of the turnstile feather effect. /// </param> internal static void ComposeStoryboard(Storyboard storyboard, TimeSpan?beginTime, TurnstileFeatherTransitionMode mode) { RestoreProjectionsAndTransforms(); _featheringTargets = GetTargetsToAnimate(); if (_featheringTargets == null) { return; } _pendingRestore = true; switch (mode) { case TurnstileFeatherTransitionMode.ForwardIn: ComposeForwardInStoryboard(storyboard); break; case TurnstileFeatherTransitionMode.ForwardOut: ComposeForwardOutStoryboard(storyboard); break; case TurnstileFeatherTransitionMode.BackwardIn: ComposeBackwardInStoryboard(storyboard); break; case TurnstileFeatherTransitionMode.BackwardOut: ComposeBackwardOutStoryboard(storyboard); break; default: break; } storyboard.BeginTime = beginTime; storyboard.Completed += (s, e) => { foreach (WeakReference r in _featheringTargets) { FrameworkElement element = (FrameworkElement)r.Target; double originalOpacity = TurnstileFeatherEffect.GetOriginalOpacity(element); element.Opacity = originalOpacity; } RestoreProjectionsAndTransforms(); }; }
/// <summary> /// Subscribes an element to the private managers. /// </summary> /// <param name="target">The framework element.</param> private static void SubscribeFrameworkElement(FrameworkElement target) { if (!TurnstileFeatherEffect.GetIsSubscribed(target)) { // Find the parent page. PhoneApplicationPage page = target.GetParentByType <PhoneApplicationPage>(); if (page == null) { return; } TurnstileFeatherEffect.SetParentPage(target, page); TurnstileFeatherEffect.SetIsSubscribed(target, true); } }
/// <summary> /// Adds a set of animations corresponding to the /// turnstile feather backward in effect. /// </summary> /// <param name="storyboard"> /// The storyboard where the animations /// will be added. /// </param> private static void ComposeBackwardInStoryboard(Storyboard storyboard) { int counter = 0; PhoneApplicationFrame root = Application.Current.RootVisual as PhoneApplicationFrame; foreach (WeakReference r in _featheringTargets) { FrameworkElement element = (FrameworkElement)r.Target; double originalOpacity = element.Opacity; TurnstileFeatherEffect.SetOriginalOpacity(element, originalOpacity); // Hide the element until the storyboard is begun. element.Opacity = 0.0; if (!TryAttachProjectionAndTransform(root, element)) { continue; } DoubleAnimation doubleAnimation = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(BackwardInFeatheringDuration), From = BackwardInFeatheringAngle, To = 0.0, BeginTime = TimeSpan.FromMilliseconds(BackwardInFeatheringDelay * counter), EasingFunction = TurnstileFeatheringExponentialEaseOut }; Storyboard.SetTarget(doubleAnimation, element); Storyboard.SetTargetProperty(doubleAnimation, RotationYPropertyPath); storyboard.Children.Add(doubleAnimation); doubleAnimation = new DoubleAnimation() { Duration = TimeSpan.Zero, From = 0.0, To = originalOpacity, BeginTime = TimeSpan.FromMilliseconds(BackwardInFeatheringDelay * counter) }; Storyboard.SetTarget(doubleAnimation, element); Storyboard.SetTargetProperty(doubleAnimation, OpacityPropertyPath); storyboard.Children.Add(doubleAnimation); counter++; } }
/// <summary> /// Prepares a framework element to be feathered by adding a plane projection /// and a composite transform to it. /// </summary> /// <param name="root">The root visual.</param> /// <param name="element">The framework element.</param> private static bool TryAttachProjectionAndTransform(PhoneApplicationFrame root, FrameworkElement element) { GeneralTransform generalTransform; try { generalTransform = element.TransformToVisual(root); } catch (ArgumentException) { return(false); } Point coordinates = generalTransform.Transform(Origin); double y = coordinates.Y + element.ActualHeight / 2.0; double offset = (root.ActualHeight / 2.0) - y; // Cache original projection and transform. TurnstileFeatherEffect.SetOriginalProjection(element, element.Projection); TurnstileFeatherEffect.SetOriginalRenderTransform(element, element.RenderTransform); // Attach projection. PlaneProjection projection = new PlaneProjection(); projection.GlobalOffsetY = offset * -1.0; projection.CenterOfRotationX = FeatheringCenterOfRotationX; element.Projection = projection; // Attach transform. Transform originalTransform = element.RenderTransform; TranslateTransform translateTransform = new TranslateTransform(); translateTransform.Y = offset; TransformGroup transformGroup = new TransformGroup(); transformGroup.Children.Add(originalTransform); transformGroup.Children.Add(translateTransform); element.RenderTransform = transformGroup; return(true); }
/// <summary> /// Subscribes an element to the private manager. /// </summary> /// <param name="obj">The event sender.</param> /// <param name="e">The event arguments.</param> private static void OnFeatheringIndexPropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) { FrameworkElement target = obj as FrameworkElement; if (target == null) { string message = string.Format(CultureInfo.InvariantCulture, "The dependency object must be of the type {0}.", typeof(FrameworkElement)); throw new InvalidOperationException(message); } CheckForTypePermission(target); int index = (int)e.NewValue; if (index < 0) { // Dettach event handlers. if (TurnstileFeatherEffect.GetHasEventsAttached(target)) { target.SizeChanged -= Target_SizeChanged; target.Unloaded -= Target_Unloaded; TurnstileFeatherEffect.SetHasEventsAttached(target, false); } UnsubscribeFrameworkElement(target); } else { // Attach event handlers. if (!TurnstileFeatherEffect.GetHasEventsAttached(target)) { target.SizeChanged += Target_SizeChanged; target.Unloaded += Target_Unloaded; TurnstileFeatherEffect.SetHasEventsAttached(target, true); } SubscribeFrameworkElement(target); } }
/// <summary> /// Composes the /// <see cref="M:System.Windows.Media.Animation.Storyboard"/> /// and mirrors /// <see cref="M:System.Windows.Media.Animation.Storyboard.Begin"/>. /// </summary> public override void Begin() { TurnstileFeatherEffect.ComposeStoryboard(Storyboard, _beginTime, _mode); base.Begin(); }