public static DependencyObject GetLogicalParent(DependencyObject element, DeferredElementTreeState treeState)
        {
            DependencyObject parent = null;
            
            if(treeState != null && treeState._oldLogicalParents.ContainsKey(element))
            {
                parent = treeState._oldLogicalParents[element];
            }
            else
            {
                UIElement e = element as UIElement;
                if(e != null)
                {
                    parent = e.GetUIParentCore();  // Overriden by FrameworkElement.
                }

                ContentElement ce = element as ContentElement;
                if(ce != null)
                {
                    parent = ce.GetUIParentCore(); // Overriden by FrameworkContentElement.
                }
            }

            return parent;
        }
        public static DependencyObject GetLogicalParent(DependencyObject element, DeferredElementTreeState treeState)
        {
            DependencyObject parent = null;

            if (treeState != null && treeState._oldLogicalParents.ContainsKey(element))
            {
                parent = treeState._oldLogicalParents[element];
            }
            else
            {
                UIElement e = element as UIElement;
                if (e != null)
                {
                    parent = e.GetUIParentCore();  // Overriden by FrameworkElement.
                }

                ContentElement ce = element as ContentElement;
                if (ce != null)
                {
                    parent = ce.GetUIParentCore(); // Overriden by FrameworkContentElement.
                }
            }

            return(parent);
        }
        public static DependencyObject GetCoreParent(DependencyObject element, DeferredElementTreeState treeState)
        {
            DependencyObject parent = null;

            if (treeState != null && treeState._oldCoreParents.ContainsKey(element))
            {
                parent = treeState._oldCoreParents[element];
            }
            else
            {
                Visual v = element as Visual;
                if (v != null)
                {
                    parent = VisualTreeHelper.GetParent(v);
                }
                else
                {
                    ContentElement ce = element as ContentElement;
                    if (ce != null)
                    {
                        parent = ContentOperations.GetParent(ce);
                    }
                    else
                    {
                        Visual3D v3D = element as Visual3D;
                        if (v3D != null)
                        {
                            parent = VisualTreeHelper.GetParent(v3D);
                        }
                    }
                }
            }

            return(parent);
        }
        internal void OnOriginValueChanged(DependencyObject oldOrigin,
            DependencyObject newOrigin,
            IList<DependencyObject> otherOrigins,
            ref DeferredElementTreeState oldTreeState,
            Action<DependencyObject, bool> originChangedAction)
        {
            DeferredElementTreeState treeStateLocalCopy = oldTreeState;
            oldTreeState = null;

            // Determine if one needs to raise notifications of elements
            // affected by the origin change irrespective of other origins
            bool setOriginCacheFlag = ((originChangedAction != null) &&
                                       (FlagOldOriginCache != CoreFlags.None) &&
                                       (FlagNewOriginCache != CoreFlags.None));

            // Step #1
            // Update the cache flags for all elements in the ancestry 
            // of the element that got turned off and record the changed nodes
            if (oldOrigin != null)
            {
                SetCacheFlagInAncestry(oldOrigin, false, treeStateLocalCopy, true, setOriginCacheFlag);
            }

            // Step #2
            // Update the cache flags for all elements in the ancestry 
            // of the element that got turned on and record the changed nodes
            if (newOrigin != null)
            {
                SetCacheFlagInAncestry(newOrigin, true, null, true, setOriginCacheFlag);
            }
            int otherCount = (otherOrigins != null) ? otherOrigins.Count : 0;
            for (int i = 0; i < otherCount; i++)
            {
                // setOriginCacheFlag is false, because these flags should not be affected by other origins
                SetCacheFlagInAncestry(otherOrigins[i], true, null, false, /*setOriginCacheFlag*/ false);
            }

            // Step #3
            // Fire value changed on elements in the ancestry of the element that got turned off.
            if (oldOrigin != null)
            {
                FirePropertyChangeInAncestry(oldOrigin, true /* oldValue */, treeStateLocalCopy, originChangedAction);
            }

            // Step #4
            // Fire value changed on elements in the ancestry of the element that got turned on.
            if (newOrigin != null)
            {
                FirePropertyChangeInAncestry(newOrigin, false /* oldValue */, null, originChangedAction);
            }

            if (oldTreeState == null && treeStateLocalCopy != null)
            {
                // Now that we have applied the old tree state, throw it away.
                treeStateLocalCopy.Clear();
                oldTreeState = treeStateLocalCopy;
            }
        }
        public static DependencyObject GetInputElementParent(DependencyObject element, DeferredElementTreeState treeState)
        {
            DependencyObject parent = element;
            
            while (true)
            {
                parent = GetCoreParent(parent, treeState);

                if (parent == null || InputElement.IsValid(parent))
                {
                    break;
                }
            }

            return parent;
        }
        public static DependencyObject GetCoreParent(DependencyObject element, DeferredElementTreeState treeState)
        {
            DependencyObject parent = null;
            
            if(treeState != null && treeState._oldCoreParents.ContainsKey(element))
            {
                parent = treeState._oldCoreParents[element];
            }
            else
            {
                Visual v = element as Visual;
                if(v != null)
                {
                    parent = VisualTreeHelper.GetParent(v);
                }
                else
                {
                    ContentElement ce = element as ContentElement;
                    if(ce != null)
                    {
                        parent = ContentOperations.GetParent(ce);
                    }
                    else
                    {
                        Visual3D v3D = element as Visual3D;
                        if (v3D != null)
                        {
                            parent = VisualTreeHelper.GetParent(v3D);
                        }
                    }

                }
            }

            return parent;
        }
        private void SetCacheFlagInAncestry(DependencyObject element,
            bool newValue,
            DeferredElementTreeState treeState,
            bool shortCircuit,
            bool setOriginCacheFlag)
        {
            UIElement uie;
            ContentElement ce;
            UIElement3D uie3D;
            CastElement(element, out uie, out ce, out uie3D);

            bool isFlagSet = IsFlagSet(uie, ce, uie3D, FlagCache);
            bool isFlagOriginCacheSet = (setOriginCacheFlag ? IsFlagSet(uie, ce, uie3D, (newValue ? FlagNewOriginCache : FlagOldOriginCache)) : false);

            // If the cache flag value is undergoing change, record it and
            // propagate the change to the ancestors.
            if ((newValue != isFlagSet) ||
                (setOriginCacheFlag && !isFlagOriginCacheSet) ||
                !shortCircuit)
            {
                if (newValue != isFlagSet)
                {
                    SetFlag(uie, ce, uie3D, FlagCache, newValue);

                    // NOTE: we toggle the changed flag instead of setting it so that that way common 
                    // ancestors show resultant unchanged and do not receive any change notification.
                    SetFlag(uie, ce, uie3D, FlagChanged, !IsFlagSet(uie, ce, uie3D, FlagChanged));
                }

                if (setOriginCacheFlag && !isFlagOriginCacheSet)
                {
                    SetFlag(uie, ce, uie3D, (newValue ? FlagNewOriginCache : FlagOldOriginCache), true);
                }

                // Check for block reverse inheritance flag, elements like popup want to set this.
                if (BlockReverseInheritance(uie, ce, uie3D))
                {
                    return;
                }

                // Propagate the flag up the visual and logical trees.  Note our
                // minimal optimization check to avoid walking both the core
                // and logical parents if they are the same.
                {
                    DependencyObject coreParent = DeferredElementTreeState.GetInputElementParent(element, treeState);
                    DependencyObject logicalParent = DeferredElementTreeState.GetLogicalParent(element, treeState);
                    
                    if (coreParent != null)
                    {
                        SetCacheFlagInAncestry(coreParent, newValue, treeState, shortCircuit, setOriginCacheFlag);
                    }                
                    if (logicalParent != null && logicalParent != coreParent)
                    {
                        SetCacheFlagInAncestry(logicalParent, newValue, treeState, shortCircuit, setOriginCacheFlag);
                    }
                }
            }
        }
 internal void OnOriginValueChanged(DependencyObject oldOrigin, DependencyObject newOrigin, ref DeferredElementTreeState oldTreeState)
 {
     OnOriginValueChanged(oldOrigin, newOrigin, null, ref oldTreeState, null);
 }
        private void FirePropertyChangeInAncestry(DependencyObject element,
            bool oldValue,
            DeferredElementTreeState treeState,
            Action<DependencyObject, bool> originChangedAction)
        {
            UIElement uie;
            ContentElement ce;
            UIElement3D uie3D;
            CastElement(element, out uie, out ce, out uie3D);

            bool flagChanged = IsFlagSet(uie, ce, uie3D, FlagChanged);
            bool isFlagOldOriginCacheSet = ((FlagOldOriginCache == CoreFlags.None) ? false : IsFlagSet(uie, ce, uie3D, FlagOldOriginCache));
            bool isFlagNewOriginCacheSet = ((FlagNewOriginCache == CoreFlags.None) ? false : IsFlagSet(uie, ce, uie3D, FlagNewOriginCache));

            if (flagChanged || isFlagOldOriginCacheSet || isFlagNewOriginCacheSet)
            {
                if (flagChanged)
                {
                    // if FlagChanged bit is set, then the value has changed effectively
                    // after considering all the origins. Hence change the property value
                    // and fire notifications.
                    SetFlag(uie, ce, uie3D, FlagChanged, false);

                    if (oldValue)
                    {
                        element.ClearValue(FlagKey);
                    }
                    else
                    {
                        element.SetValue(FlagKey, true);
                    }

                    FireNotifications(uie, ce, uie3D, oldValue);
                }

                if (isFlagOldOriginCacheSet || isFlagNewOriginCacheSet)
                {
                    SetFlag(uie, ce, uie3D, FlagOldOriginCache, false);
                    SetFlag(uie, ce, uie3D, FlagNewOriginCache, false);
                    if (isFlagOldOriginCacheSet != isFlagNewOriginCacheSet)
                    {
                        // if either FlagOldOriginCache or FlagNewOriginCache
                        // are set, then the origin change has affected this node
                        // and hence originChangedAction should be executed.
                        Debug.Assert(originChangedAction != null);
                        originChangedAction(element, oldValue);
                    }
                }

                // Check for block reverse inheritance flag, elements like popup want to set this.
                if (BlockReverseInheritance(uie, ce, uie3D))
                {
                    return;
                }

                // Call FirePropertyChange up the visual and logical trees.
                // Note our minimal optimization check to avoid walking both
                // the core and logical parents if they are the same.
                {
                    DependencyObject coreParent = DeferredElementTreeState.GetInputElementParent(element, treeState);
                    DependencyObject logicalParent = DeferredElementTreeState.GetLogicalParent(element, treeState);

                    if (coreParent != null)
                    {
                        FirePropertyChangeInAncestry(coreParent, oldValue, treeState, originChangedAction);
                    }
                    if (logicalParent != null && logicalParent != coreParent)
                    {
                        FirePropertyChangeInAncestry(logicalParent, oldValue, treeState, originChangedAction);
                    }
                }
            }
        }
        public static DependencyObject GetInputElementParent(DependencyObject element, DeferredElementTreeState treeState)
        {
            DependencyObject parent = element;

            while (true)
            {
                parent = GetCoreParent(parent, treeState);

                if (parent == null || InputElement.IsValid(parent))
                {
                    break;
                }
            }

            return(parent);
        }
        private void ReevaluateDirectlyOverAsync(DependencyObject element, DependencyObject oldParent, bool isCoreParent)
        {
            if (element != null)
            {
                if (_directlyOverTreeState == null)
                {
                    _directlyOverTreeState = new DeferredElementTreeState();
                }

                if (isCoreParent)
                {
                    _directlyOverTreeState.SetCoreParent(element, oldParent);
                }
                else
                {
                    _directlyOverTreeState.SetLogicalParent(element, oldParent);
                }
            }

            if (_reevaluateOver == null)
            {
                _reevaluateOver = Dispatcher.BeginInvoke(DispatcherPriority.Input,
                    (DispatcherOperationCallback)delegate(object args)
                    {
                        _reevaluateOver = null;
                        OnHitTestInvalidatedAsync(this, EventArgs.Empty);
                        return null;
                    }, null);
            }
        }
        private void ReevaluateCapturedWithinAsync(DependencyObject element, DependencyObject oldParent, bool isCoreParent)
        {
            if (element != null)
            {
                if (_capturedWithinTreeState == null)
                {
                    _capturedWithinTreeState = new DeferredElementTreeState();
                }

                if (isCoreParent)
                {
                    _capturedWithinTreeState.SetCoreParent(element, oldParent);
                }
                else
                {
                    _capturedWithinTreeState.SetLogicalParent(element, oldParent);
                }
            }

            if (_reevaluateCapture == null)
            {
                _reevaluateCapture = Dispatcher.BeginInvoke(DispatcherPriority.Input,
                    (DispatcherOperationCallback)delegate(object args)
                    {
                        _reevaluateCapture = null;
                        OnReevaluateCapturedWithinAsync();
                        return null;
                    }, null);
            }
        }