Esempio n. 1
0
        /// <summary>
        /// Starts the specified <paramref name="board"/> in the context of the specified
        /// <paramref name="element"/>.
        /// </summary>
        /// <remarks>
        /// Depending on the parameter <paramref name="handoffBehavior"/>, the new storyboard will
        /// be started when the last other storyboard, which occupies a conflicting property,
        /// has finished.
        /// </remarks>
        /// <param name="board">The storyboard to start.</param>
        /// <param name="element">Context element which will be used as
        /// <see cref="TimelineContext.VisualParent"/> for the new <paramref name="board"/>.</param>
        /// <param name="handoffBehavior">Controls how the new storyboard animation will be
        /// attached to already running animations, if there are conflicting properties animated
        /// by an already running anmiation an by the new <paramref name="board"/>.</param>
        public void StartStoryboard(Storyboard board, UIElement element,
                                    HandoffBehavior handoffBehavior)
        {
            lock (_syncObject)
            {
                AnimationContext context = new AnimationContext
                {
                    Timeline        = board,
                    TimelineContext = board.CreateTimelineContext(element)
                };

                IDictionary <IDataDescriptor, object> conflictingProperties;
                ICollection <AnimationContext>        conflictingAnimations;
                FindConflicts(context, out conflictingAnimations, out conflictingProperties);
                ExecuteHandoff(context, conflictingAnimations, handoffBehavior);

                try
                {
                    board.Setup(context.TimelineContext, conflictingProperties);

                    _scheduledAnimations.Add(context);
                    board.Start(context.TimelineContext, SkinContext.SystemTickCount);
                }
                catch (Exception ex)
                {
                    ServiceRegistration.Get <ILogger>().Error("Animator: Error initializing StoryBoard", ex);
                }

                // No animation here - has to be done in the Animate method
            }
        }
Esempio n. 2
0
        protected void ResetAllValues(AnimationContext ac)
        {
            IDictionary <IDataDescriptor, object> animProperties = new Dictionary <IDataDescriptor, object>();

            ac.Timeline.AddAllAnimatedProperties(ac.TimelineContext, animProperties);
            foreach (KeyValuePair <IDataDescriptor, object> animProperty in animProperties)
            {
                SetValue(animProperty.Key, animProperty.Value);
            }
        }
Esempio n. 3
0
 /// <summary>
 /// Stops the specified <paramref name="board"/> which runs in the context of the
 /// given <paramref name="element"/>.
 /// </summary>
 /// <param name="board">The storyboard to stop.</param>
 /// <param name="element">Context element on which the <paramref name="board"/> runs.</param>
 public void StopStoryboard(Storyboard board, UIElement element)
 {
     lock (_syncObject)
     {
         AnimationContext context = GetContext(board, element);
         if (context == null)
         {
             return;
         }
         ResetAllValues(context);
         _scheduledAnimations.Remove(context);
     }
 }
