Code:
/ DotNET / DotNET / 8.0 / untmp / WIN_WINDOWS / lh_tools_devdiv_wpf / Windows / wcp / Core / System / Windows / Media / Animation / AnimationStorage.cs / 1 / AnimationStorage.cs
// DependencyPropertyAnimationStorage.cs using MS.Internal; using MS.Utility; using System.Collections.Generic; using System.Diagnostics; using System.Windows.Threading; using System.Windows.Media.Composition; using System.Windows.Media.Media3D; using MS.Internal.PresentationCore; // SR, SRID, FriendAccessAllowed namespace System.Windows.Media.Animation { internal class AnimationStorage { #if DEBUG private static int _nextID = 1; private readonly int DebugID = _nextID++; #endif #region Constructor protected AnimationStorage() { _currentTimeInvalidatedHandler = new EventHandler(OnCurrentTimeInvalidated); _removeRequestedHandler = new EventHandler(OnRemoveRequested); } #endregion #region Uncommon Fields private static readonly UncommonFieldAnimatedPropertyMapField = new UncommonField (); #endregion #region Properties internal bool IsEmpty { get { Debug.Assert( _animationClocks == null || _animationClocks.Count > 0); Debug.Assert( _propertyTriggerLayers == null || _propertyTriggerLayers.Count > 0); return _animationClocks == null && _propertyTriggerLayers == null && _snapshotValue == DependencyProperty.UnsetValue; } } #endregion #region Methods /// /// Attaches an AnimationClock but does not add it to the collection. /// ////// It's expected that the AnimationClock will have been added to the /// collection before this is called. /// /// The AnimationClock. /// /// The event handler to be executed when the RemoveRequested event is /// raised by the AnimationClock. /// internal void AttachAnimationClock( AnimationClock animationClock, EventHandler removeRequestedHandler) { Debug.Assert(animationClock != null); Debug.Assert(_dependencyObject.Target != null); Debug.Assert(_currentTimeInvalidatedHandler != null); animationClock.CurrentTimeInvalidated += _currentTimeInvalidatedHandler; if (animationClock.HasControllableRoot) { animationClock.RemoveRequested += removeRequestedHandler; } } ////// Detaches an AnimationClock but does not remove it from the collection. /// ////// It's expected that the AnimationClock will be removed from the /// collection immediately after calling this method. /// /// The AnimationClock. /// /// The event handler associated with the RemoveRequested event on the /// AnimationClock. /// internal void DetachAnimationClock( AnimationClock animationClock, EventHandler removeRequestedHandler) { Debug.Assert(animationClock != null); Debug.Assert(_currentTimeInvalidatedHandler != null); animationClock.CurrentTimeInvalidated -= _currentTimeInvalidatedHandler; if (animationClock.HasControllableRoot) { animationClock.RemoveRequested -= removeRequestedHandler; } } internal void Initialize(DependencyObject d, DependencyProperty dp) { Debug.Assert(_dependencyObject == null); Debug.Assert(_dependencyProperty == null); Animatable a = d as Animatable; if (a != null) { _dependencyObject = a.GetWeakReference(); } else { // _dependencyObject = new WeakReference(d); } _dependencyProperty = dp; } ////// /// /// internal void RemoveLayer(AnimationLayer layer) { Debug.Assert(_propertyTriggerLayers != null); Debug.Assert(_propertyTriggerLayers.ContainsValue(layer)); int index = _propertyTriggerLayers.IndexOfValue(layer); Debug.Assert(index >= 0); _propertyTriggerLayers.RemoveAt(index); if (_propertyTriggerLayers.Count == 0) { _propertyTriggerLayers = null; } } ////// This should be called at the end of any method that alters the /// storage in any way. This method will make sure the peer dp is /// set correctly and notify Animatables if something changes. /// internal void WritePostscript() { DependencyObject d = (DependencyObject)_dependencyObject.Target; if (d == null) { return; } FrugalMap animatedPropertyMap = AnimatedPropertyMapField.GetValue(d); if ( animatedPropertyMap.Count == 0 || animatedPropertyMap[_dependencyProperty.GlobalIndex] == DependencyProperty.UnsetValue) { if (!IsEmpty) { // This is kind of tricky: // // Because FrugalMap is a struct instead of a class, we must // be sure to add this AnimationStorage to the map before // setting the FrugalMap into the UncommonField storage. If // we don't and the FrugalMap is empty then an empty FrugalMap // will be set into the UncommonField storage. If we were to // then add our AnimationStorage to the local FrugalMap, it // would only allocate its own internal storage at that point // which would not apply to the FrugalMap we set into the // UncommonField storage. Once a FrugalMap has allocated its // internal storage, though, that storage is copied with the // FrugalMap. This is what will happen when we add our // AnimationStorage to the FrugalMap first as we do below: animatedPropertyMap[_dependencyProperty.GlobalIndex] = this; // Since FrugalMap is a struct and adding a new value to it // may re-allocate the storage, we need to set this value // each time we make a change to the map. AnimatedPropertyMapField.SetValue(d, animatedPropertyMap); if (animatedPropertyMap.Count == 1) { d.IAnimatable_HasAnimatedProperties = true; } // If this the target is an Animatable we'll need to // invalidate it so that the animation resource for this // newly animated property will be passed across to the UCE. Animatable a = d as Animatable; if (a != null) { a.RegisterForAsyncUpdateResource(); } // If this AnimationStorage is a resource, add it to the // channel now. DUCE.IResource animationResource = this as DUCE.IResource; if (animationResource != null) { DUCE.IResource targetResource = d as DUCE.IResource; if (targetResource != null) { using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int i = 0; i < channelCount; i++) { DUCE.Channel channel = targetResource.GetChannel(i); if (!targetResource.GetHandle(channel).IsNull) { animationResource.AddRefOnChannel(channel); } } } } } } } else { Debug.Assert(animatedPropertyMap.Count > 0); Debug.Assert(animatedPropertyMap[_dependencyProperty.GlobalIndex] != DependencyProperty.UnsetValue); if (IsEmpty) { // If this AnimationStorage is a resource, release it from // the channel now. DUCE.IResource animationResource = this as DUCE.IResource; if (animationResource != null) { DUCE.IResource targetResource = d as DUCE.IResource; if (targetResource != null) { using (CompositionEngineLock.Acquire()) { int channelCount = targetResource.GetChannelCount(); for (int i = 0; i < channelCount; i++) { DUCE.Channel channel = targetResource.GetChannel(i); if (!targetResource.GetHandle(channel).IsNull) { animationResource.ReleaseOnChannel(channel); } } } } } // If this the target is an Animatable we'll need to // invalidate it so that the animation resource for this // no longer animated property will no longer be passed // across to the UCE. Animatable a = d as Animatable; if (a != null) { a.RegisterForAsyncUpdateResource(); } animatedPropertyMap[_dependencyProperty.GlobalIndex] = DependencyProperty.UnsetValue; if (animatedPropertyMap.Count == 0) { AnimatedPropertyMapField.ClearValue(d); d.IAnimatable_HasAnimatedProperties = false; } else { AnimatedPropertyMapField.SetValue(d, animatedPropertyMap); } // We've removed animation storage for this DP, so if we were storing the local // base value here then it has to go back to its non-animated storage spot. if (_baseValue != DependencyProperty.UnsetValue) { d.SetValue(_dependencyProperty, _baseValue); } } } // recompute animated value d.InvalidateProperty(_dependencyProperty); } #endregion #region Private private void OnCurrentTimeInvalidated(object sender, EventArgs args) { object target = _dependencyObject.Target; if (target == null) { // If the target has been garbage collected, remove this handler // from the AnimationClock so that this collection can be // released also. DetachAnimationClock((AnimationClock)sender, _removeRequestedHandler); } else { // recompute animated value try { DependencyObject targetDO = ((DependencyObject)target); // fetch the existing entry EffectiveValueEntry oldEntry = targetDO.GetValueEntry( targetDO.LookupEntry(_dependencyProperty.GlobalIndex), _dependencyProperty, null, RequestFlags.RawEntry); EffectiveValueEntry newEntry; object value; // create a copy of that entry, removing animated & coerced values if (!oldEntry.HasModifiers) { // no modifiers; just use it, removing deferred references newEntry = oldEntry; value = newEntry.Value; if (newEntry.IsDeferredReference) { value = ((DeferredReference) value).GetValue(newEntry.BaseValueSourceInternal); newEntry.Value = value; newEntry.IsDeferredReference = false; } } else { // else entry has modifiers; preserve expression but throw away // coerced & animated values, since we'll be recomputing an animated value newEntry = new EffectiveValueEntry(); newEntry.BaseValueSourceInternal = oldEntry.BaseValueSourceInternal; newEntry.PropertyIndex = oldEntry.PropertyIndex; newEntry.HasExpressionMarker = oldEntry.HasExpressionMarker; value = oldEntry.ModifiedValue.BaseValue; if (oldEntry.IsDeferredReference) { DeferredReference dr = value as DeferredReference; if (dr != null) { value = dr.GetValue(newEntry.BaseValueSourceInternal); } } newEntry.Value = value; if (oldEntry.IsExpression) { value = oldEntry.ModifiedValue.ExpressionValue; if (oldEntry.IsDeferredReference) { DeferredReference dr = value as DeferredReference; if (dr != null) { value = dr.GetValue(newEntry.BaseValueSourceInternal); } } newEntry.SetExpressionValue(value, newEntry.Value); } } // compute the new value for the property PropertyMetadata metadata = _dependencyProperty.GetMetadata(targetDO.DependencyObjectType); object animatedValue = AnimationStorage.GetCurrentPropertyValue(this, targetDO, _dependencyProperty, metadata, value); // update the new entry to contain the new animated value newEntry.SetAnimatedValue(animatedValue, value); // call UpdateEffectiveValue to put the new entry in targetDO's effective values table targetDO.UpdateEffectiveValue( targetDO.LookupEntry(_dependencyProperty.GlobalIndex), _dependencyProperty, metadata, oldEntry, ref newEntry, false /* coerceWithDeferredReference */, OperationType.Unknown); } catch (Exception e) { // Catch all exceptions thrown during the InvalidateProperty callstack // and wrap them in an AnimationException throw new AnimationException( (AnimationClock)sender, _dependencyProperty, (IAnimatable)target, SR.Get( SRID.Animation_Exception, _dependencyProperty.Name, target.GetType().FullName, ((AnimationClock)sender).Timeline.GetType().FullName), e); } } } private void OnRemoveRequested(object sender, EventArgs args) { Debug.Assert( _animationClocks != null && _animationClocks.Count > 0, "An AnimationClock no longer associated with a property should not have a RemoveRequested event handler."); AnimationClock animationClock = (AnimationClock)sender; int index = _animationClocks.IndexOf(animationClock); Debug.Assert(index > -1, "An AnimationClock no longer associated with a property should not have a RemoveRequested event handler."); _animationClocks.RemoveAt(index); if ( _hasStickySnapshotValue && index == 0) { // The first clock is always the one that would have unstuck // the snapshot value. Since it's been removed, instick the // snapshot value now. _hasStickySnapshotValue = false; animationClock.CurrentStateInvalidated -= new EventHandler(OnCurrentStateInvalidated); } if (_animationClocks.Count == 0) { _animationClocks = null; _snapshotValue = DependencyProperty.UnsetValue; } DetachAnimationClock(animationClock, _removeRequestedHandler); WritePostscript(); } private void OnCurrentStateInvalidated(object sender, EventArgs args) { Debug.Assert(_hasStickySnapshotValue, "_hasStickySnapshotValue should be set to true if OnCurrentStateInvalidated has been called."); _hasStickySnapshotValue = false; ((AnimationClock)sender).CurrentStateInvalidated -= new EventHandler(OnCurrentStateInvalidated); } private void ClearAnimations() { if (_animationClocks != null) { Debug.Assert(_animationClocks.Count > 0); for (int i = 0; i < _animationClocks.Count; i++) { DetachAnimationClock(_animationClocks[i], _removeRequestedHandler); } _animationClocks = null; } } #endregion #region Static Helper Methods internal static void ApplyAnimationClock( DependencyObject d, DependencyProperty dp, AnimationClock animationClock, HandoffBehavior handoffBehavior) { if (animationClock == null) { BeginAnimation(d, dp, null, handoffBehavior); } else { // ApplyAnimationClocks(d, dp, new AnimationClock[] { animationClock }, handoffBehavior); } } [FriendAccessAllowed] // Built into Core, also used by Framework. internal static void ApplyAnimationClocks( DependencyObject d, DependencyProperty dp, IListanimationClocks, HandoffBehavior handoffBehavior) { Debug.Assert(animationClocks != null, "The animationClocks parameter should not be passed in as null."); Debug.Assert(animationClocks.Count > 0, "The animationClocks parameter should contain at least one clock."); Debug.Assert(!animationClocks.Contains(null), "The animationClocks parameter should not contain a null entry."); Debug.Assert(HandoffBehaviorEnum.IsDefined(handoffBehavior), "Public API caller of this internal method is responsible for validating that the HandoffBehavior value is valid." ); AnimationStorage storage = GetStorage(d, dp); // handoffBehavior is SnapshotAndReplace or the situation is such // that it is the equivalent because we have nothing to compose // with. if ( handoffBehavior == HandoffBehavior.SnapshotAndReplace || storage == null || storage._animationClocks == null) { if (storage != null) { EventHandler handler = new EventHandler(storage.OnCurrentStateInvalidated); // If we have a sticky snapshot value, the clock that would have // unstuck it is being replaced, so we need to remove our event // handler from that clock. if (storage._hasStickySnapshotValue) { storage._animationClocks[0].CurrentStateInvalidated -= handler; } // Calculate a snapshot value if we don't already have one // since the last tick. else { storage._snapshotValue = d.GetValue(dp); } // If we have a new clock in a stopped state, then the snapshot // value will be sticky. if (animationClocks[0].CurrentState == ClockState.Stopped) { storage._hasStickySnapshotValue = true; animationClocks[0].CurrentStateInvalidated += new EventHandler(storage.OnCurrentStateInvalidated); } // Otherwise it won't be sticky. else { storage._hasStickySnapshotValue = false; } storage.ClearAnimations(); } else { storage = CreateStorage(d, dp); } // Add and attach new animation. storage._animationClocks = new FrugalObjectList (animationClocks.Count); for (int i = 0; i < animationClocks.Count; i++) { Debug.Assert(animationClocks[i] != null); storage._animationClocks.Add(animationClocks[i]); storage.AttachAnimationClock(animationClocks[i], storage._removeRequestedHandler); } } else { Debug.Assert(handoffBehavior == HandoffBehavior.Compose); Debug.Assert(storage != null); Debug.Assert(storage._animationClocks != null); FrugalObjectList newClockCollection = new FrugalObjectList (storage._animationClocks.Count + animationClocks.Count); for (int i = 0; i < storage._animationClocks.Count; i++) { newClockCollection.Add(storage._animationClocks[i]); } storage._animationClocks = newClockCollection; for (int i = 0; i < animationClocks.Count; i++) { newClockCollection.Add(animationClocks[i]); storage.AttachAnimationClock(animationClocks[i], storage._removeRequestedHandler); } } storage.WritePostscript(); } /// /// Applies animation clocks to a layer /// /// /// /// /// /// [FriendAccessAllowed] internal static void ApplyAnimationClocksToLayer( DependencyObject d, DependencyProperty dp, IListanimationClocks, HandoffBehavior handoffBehavior, Int64 propertyTriggerLayerIndex) { if( propertyTriggerLayerIndex == 1 ) { // Layer 1 is a special layer, where it gets treated as if there // was no layer specification at all. ApplyAnimationClocks( d, dp, animationClocks, handoffBehavior ); return; } Debug.Assert(animationClocks != null); Debug.Assert(!animationClocks.Contains(null)); Debug.Assert(HandoffBehaviorEnum.IsDefined(handoffBehavior), "Public API caller of this internal method is responsible for validating that the HandoffBehavior value is valid."); AnimationStorage storage = GetStorage(d, dp); if (storage == null) { storage = CreateStorage(d, dp); } SortedList propertyTriggerLayers = storage._propertyTriggerLayers; if (propertyTriggerLayers == null) { propertyTriggerLayers = new SortedList (1); storage._propertyTriggerLayers = propertyTriggerLayers; } AnimationLayer layer; if (propertyTriggerLayers.ContainsKey(propertyTriggerLayerIndex)) { layer = propertyTriggerLayers[propertyTriggerLayerIndex]; } else { layer = new AnimationLayer(storage); propertyTriggerLayers[propertyTriggerLayerIndex] = layer; } object defaultDestinationValue = DependencyProperty.UnsetValue; if (handoffBehavior == HandoffBehavior.SnapshotAndReplace) { // defaultDestinationValue = ((IAnimatable)d).GetAnimationBaseValue(dp); int count = propertyTriggerLayers.Count; if (count > 1) { IList keys = propertyTriggerLayers.Keys; for (int i = 0; i < count && keys[i] < propertyTriggerLayerIndex; i++) { AnimationLayer currentLayer; propertyTriggerLayers.TryGetValue(keys[i], out currentLayer); defaultDestinationValue = currentLayer.GetCurrentValue(defaultDestinationValue); } } } layer.ApplyAnimationClocks( animationClocks, handoffBehavior, defaultDestinationValue); storage.WritePostscript(); } internal static void BeginAnimation( DependencyObject d, DependencyProperty dp, AnimationTimeline animation, HandoffBehavior handoffBehavior) { // Caller should be validating animation. Debug.Assert(animation == null || IsAnimationValid(dp, animation)); Debug.Assert(IsPropertyAnimatable(d, dp)); Debug.Assert(HandoffBehaviorEnum.IsDefined(handoffBehavior), "Public API caller of this internal method is responsible for validating that the HandoffBehavior value is valid." ); AnimationStorage storage = GetStorage(d, dp); if (animation == null) { if ( storage == null || handoffBehavior == HandoffBehavior.Compose) { // Composing with a null animation is a no-op. return; } else { // When the incoming animation is passed in as null and // handoffBehavior == HandoffBehavior.SnapshotAndReplace it means // that we should stop any and all animation behavior for // this property. if (storage._hasStickySnapshotValue) { storage._hasStickySnapshotValue = false; storage._animationClocks[0].CurrentStateInvalidated -= new EventHandler(storage.OnCurrentStateInvalidated); } storage._snapshotValue = DependencyProperty.UnsetValue; storage.ClearAnimations(); } } else if (animation.BeginTime.HasValue) { // We have an animation AnimationClock animationClock; animationClock = animation.CreateClock(); // note that CreateClock also calls InternalBeginIn ApplyAnimationClocks(d, dp, new AnimationClock[] { animationClock }, handoffBehavior); // ApplyAnimationClocks has fixed up the storage and called // WritePostscript already so we can just return. return; } else if (storage == null) { // The user gave us an animation with a BeginTime of null which // means snapshot the current value and throw away all animations // for SnapshotAndReplace and means nothing for Compose. // But since we don't have any animations the current we don't // have to do anything for either of these cases. return; } else if (handoffBehavior == HandoffBehavior.SnapshotAndReplace) { // This block handles the case where the user has called // BeginAnimation with an animation that has a null begin time. // We handle this by taking a snapshot value and throwing // out the animation, which is the same as keeping it because // we know it will never start. // // If the handoffBehavior is Compose, we ignore the user's call // because it wouldn't mean anything unless they were planning // on changing the BeginTime of their animation later, which we // don't support. // If _hasStickySnapshotValue is set, unset it and remove our // event handler from the clock. The current snapshot value // will still be used. if (storage._hasStickySnapshotValue) { Debug.Assert(storage._animationClocks != null && storage._animationClocks.Count > 0, "If _hasStickySnapshotValue is set we should have at least one animation clock stored in the AnimationStorage."); storage._hasStickySnapshotValue = false; storage._animationClocks[0].CurrentStateInvalidated -= new EventHandler(storage.OnCurrentStateInvalidated); } // Otherwise take a new snapshot value. else { storage._snapshotValue = d.GetValue(dp); } storage.ClearAnimations(); } // If storage were null we would have returned already. storage.WritePostscript(); } internal static AnimationStorage EnsureStorage( DependencyObject d, DependencyProperty dp) { FrugalMap animatedPropertyMap = AnimatedPropertyMapField.GetValue(d); object currentStorage = animatedPropertyMap[dp.GlobalIndex]; if (currentStorage == DependencyProperty.UnsetValue) { return CreateStorage(d, dp); } else { return (AnimationStorage)currentStorage; } } /// /// GetCurrentPropertyValue /// ///internal static object GetCurrentPropertyValue( AnimationStorage storage, DependencyObject d, DependencyProperty dp, PropertyMetadata metadata, object baseValue) { Debug.Assert(storage != null, "The 'storage' parameter cannot be passed into the GetCurrentPropertyValue method as null."); // If changes have been made to the snapshot value since the last tick // that value represents the current value of the property until the // next tick when the flag will be cleared. We will only take one // snapshot value between ticks. // // Since CurrentTimeInvaliated is raised before CurrentStateInvalidated // we need to check the state of the first clock as well to avoid // potential first frame issues. In this case _hasStickySnapshotValue // will be updated to false shortly. if ( storage._hasStickySnapshotValue && storage._animationClocks[0].CurrentState == ClockState.Stopped) { return storage._snapshotValue; } if ( storage._animationClocks == null && storage._propertyTriggerLayers == null) { Debug.Assert(storage._snapshotValue != DependencyProperty.UnsetValue); return storage._snapshotValue; } object currentPropertyValue = baseValue; if (currentPropertyValue == DependencyProperty.UnsetValue) { currentPropertyValue = metadata.GetDefaultValue(d, dp); } Debug.Assert(currentPropertyValue != DependencyProperty.UnsetValue); // // Process property trigger animations. // if (storage._propertyTriggerLayers != null) { int count = storage._propertyTriggerLayers.Count; Debug.Assert(count > 0); IList layers = storage._propertyTriggerLayers.Values; for (int i = 0; i < count; i++) { currentPropertyValue = layers[i].GetCurrentValue(currentPropertyValue); } } // // Process local animations // if (storage._animationClocks != null) { FrugalObjectList clocks = storage._animationClocks; int clocksCount = clocks.Count; bool hasActiveOrFillingClock = false; // default destination value will be the current property value // calculated by the previous layer. object defaultDestinationValue = currentPropertyValue; object currentLayerValue = currentPropertyValue; // if we have a snapshot value, then that will be the new // initial current property value. if (storage._snapshotValue != DependencyProperty.UnsetValue) { currentLayerValue = storage._snapshotValue; } Debug.Assert(clocksCount > 0); Debug.Assert(defaultDestinationValue != DependencyProperty.UnsetValue); for (int i = 0; i < clocksCount; i++) { if (clocks[i].CurrentState != ClockState.Stopped) { hasActiveOrFillingClock = true; currentLayerValue = clocks[i].GetCurrentValue(currentLayerValue, defaultDestinationValue); // An animation may not return DependencyProperty.UnsetValue as its // current value. if (currentLayerValue == DependencyProperty.UnsetValue) { throw new InvalidOperationException(SR.Get( SRID.Animation_ReturnedUnsetValueInstance, clocks[i].Timeline.GetType().FullName, dp.Name, d.GetType().FullName)); } } } // The currentLayerValue only applies when there is at least one // active or filling clock. if (hasActiveOrFillingClock) { currentPropertyValue = currentLayerValue; } } // We have a calculated currentPropertyValue, so validate it and // then return it. if (dp.IsValidValue(currentPropertyValue)) { return currentPropertyValue; } else { // If the animation(s) applied to the property have calculated an // invalid value for the property then raise an exception. throw new InvalidOperationException( SR.Get( SRID.Animation_CalculatedValueIsInvalidForProperty, dp.Name, (currentPropertyValue == null ? "null" : currentPropertyValue.ToString()))); } } [FriendAccessAllowed] // Built into Core, also used by Framework. internal static bool IsPropertyAnimatable( DependencyObject d, DependencyProperty dp) { // if (dp.PropertyType != typeof(Visual3DCollection) && dp.ReadOnly) { return false; } UIPropertyMetadata uiMetadata = dp.GetMetadata(d.DependencyObjectType) as UIPropertyMetadata; if ( uiMetadata != null && uiMetadata.IsAnimationProhibited) { return false; } return true; } internal static bool IsAnimationValid( DependencyProperty dp, AnimationTimeline animation) { return dp.PropertyType.IsAssignableFrom(animation.TargetPropertyType) || (animation.TargetPropertyType == typeof(Object)); } [FriendAccessAllowed] // Built into Core, also used by Framework. internal static bool IsAnimationClockValid( DependencyProperty dp, AnimationClock animation) { return IsAnimationValid(dp, (AnimationTimeline)animation.Timeline); } /// /// Returns the list of animated DependencyProperties for a /// given DependencyObject. /// /// /// The DependencyObject. /// ////// The list of animated DependencyProperties if any are animated; /// otherwise null. /// internal static FrugalMap GetAnimatedPropertiesMap(DependencyObject d) { return AnimatedPropertyMapField.GetValue(d); } ////// Returns the AnimationStorage associated with a given DependencyProperty /// on a give DependencyObject. /// /// The DependencyObject. /// The DependencyProperty. ////// The AnimationStorage associated with the DependencyProperty if it /// has any; otherwise null. /// internal static AnimationStorage GetStorage(DependencyObject d, DependencyProperty dp) { Debug.Assert( AnimatedPropertyMapField.GetValue(d)[dp.GlobalIndex] == DependencyProperty.UnsetValue || AnimatedPropertyMapField.GetValue(d)[dp.GlobalIndex] is AnimationStorage); return AnimatedPropertyMapField.GetValue(d)[dp.GlobalIndex] as AnimationStorage; } private static AnimationStorage CreateStorage( DependencyObject d, DependencyProperty dp) { AnimationStorage newStorage; if (dp.GetMetadata(d.DependencyObjectType) is IndependentlyAnimatedPropertyMetadata) { newStorage = CreateIndependentAnimationStorageForType(dp.PropertyType); } else { newStorage = new AnimationStorage(); } newStorage.Initialize(d, dp); return newStorage; } private static IndependentAnimationStorage CreateIndependentAnimationStorageForType(Type type) { if (type == typeof(Double)) { return new DoubleIndependentAnimationStorage(); } else if (type == typeof(Color)) { return new ColorIndependentAnimationStorage(); } else if (type == typeof(Matrix)) { return new MatrixIndependentAnimationStorage(); } else if (type == typeof(Point3D)) { return new Point3DIndependentAnimationStorage(); } else if (type == typeof(Point)) { return new PointIndependentAnimationStorage(); } else if (type == typeof(Quaternion)) { return new QuaternionIndependentAnimationStorage(); } else if (type == typeof(Rect)) { return new RectIndependentAnimationStorage(); } else if (type == typeof(Size)) { return new SizeIndependentAnimationStorage(); } else { Debug.Assert(type == typeof(Vector3D), "Application is trying to create independent animation storage for an unsupported type."); return new Vector3DIndependentAnimationStorage(); } } #endregion #region Data protected WeakReference _dependencyObject; protected DependencyProperty _dependencyProperty; protected FrugalObjectList_animationClocks; private SortedList _propertyTriggerLayers; private EventHandler _currentTimeInvalidatedHandler; private EventHandler _removeRequestedHandler; private object _snapshotValue = DependencyProperty.UnsetValue; private bool _hasStickySnapshotValue; // This can be used by Animatables to store a local value if // they provide a WriteLocalValueOverride but need to spill // the local value if they are animated because they also use // the local value storage as a current value cache. internal object _baseValue = DependencyProperty.UnsetValue; #endregion } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007. // Copyright (c) Microsoft Corporation. All rights reserved.
Link Menu

