public TimeTracker() { _timeline = new ParallelTimeline(null, Duration.Forever); _timeClock = _timeline.CreateClock(); _timeClock.Controller.Begin(); _lastTime = TimeSpan.FromSeconds(0); }
/// <summary>Defines timeline properties common to all atomic effects and returns the resulting total duration</summary> protected TimeSpan DefineTimelineCore(Timeline timeline, TimeSpan parentOffset) { var totalDuration = (Duration.HasValue ? Duration.Value : TimeSpan.Zero); timeline.Duration = totalDuration; if (RepeatCount.HasValue) { var repeatCount = RepeatCount.Value; if (!repeatCount.IsOne()) { if (Double.IsPositiveInfinity(repeatCount)) { timeline.RepeatBehavior = RepeatBehavior.Forever; } else { timeline.RepeatBehavior = new RepeatBehavior(repeatCount); totalDuration = TimeSpan.FromTicks((long)(totalDuration.Ticks * repeatCount)); } } } if (AutoReverse) { timeline.AutoReverse = true; totalDuration += totalDuration; } var offset = parentOffset + BeginTime; if (offset != TimeSpan.Zero) { timeline.BeginTime = offset; totalDuration += offset; } Assumption.IsFalse(totalDuration < TimeSpan.Zero, "An effect cannot have a negative duration"); return totalDuration; }
protected internal Clock(Timeline timeline) { _timeline = timeline; _timeline.CurrentGlobalSpeedInvalidated += new EventHandler(TimelineCurrentGlobalSpeedInvalidated); _timeline.CurrentStateInvalidated += new EventHandler(TimelineCurrentStateInvalidated); _timeline.CurrentTimeInvalidated += new EventHandler(TimelineCurrentTimeInvalidated); }
public static void BeginAnimation(this DependencyObject obj, DependencyProperty property, Timeline animation) { Storyboard.SetTargetProperty(animation, new PropertyPath(property)); Storyboard.SetTarget(animation, obj); var storyboard = new Storyboard(); storyboard.Children.Add(animation); storyboard.Begin(); }
public void Insert(int index, Timeline timeline) { if (timeline == null) { throw new ArgumentNullException("timeline"); } List.Insert(index, timeline); }
public int IndexOf(Timeline timeline) { if (timeline == null) { throw new ArgumentNullException("timeline"); } return List.IndexOf(timeline); }
public void CopyTo(Timeline[] array, int arrayIndex) { if (array == null) { throw new ArgumentNullException("array"); } List.CopyTo(array, arrayIndex); }
public bool Contains(Timeline timeline) { if (timeline == null) { throw new ArgumentNullException("timeline"); } return List.Contains(timeline); }
public void Add(Timeline timeline) { if (timeline == null) { throw new ArgumentNullException("timeline"); } List.Add(timeline); }
/// <summary> /// Extension method to quickly animate a DependencyObject. Simply provide the propertyPath and a timeline. /// </summary> /// <param name="element">The element to animate.</param> /// <param name="propertyPath">The property to animate.</param> /// <param name="timeline">The animation to apply to the element.</param> /// <param name="completed">The event handler to fire once the animation completes.</param> public static void Animate(this DependencyObject element, string propertyPath, Timeline timeline, EventHandler completed) { Storyboard sb = new Storyboard(); if (completed != null) sb.Completed += completed; sb.Children.Add(timeline); Storyboard.SetTarget(sb, element); Storyboard.SetTargetProperty(sb, new PropertyPath(propertyPath)); sb.Begin(); }
public static void BeginAnimation(Timeline animation, FrameworkElement element, DependencyProperty property, Action completed = null) { Storyboard.SetTarget(animation, element); Storyboard.SetTargetProperty(animation, new PropertyPath(property)); var sb = new Storyboard(); sb.Children.Add(animation); if (completed != null) sb.Completed += (s, e) => { completed.Invoke(); }; sb.Begin(element); }
protected internal Clock(Timeline timeline) { myAutoReverse = timeline.AutoReverse; myTimeline = timeline; myNaturalDuration = myTimeline.Duration; if (timeline.RepeatBehavior == RepeatBehavior.Forever) myTotalTime = float.MaxValue; else { if (timeline.RepeatBehavior.HasCount) myTotalTime = (float)(myTimeline.Duration.TimeSpan.TotalMilliseconds * myTimeline.RepeatBehavior.Count); else myTotalTime = (float)myTimeline.RepeatBehavior.Duration.TimeSpan.TotalMilliseconds; } mySystem.AddClock(this); }
public bool Remove(Timeline timeline) { if (timeline == null) { throw new ArgumentNullException("timeline"); } if (List.Contains(timeline) == false) { return false; } List.Remove(timeline); return true; }
private static TimeSpan GetTimeToFinished(Timeline timeline) { if (timeline.Duration.HasTimeSpan) { var beginTime = timeline.BeginTime ?? TimeSpan.Zero; return beginTime + timeline.Duration.TimeSpan; } var storyboard = timeline as Storyboard; if (storyboard != null) { if (storyboard.Children.Count == 0) { return TimeSpan.Zero; } return storyboard.Children.Max(x => GetTimeToFinished(x)); } throw new NotImplementedException(string.Format("GetTimeToFinished not implemented for: {0}", timeline.GetType().FullName)); }
/// <summary> /// Creates an enumerator that iterates over a subtree of timelines /// in prefix order. /// </summary> /// <param name="root"> /// The timeline that is the root of the subtree to enumerate. /// </param> /// <param name="processRoot"> /// True to include the root in the enumeration, false otherwise. /// </param> internal TimelineTreeEnumerator(Timeline root, bool processRoot) { _rootTimeline = root; _flags = processRoot ? (SubtreeFlag.Reset | SubtreeFlag.ProcessRoot) : SubtreeFlag.Reset; // Start with stacks of capacity 10. That's relatively small, yet // it covers very large trees without reallocation of stack data. // Note that given the way we use the stacks we need one less entry // for indices than for timelines, as we don't care what the index // of the root timeline is. _indexStack = new Stack(9); _timelineStack = new Stack<Timeline>(10); }
internal static Clock BuildClockTreeFromTimeline( Timeline rootTimeline, bool hasControllableRoot) { Clock rootClock = AllocateClock(rootTimeline, hasControllableRoot); // Set this flag so that the subsequent method can rely on it. rootClock.IsRoot = true; rootClock._rootData = new RootData(); // Create a RootData to hold root specific information. // The root clock was given a reference to a frozen copy of the // timing tree. We pass this copy down BuildClockSubTreeFromTimeline // so that each child clock will use that tree rather // than create a new one. rootClock.BuildClockSubTreeFromTimeline(rootClock.Timeline, hasControllableRoot); rootClock.AddToTimeManager(); return rootClock; }
internal virtual void BuildClockSubTreeFromTimeline( Timeline timeline, bool hasControllableRoot) { SetFlag(ClockFlags.CanSlip, GetCanSlip()); // Set the CanSlip flag // Here we preview the clock's own slip-ability, hence ClockGroups should return false // at this stage, because their children are not yet added by the time of this call. if (CanSlip && (IsRoot || _timeline.BeginTime.HasValue)) { ResolveDuration(); // A [....] clock with duration of zero or no begin time has no effect, so do skip it if (!_resolvedDuration.HasTimeSpan || _resolvedDuration.TimeSpan > TimeSpan.Zero) { // Verify that we only use SlipBehavior in supported scenarios if ((_timeline.AutoReverse == true) || (_timeline.AccelerationRatio > 0) || (_timeline.DecelerationRatio > 0)) { throw new NotSupportedException(SR.Get(SRID.Timing_CanSlipOnlyOnSimpleTimelines)); } _syncData = new SyncData(this); // CanSlip clocks keep themselves synced HasDescendantsWithUnresolvedDuration = !HasResolvedDuration; // Keep track of when our duration is resolved Clock current = _parent; // Traverse up the parent chain and verify that no unsupported behavior is specified while (current != null) { Debug.Assert(!current.IsTimeManager); // We should not yet be connected to the TimeManager if (current._timeline.AutoReverse || current._timeline.AccelerationRatio > 0 || current._timeline.DecelerationRatio > 0) { throw new System.InvalidOperationException(SR.Get(SRID.Timing_SlipBehavior_SyncOnlyWithSimpleParents)); } current.SetFlag(ClockFlags.CanGrow, true); // Propagate the slippage tracking up the tree if (!HasResolvedDuration) // Let the parents know that we have not yet unresolved duration { current.HasDescendantsWithUnresolvedDuration = true; } current._currentIterationBeginTime = current._beginTime; current = current._parent; } } } }
internal static Clock AllocateClock( Timeline timeline, bool hasControllableRoot) { Clock clock = timeline.AllocateClock(); // Assert that we weren't given an existing clock Debug.Assert(!clock.IsTimeManager); ClockGroup clockGroup = clock as ClockGroup; if ( clock._parent != null || ( clockGroup != null && clockGroup.InternalChildren != null )) { // The derived class is trying to fool us -- we require a new, // fresh, unassociated clock here throw new InvalidOperationException( SR.Get( SRID.Timing_CreateClockMustReturnNewClock, timeline.GetType().Name)); } clock.SetFlag(ClockFlags.HasControllableRoot, hasControllableRoot); return clock; }
// // Constructors // #region Constructors /// <summary> /// Creates a Clock object. /// </summary> /// <param name="timeline"> /// The Timeline to use as a template. /// </param> /// <remarks> /// The returned Clock doesn't have any children. /// </remarks> protected internal Clock(Timeline timeline) { #if DEBUG lock (_debugLockObject) { _debugIdentity = ++_nextIdentity; WeakReference weakRef = new WeakReference(this); _objectTable[_debugIdentity] = weakRef; } #endif // DEBUG Debug.Assert(timeline != null); // // Store a frozen copy of the timeline // _timeline = (Timeline)timeline.GetCurrentValueAsFrozen(); // GetCurrentValueAsFrozen will make a clone of the Timeline if it's // not frozen and will return the Timeline if it is frozen. // The clone will never have event handlers, while the // frozen original may. This means we need to copy // the event handlers from the original timeline onto the clock // to be consistent. // // Copy the event handlers from the original timeline into the clock // _eventHandlersStore = timeline.InternalEventHandlersStore; // // FXCop fix. Do not call overridables in constructors // UpdateNeedsTicksWhenActive(); // Set the NeedsTicksWhenActive only if we have someone listening // to an event. SetFlag(ClockFlags.NeedsTicksWhenActive, _eventHandlersStore != null); // // Cache values that won't change as the clock ticks // // Non-root clocks have an unchanging begin time specified by their timelines. // A root clock will update _beginTime as necessary. _beginTime = _timeline.BeginTime; // Cache duration, getting Timeline.Duration and recalculating duration // each Tick was eating perf, resolve the duration if possible. _resolvedDuration = _timeline.Duration; if (_resolvedDuration == Duration.Automatic) { // Forever is the default for an automatic duration. We can't // try to resolve the duration yet because the tree // may not be fully built, in which case ClockGroups won't // have their children yet. _resolvedDuration = Duration.Forever; } else { HasResolvedDuration = true; } _currentDuration = _resolvedDuration; // Cache speed ratio, for roots this value may be updated if the interactive // speed ratio changes, but for non-roots this value will remain constant // throughout the lifetime of the clock. _appliedSpeedRatio = _timeline.SpeedRatio; // // Initialize current state // _currentClockState = ClockState.Stopped; if (_beginTime.HasValue) { // We need a tick to bring our state up to date _nextTickNeededTime = TimeSpan.Zero; } // All other data members initialized to zero by default }
/// <summary> /// Helper for the UpdateDropIndicatorAnimationHeight method. /// </summary> private void UpdateDropIndicatorAnimationHeight(double height, Timeline animation) { DoubleAnimation da = animation as DoubleAnimation; if (da != null) { string targetName = Storyboard.GetTargetName(da); PropertyPath targetPath = Storyboard.GetTargetProperty(da); if ((targetName == ReorderListBoxItem.DropBeforeSpacePart || targetName == ReorderListBoxItem.DropAfterSpacePart) && targetPath != null && targetPath.Path == "Height") { if (da.From > 0 && da.From != height) { da.From = height; } if (da.To > 0 && da.To != height) { da.To = height; } } } }
// Hack for VSM. internal static DependencyProperty GetTargetDependencyProperty (Timeline element) { if (element == null) throw new ArgumentNullException ("element"); IntPtr ptr = NativeMethods.storyboard_get_target_dependency_property (element.native); return ptr == IntPtr.Zero ? null : DependencyProperty.Lookup (ptr); }
public static string GetTargetName (Timeline element) { return (string) element.GetValue (TargetNameProperty); }
public static void SetTargetName (Timeline element, string name) { // NOTE: this throws a NRE if element is null, while name == null is a valid value // FIXME Exception if setting on running element.SetValue (TargetNameProperty, name); }
public static void SetTarget (Timeline timeline, DependencyObject target) { if (timeline == null) throw new ArgumentNullException ("timeline"); if (target == null) throw new ArgumentNullException ("target"); // FIXME Exception if setting on running timeline.ManualTarget = target; }
// // Summary: // Causes the specified System.Windows.Media.Animation.Timeline to target the // specified object. // // Parameters: // timeline: // The timeline that targets the specified dependency object. // // target: // The actual instance of the object to target. // // Exceptions: // System.ArgumentNullException: // One or more of the parameters is null. extern public static void SetTarget(Timeline timeline, DependencyObject target);
public static void SetTargetProperty (Timeline element, PropertyPath path) { if (element == null) throw new ArgumentNullException ("element"); if (path == null) throw new ArgumentNullException ("path"); // FIXME Exception if setting on running element.SetValue (TargetPropertyProperty, path); }
// // Summary: // Causes the specified System.Windows.Media.Animation.Timeline to target the // object with the specified name. // // Parameters: // element: // The timeline that targets the specified dependency object. // // name: // The name of the object to target. extern public static void SetTargetName(Timeline element, string name);
public static PropertyPath GetTargetProperty (Timeline element) { if (element == null) throw new ArgumentNullException ("element"); return (PropertyPath) element.GetValue (TargetPropertyProperty); }
public TimelineClock(IClock baseClock, Timeline timeline) { this.clock = CreateClock(baseClock, timeline); this.Timeline = timeline; this.CurrentState = ClockState.Empty; }
// // Summary: // Causes the specified System.Windows.Media.Animation.Timeline to target the // specified dependency property. // // Parameters: // element: // The timeline with which to associate the specified dependency property. // // path: // A path that describe the dependency property to be animated. // // Exceptions: // System.ArgumentNullException: // One or more of the parameters is null. extern public static void SetTargetProperty(Timeline element, PropertyPath path);
/// <summary> /// Moves the clock forward to the current time and updates the state of /// all timing objects based on the time change. /// </summary> /// <remarks> /// The associated reference clock is used to determine the current time. /// The new position of the clock will be equal to the difference between the /// starting system time and the current system time. The time manager requires /// the system time to move forward. /// </remarks> public void Tick() { try { #if DEBUG // On a regular interval, clean up our tables of known // timelines and clocks if (++_frameCount >= 1000) // Should be about once every 10s { Timeline.CleanKnownTimelinesTable(); System.Windows.Media.Animation.Clock.CleanKnownClocksTable(); _frameCount = 0; } #endif // DEBUG // Don't need to worry about needing a tick sooner _nextTickTimeQueried = false; // Mark the tree as clean immediately. If any changes occur during // processing of the tick, the tree will be marked as dirty again. _isDirty = false; // No effect unless we are in the running state if (_timeState == TimeState.Running) { // Figure out the current time _globalTime = GetCurrentGlobalTime(); // Start the tick _isInTick = true; } // Trace the start of the tick and pass along the absolute time to which // we are ticking. EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnimation | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientTimeManagerTickBegin, (_startTime + _globalTime).Ticks / TimeSpan.TicksPerMillisecond); // Run new property querying logic on the timing tree if (_lastTimeState == TimeState.Stopped && _timeState == TimeState.Stopped) // We were stopped the whole time { _currentTickInterval = TimeIntervalCollection.CreateNullPoint(); } else // We were not stopped at some time, so process the tick interval { _currentTickInterval = TimeIntervalCollection.CreateOpenClosedInterval(_lastTickTime, _globalTime); // If at either tick we were stopped, add the null point to represent that if (_lastTimeState == TimeState.Stopped || _timeState == TimeState.Stopped) { _currentTickInterval.AddNullPoint(); } } // Compute the tree state, using _currentTickInterval to compute the events that occured _timeManagerClock.ComputeTreeState(); // Cache TimeManager state at this time _lastTimeState = _timeState; // When the tick is done, we raise timing events RaiseEnqueuedEvents(); } finally { _isInTick = false; // Cache the tick time _lastTickTime = _globalTime; //trace the end of the tick EventTrace.EasyTraceEvent(EventTrace.Keyword.KeywordAnimation | EventTrace.Keyword.KeywordPerf, EventTrace.Event.WClientTimeManagerTickEnd); } // At the end of every tick clean up GC'ed clocks, if necessary CleanupClocks(); }
protected internal Clock(Timeline timeline) { }
internal override void BuildClockSubTreeFromTimeline( Timeline timeline, bool hasControllableRoot) { // This is not currently necessary //base.BuildClockSubTreeFromTimeline(timeline); // Only TimelineGroup has children TimelineGroup timelineGroup = timeline as TimelineGroup; // Only a TimelineGroup should have allocated a ClockGroup. Debug.Assert(timelineGroup != null); // Create a clock for each of the children of the timeline TimelineCollection timelineChildren = timelineGroup.Children; if (timelineChildren != null && timelineChildren.Count > 0) { Clock childClock; // Create a collection for the children of the clock _children = new List <Clock>(); // Create clocks for the children for (int index = 0; index < timelineChildren.Count; index++) { childClock = AllocateClock(timelineChildren[index], hasControllableRoot); childClock._parent = this; // We connect the child to the subtree before calling BuildClockSubtreeFromTimeline childClock.BuildClockSubTreeFromTimeline(timelineChildren[index], hasControllableRoot); _children.Add(childClock); childClock._childIndex = index; } // If we have SlipBehavior, check if we have any childen with which to slip. if (_timeline is ParallelTimeline && ((ParallelTimeline)_timeline).SlipBehavior == SlipBehavior.Slip) { // Verify that we only use SlipBehavior in supported scenarios if (!IsRoot || (_timeline.RepeatBehavior.HasDuration) || (_timeline.AutoReverse == true) || (_timeline.AccelerationRatio > 0) || (_timeline.DecelerationRatio > 0)) { throw new NotSupportedException(SR.Get(SRID.Timing_SlipBehavior_SlipOnlyOnSimpleTimelines)); } for (int index = 0; index < _children.Count; index++) { Clock child = _children[index]; if (child.CanSlip) { Duration duration = child.ResolvedDuration; // A [....] clock with duration of zero or no begin time has no effect, so do skip it if ((!duration.HasTimeSpan || duration.TimeSpan > TimeSpan.Zero) && child._timeline.BeginTime.HasValue) { _syncData = new SyncData(child); child._syncData = null; // The child will no longer self-[....] } break; // We only want the first child with CanSlip } } } } }