Esempio n. 4
0
        /// <summary>
        /// Checks the state of all wait dependencies for the specified animation
        /// <paramref name="context"/> and tidies up the wait hierarchy, if appropriate.
        /// </summary>
        /// <returns><c>true</c>, if the specified animation is ready to be animated, else <c>false</c>.</returns>
        protected bool IsWaiting(AnimationContext context)
        {
            // Tidy up wait dependencies
            if (context.WaitingFor.Count == 0)
            {
                return(false);
            }

            bool allEndedOrStopped = true;

            foreach (AnimationContext waitForAc in context.WaitingFor)
            {
                int index = _scheduledAnimations.IndexOf(waitForAc);
                AnimationContext ac;
                if (index != -1)
                {
                    if ((ac = _scheduledAnimations[index]).Timeline.HasEnded(ac.TimelineContext))
                    {
                        endedWaitForAnimations.Add(waitForAc);
                    }
                    else
                    {
                        allEndedOrStopped = false;
                        break;
                    }
                }
            }
            try
            {
                if (allEndedOrStopped)
                {
                    // Stop all parent animations at once via the ExecuteHandoff method, when the last
                    // one ended. This will preserve all animations with FillBehavior.HoldEnd until
                    // the new animation starts.
                    context.WaitingFor.Clear();
                    ExecuteHandoff(context, endedWaitForAnimations, HandoffBehavior.SnapshotAndReplace);
                    return(false);
                }
                else
                {
                    // Animation isn't ready yet.
                    return(true);
                }
            }
            finally
            {
                endedWaitForAnimations.Clear();
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Will check the specified <paramref name="animationContext"/> for conflicts with already
        /// scheduled animations and returns those conflicts.
        /// </summary>
        /// <param name="animationContext">The new animation context to check against the running
        /// animations.</param>
        /// <param name="conflictingAnimations">Returns all already running or sleeping animations with
        /// conflicting properties.</param>
        /// <param name="conflictingProperties">Conflicting data descriptors mapped to their original
        /// values. This returned value can be used to initialize the original values of the new animation.</param>
        protected void FindConflicts(
            AnimationContext animationContext,
            out ICollection <AnimationContext> conflictingAnimations,
            out IDictionary <IDataDescriptor, object> conflictingProperties)
        {
            Timeline        newTL   = animationContext.Timeline;
            TimelineContext context = animationContext.TimelineContext;
            IDictionary <IDataDescriptor, object> newProperties = new Dictionary <IDataDescriptor, object>();

            newTL.AddAllAnimatedProperties(context, newProperties);
            ICollection <IDataDescriptor> newPDs = newProperties.Keys;

            conflictingAnimations = new List <AnimationContext>();
            conflictingProperties = new Dictionary <IDataDescriptor, object>();
            lock (_syncObject)
            {
                // Find conflicting properties in the values to be set
                foreach (KeyValuePair <IDataDescriptor, object> property in new Dictionary <IDataDescriptor, object>(_valuesToSet))
                {
                    if (!newPDs.Contains(property.Key))
                    {
                        continue;
                    }
                    conflictingProperties[property.Key] = property.Value;
                    _valuesToSet.Remove(property.Key);
                }
                // Find conflicting animations and conflicting animated properties
                foreach (AnimationContext ac in _scheduledAnimations)
                {
                    IDictionary <IDataDescriptor, object> animProperties = new Dictionary <IDataDescriptor, object>();
                    ac.Timeline.AddAllAnimatedProperties(ac.TimelineContext, animProperties);
                    bool isConflict = false;
                    foreach (KeyValuePair <IDataDescriptor, object> animProperty in animProperties)
                    {
                        if (!newPDs.Contains(animProperty.Key))
                        {
                            continue;
                        }
                        isConflict = true;
                        conflictingProperties[animProperty.Key] = animProperty.Value;
                    }
                    if (isConflict)
                    {
                        conflictingAnimations.Add(ac);
                    }
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        /// Handles the handoff between conflicting animations.
        /// This method will, depending on the specified <paramref name="handoffBehavior"/>, stop conflicting
        /// animations (in case see cref="HandoffBehavior.SnapshotAndReplace"/>)
        /// or add them to the wait set for the given <paramref name="animationContext"/>
        /// (in case <see cref="HandoffBehavior.Compose"/>).
        /// The handoff behavior <see cref="HandoffBehavior.TemporaryReplace"/> will stop the conflicting
        /// animations, let the new animation run, and re-schedule the conflicting animations after the new animation.
        /// </summary>
        protected void ExecuteHandoff(AnimationContext animationContext, ICollection <AnimationContext> conflictingAnimations,
                                      HandoffBehavior handoffBehavior)
        {
            // Do the handoff depending on HandoffBehavior
            switch (handoffBehavior)
            {
            case HandoffBehavior.Compose:
                foreach (AnimationContext ac in conflictingAnimations)
                {
                    animationContext.WaitingFor.Add(ac);
                }
                break;

            case HandoffBehavior.TemporaryReplace:
                foreach (AnimationContext ac in conflictingAnimations)
                {
                    ac.WaitingFor.Add(animationContext);
                }
                break;

            case HandoffBehavior.SnapshotAndReplace:
                // Reset values of conflicting animations
                foreach (AnimationContext ac in conflictingAnimations)
                {
                    ResetAllValues(ac);
                }
                // And remove those values which are handled by the new animation -
                // avoids flickering
                IDictionary <IDataDescriptor, object> animProperties = new Dictionary <IDataDescriptor, object>();
                animationContext.Timeline.AddAllAnimatedProperties(animationContext.TimelineContext, animProperties);
                foreach (IDataDescriptor dd in animProperties.Keys)
                {
                    _valuesToSet.Remove(dd);
                }
                break;

            default:
                throw new NotImplementedException("Animator.HandleConflicts: HandoffBehavior '" + handoffBehavior + "' is not implemented");
            }
        }
Esempio n. 7
0
        /// <summary>
        /// Starts the specified <paramref name="board"/> in the context of the specified
        /// <paramref name="element"/>.
        /// </summary>
        /// <remarks>
        /// Depending on the parameter <paramref name="handoffBehavior"/>, the new storyboard will
        /// be started when the last other storyboard, which occupies a conflicting property,
        /// has finished.
        /// </remarks>
        /// <param name="board">The storyboard to start.</param>
        /// <param name="element">Context element which will be used as
        /// <see cref="TimelineContext.VisualParent"/> for the new <paramref name="board"/>.</param>
        /// <param name="handoffBehavior">Controls how the new storyboard animation will be
        /// attached to already running animations, if there are conflicting properties animated
        /// by an already running anmiation an by the new <paramref name="board"/>.</param>
        public void StartStoryboard(Storyboard board, UIElement element,
                                    HandoffBehavior handoffBehavior)
        {
            lock (_syncObject)
            {
                AnimationContext context = new AnimationContext
                {
                    Timeline        = board,
                    TimelineContext = board.CreateTimelineContext(element)
                };

                IDictionary <IDataDescriptor, object> conflictingProperties;
                ICollection <AnimationContext>        conflictingAnimations;
                FindConflicts(context, out conflictingAnimations, out conflictingProperties);
                ExecuteHandoff(context, conflictingAnimations, handoffBehavior);

                board.Setup(context.TimelineContext, conflictingProperties);

                _scheduledAnimations.Add(context);
                board.Start(context.TimelineContext, SkinContext.SystemTickCount);

                // No animation here - has to be done in the Animate method
            }
        }
Esempio n. 8
0
 /// <summary>
 /// Handles the handoff between conflicting animations.
 /// This method will, depending on the specified <paramref name="handoffBehavior"/>, stop conflicting
 /// animations (in case see cref="HandoffBehavior.SnapshotAndReplace"/>)
 /// or add them to the wait set for the given <paramref name="animationContext"/>
 /// (in case <see cref="HandoffBehavior.Compose"/>).
 /// The handoff behavior <see cref="HandoffBehavior.TemporaryReplace"/> will stop the conflicting
 /// animations, let the new animation run, and re-schedule the conflicting animations after the new animation.
 /// </summary>
 protected void ExecuteHandoff(AnimationContext animationContext, ICollection<AnimationContext> conflictingAnimations,
     HandoffBehavior handoffBehavior)
 {
   // Do the handoff depending on HandoffBehavior
   switch (handoffBehavior)
   {
     case HandoffBehavior.Compose:
       foreach (AnimationContext ac in conflictingAnimations)
         animationContext.WaitingFor.Add(ac);
       break;
     case HandoffBehavior.TemporaryReplace:
       foreach (AnimationContext ac in conflictingAnimations)
         ac.WaitingFor.Add(animationContext);
       break;
     case HandoffBehavior.SnapshotAndReplace:
       // Reset values of conflicting animations
       foreach (AnimationContext ac in conflictingAnimations)
         ResetAllValues(ac);
       // And remove those values which are handled by the new animation -
       // avoids flickering
       IDictionary<IDataDescriptor, object> animProperties = new Dictionary<IDataDescriptor, object>();
       animationContext.Timeline.AddAllAnimatedProperties(animationContext.TimelineContext, animProperties);
       foreach (IDataDescriptor dd in animProperties.Keys)
         _valuesToSet.Remove(dd);
       break;
     default:
       throw new NotImplementedException("Animator.HandleConflicts: HandoffBehavior '" + handoffBehavior + "' is not implemented");
   }
 }
Esempio n. 9
0
 /// <summary>
 /// Will check the specified <paramref name="animationContext"/> for conflicts with already
 /// scheduled animations and returns those conflicts.
 /// </summary>
 /// <param name="animationContext">The new animation context to check against the running
 /// animations.</param>
 /// <param name="conflictingAnimations">Returns all already running or sleeping animations with
 /// conflicting properties.</param>
 /// <param name="conflictingProperties">Conflicting data descriptors mapped to their original
 /// values. This returned value can be used to initialize the original values of the new animation.</param>
 protected void FindConflicts(
     AnimationContext animationContext,
     out ICollection<AnimationContext> conflictingAnimations,
     out IDictionary<IDataDescriptor, object> conflictingProperties)
 {
   Timeline newTL = animationContext.Timeline;
   TimelineContext context = animationContext.TimelineContext;
   IDictionary<IDataDescriptor, object> newProperties = new Dictionary<IDataDescriptor, object>();
   newTL.AddAllAnimatedProperties(context, newProperties);
   ICollection<IDataDescriptor> newPDs = newProperties.Keys;
   conflictingAnimations = new List<AnimationContext>();
   conflictingProperties = new Dictionary<IDataDescriptor, object>();
   lock (_syncObject)
   {
     // Find conflicting properties in the values to be set
     foreach (KeyValuePair<IDataDescriptor, object> property in new Dictionary<IDataDescriptor, object>(_valuesToSet))
     {
       if (!newPDs.Contains(property.Key))
         continue;
       conflictingProperties[property.Key] = property.Value;
       _valuesToSet.Remove(property.Key);
     }
     // Find conflicting animations and conflicting animated properties
     foreach (AnimationContext ac in _scheduledAnimations)
     {
       IDictionary<IDataDescriptor, object> animProperties = new Dictionary<IDataDescriptor, object>();
       ac.Timeline.AddAllAnimatedProperties(ac.TimelineContext, animProperties);
       bool isConflict = false;
       foreach (KeyValuePair<IDataDescriptor, object> animProperty in animProperties)
       {
         if (!newPDs.Contains(animProperty.Key))
           continue;
         isConflict = true;
         conflictingProperties[animProperty.Key] = animProperty.Value;
       }
       if (isConflict)
         conflictingAnimations.Add(ac);
     }
   }
 }
Esempio n. 10
0
    /// <summary>
    /// Checks the state of all wait dependencies for the specified animation
    /// <paramref name="context"/> and tidies up the wait hierarchy, if appropriate.
    /// </summary>
    /// <returns><c>true</c>, if the specified animation is ready to be animated, else <c>false</c>.</returns>
    protected bool IsWaiting(AnimationContext context)
    {
      // Tidy up wait dependencies
      if (context.WaitingFor.Count == 0)
        return false;

      bool allEndedOrStopped = true;
      foreach (AnimationContext waitForAc in context.WaitingFor)
      {
        int index = _scheduledAnimations.IndexOf(waitForAc);
        AnimationContext ac;
        if (index != -1)
          if ((ac = _scheduledAnimations[index]).Timeline.HasEnded(ac.TimelineContext))
            endedWaitForAnimations.Add(waitForAc);
          else
          {
            allEndedOrStopped = false;
            break;
          }
      }
      try
      {
        if (allEndedOrStopped)
        {
          // Stop all parent animations at once via the ExecuteHandoff method, when the last
          // one ended. This will preserve all animations with FillBehavior.HoldEnd until
          // the new animation starts.
          context.WaitingFor.Clear();
          ExecuteHandoff(context, endedWaitForAnimations, HandoffBehavior.SnapshotAndReplace);
          return false;
        }
        else
          // Animation isn't ready yet.
          return true;
      }
      finally
      {
        endedWaitForAnimations.Clear();
      }
    }
Esempio n. 11
0
 protected void ResetAllValues(AnimationContext ac)
 {
   IDictionary<IDataDescriptor, object> animProperties = new Dictionary<IDataDescriptor, object>();
   ac.Timeline.AddAllAnimatedProperties(ac.TimelineContext, animProperties);
   foreach (KeyValuePair<IDataDescriptor, object> animProperty in animProperties)
     SetValue(animProperty.Key, animProperty.Value);
 }
Esempio n. 12
0
    /// <summary>
    /// Starts the specified <paramref name="board"/> in the context of the specified
    /// <paramref name="element"/>.
    /// </summary>
    /// <remarks>
    /// Depending on the parameter <paramref name="handoffBehavior"/>, the new storyboard will
    /// be started when the last other storyboard, which occupies a conflicting property,
    /// has finished.
    /// </remarks>
    /// <param name="board">The storyboard to start.</param>
    /// <param name="element">Context element which will be used as
    /// <see cref="TimelineContext.VisualParent"/> for the new <paramref name="board"/>.</param>
    /// <param name="handoffBehavior">Controls how the new storyboard animation will be
    /// attached to already running animations, if there are conflicting properties animated
    /// by an already running anmiation an by the new <paramref name="board"/>.</param>
    public void StartStoryboard(Storyboard board, UIElement element,
        HandoffBehavior handoffBehavior)
    {
      lock (_syncObject)
      {
        AnimationContext context = new AnimationContext
          {
              Timeline = board,
              TimelineContext = board.CreateTimelineContext(element)
          };

        IDictionary<IDataDescriptor, object> conflictingProperties;
        ICollection<AnimationContext> conflictingAnimations;
        FindConflicts(context, out conflictingAnimations, out conflictingProperties);
        ExecuteHandoff(context, conflictingAnimations, handoffBehavior);

        try
        {
          board.Setup(context.TimelineContext, conflictingProperties);

          _scheduledAnimations.Add(context);
          board.Start(context.TimelineContext, SkinContext.SystemTickCount);
        }
        catch (Exception ex)
        {
          ServiceRegistration.Get<ILogger>().Error("Animator: Error initializing StoryBoard", ex);
        }

        // No animation here - has to be done in the Animate method
      }
    }
Esempio n. 13
0
    /// <summary>
    /// Starts the specified <paramref name="board"/> in the context of the specified
    /// <paramref name="element"/>.
    /// </summary>
    /// <remarks>
    /// Depending on the parameter <paramref name="handoffBehavior"/>, the new storyboard will
    /// be started when the last other storyboard, which occupies a conflicting property,
    /// has finished.
    /// </remarks>
    /// <param name="board">The storyboard to start.</param>
    /// <param name="element">Context element which will be used as
    /// <see cref="TimelineContext.VisualParent"/> for the new <paramref name="board"/>.</param>
    /// <param name="handoffBehavior">Controls how the new storyboard animation will be
    /// attached to already running animations, if there are conflicting properties animated
    /// by an already running anmiation an by the new <paramref name="board"/>.</param>
    public void StartStoryboard(Storyboard board, UIElement element,
        HandoffBehavior handoffBehavior)
    {
      lock (_syncObject)
      {
        AnimationContext context = new AnimationContext
          {
              Timeline = board,
              TimelineContext = board.CreateTimelineContext(element)
          };

        IDictionary<IDataDescriptor, object> conflictingProperties;
        ICollection<AnimationContext> conflictingAnimations;
        FindConflicts(context, out conflictingAnimations, out conflictingProperties);
        ExecuteHandoff(context, conflictingAnimations, handoffBehavior);

        board.Setup(context.TimelineContext, conflictingProperties);

        _scheduledAnimations.Add(context);
        board.Start(context.TimelineContext, SkinContext.SystemTickCount);

        // No animation here - has to be done in the Animate method
      }
    }