This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- CompositeTypefaceMetrics.cs
- HttpWriter.cs
- TextDecorationCollection.cs
- BlurEffect.cs
- PrinterUnitConvert.cs
- DashStyles.cs
- AxHost.cs
- ListView.cs
- IMembershipProvider.cs
- GregorianCalendar.cs
- XPathNodeInfoAtom.cs
- NameValueCollection.cs
- BaseValidator.cs
- QuotedStringWriteStateInfo.cs
- SQLBinaryStorage.cs
- ChildChangedEventArgs.cs
- FamilyCollection.cs
- MissingMethodException.cs
- DiscardableAttribute.cs
- Environment.cs
- EnumerableRowCollection.cs
- SpAudioStreamWrapper.cs
- TextRunCacheImp.cs
- SecurityCriticalDataForSet.cs
- EditorZoneBase.cs
- UserControlCodeDomTreeGenerator.cs
- SafeHandle.cs
- TableDesigner.cs
- TouchEventArgs.cs
- LostFocusEventManager.cs
- CorrelationManager.cs
- NetworkStream.cs
- StickyNoteAnnotations.cs
- Form.cs
- Errors.cs
- CustomLineCap.cs
- ObjectViewListener.cs
- PersonalizationProvider.cs
- WpfPayload.cs
- CngKey.cs
- BaseComponentEditor.cs
- DomNameTable.cs
- NameScopePropertyAttribute.cs
- SQLConvert.cs
- ReturnEventArgs.cs
- AnnotationResourceChangedEventArgs.cs
- DefaultAsyncDataDispatcher.cs
- StaticSiteMapProvider.cs
- TraceXPathNavigator.cs
- CodeCompileUnit.cs
- XamlPoint3DCollectionSerializer.cs
- ControlPager.cs
- TableDetailsRow.cs
- StringKeyFrameCollection.cs
- FixedDocumentPaginator.cs
- HttpRequestCacheValidator.cs
- LinkedResourceCollection.cs
- ResetableIterator.cs
- XmlSchemas.cs
- ThreadStaticAttribute.cs
- StringUtil.cs
- IntPtr.cs
- MsmqIntegrationBindingElement.cs
- SchemaImporterExtensionsSection.cs
- ButtonChrome.cs
- FullTextLine.cs
- DataPagerFieldCommandEventArgs.cs
- GroupBoxAutomationPeer.cs
- IPPacketInformation.cs
- ellipse.cs
- ErrorFormatter.cs
- ListView.cs
- CharAnimationBase.cs
- SchemaNamespaceManager.cs
- SystemNetworkInterface.cs
- ResourceExpressionEditorSheet.cs
- Expressions.cs
- Buffer.cs
- SelectionRangeConverter.cs
- WindowsListBox.cs
- EmbossBitmapEffect.cs
- AdornerPresentationContext.cs
- PromptStyle.cs
- OpenTypeCommon.cs
- TreeNodeBindingCollection.cs
- XslUrlEditor.cs
- DetailsViewRow.cs
- XmlReaderDelegator.cs
- PagerSettings.cs
- XmlSchemaGroupRef.cs
- ErrorHandlerModule.cs
- QuerySafeNavigator.cs
- XslTransform.cs
- Latin1Encoding.cs
- SafeHandle.cs
- XsltFunctions.cs
- DbParameterCollectionHelper.cs
- TryCatch.cs
- MergeFailedEvent.cs
- SourceLocation.cs