Example #1
0
        //
        // 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
        }