private void Precompute() { if (VisualFlags.HasFlag(VisualFlags.BBoxDirty)) { Rect rect; PrecomputeRecursive(out rect); } }
protected virtual void PrecomputeRecursive(out Rect bboxSubgraph) { if (VisualFlags.HasFlag(VisualFlags.BBoxDirty)) { PrecomputeContent(); foreach (var child in VisualChildren) { Rect rect; child.PrecomputeRecursive(out rect); _bboxSubgraph = Rect.Union(_bboxSubgraph, rect); } VisualFlags &= ~VisualFlags.BBoxDirty; } bboxSubgraph = _bboxSubgraph; }
/// <summary> /// Walks up the Visual tree setting or clearing the given flags. Unlike /// PropagateFlags this does not terminate when it reaches node with /// the flags already set. It always walks all the way to the root. /// </summary> internal static void SetFlagsToRoot(DependencyObject element, bool value, VisualFlags flags) { Visual visual; Visual3D visual3D; AsVisualInternal(element, out visual, out visual3D); if (visual != null) { visual.SetFlagsToRoot(value, flags); } else if (visual3D != null) { visual3D.SetFlagsToRoot(value, flags); } }
//----------------------------------------------------- // // Constructors // //----------------------------------------------------- //------------------------------------------------------ // // Public Methods // //----------------------------------------------------- //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ //----------------------------------------------------- // // Public Events // //------------------------------------------------------ //----------------------------------------------------- // // Internal Methods // //----------------------------------------------------- #region Internal Methods /// <summary> /// This walks up the Visual tree setting the given flags starting at the /// given element. /// </summary> internal static void PropagateFlags( DependencyObject element, VisualFlags flags, VisualProxyFlags proxyFlags) { Visual visual; Visual3D visual3D; AsVisualInternal(element, out visual, out visual3D); if (visual != null) { Visual.PropagateFlags(visual, flags, proxyFlags); } else { Visual3D.PropagateFlags(visual3D, flags, proxyFlags); } }
//------------------------------------------------------ // // Constructors // //------------------------------------------------------ //------------------------------------------------------ // // Public Methods // //------------------------------------------------------ //------------------------------------------------------ // // Public Properties // //------------------------------------------------------ //------------------------------------------------------ // // Public Events // //------------------------------------------------------ //------------------------------------------------------ // // Internal Methods // //------------------------------------------------------ #region Internal Methods /// <summary> /// This walks up the Visual tree setting the given flags starting at the /// given element. /// </summary> internal static void PropagateFlags( DependencyObject element, VisualFlags flags, VisualProxyFlags proxyFlags) { Visual visual; Visual3D visual3D; AsVisualInternal(element, out visual, out visual3D); if (visual != null) { Visual.PropagateFlags(visual, flags, proxyFlags); } else { Visual3D.PropagateFlags(visual3D, flags, proxyFlags); } }
/// <summary> /// Walks up the Visual tree setting or clearing the given flags. Unlike /// PropagateFlags this does not terminate when it reaches node with /// the flags already set. It always walks all the way to the root. /// </summary> internal void SetFlagsToRoot(bool value, VisualFlags flag) { Visual3D current = this; do { current.SetFlags(value, flag); if (current._3DParent == null) { VisualTreeUtils.SetFlagsToRoot(InternalVisualParent, value, flag); return; } current = current._3DParent; } while (current != null); }
/// <summary> /// Propagates the flags up to the root. /// </summary> /// <remarks> /// The walk stops on a node with all of the required flags set. /// </remarks> internal static void PropagateFlags( Visual e, VisualFlags flags, VisualProxyFlags proxyFlags) { while ((e != null) && (!e.CheckFlagsAnd(flags) || !e.CheckFlagsOnAllChannels(proxyFlags))) { if (e.CheckFlagsOr(VisualFlags.ShouldPostRender)) { MediaContext mctx = MediaContext.From(e.Dispatcher); if (mctx.Channel != null) { mctx.PostRender(); } } else if (e.CheckFlagsAnd(VisualFlags.NodeIsCyclicBrushRoot)) { // // For visuals that are root nodes in visual brushes we // need to fire OnChanged on the owning brushes. // Dictionary<ICyclicBrush, int> cyclicBrushToChannelsMap = CyclicBrushToChannelsMapField.GetValue(e); Debug.Assert(cyclicBrushToChannelsMap != null, "Visual brush roots need to have the visual brush to channels map!"); // // Iterate over the visual brushes and fire the OnChanged event. // foreach (ICyclicBrush cyclicBrush in cyclicBrushToChannelsMap.Keys) { cyclicBrush.FireOnChanged(); } } e.SetFlags(true, flags); e.SetFlagsOnAllChannels(true, proxyFlags); if (e._parent == null) { // Stop propagating. We are at the root of the 2D subtree. return; } Visual parentAsVisual = e._parent as Visual; if (parentAsVisual == null) { // if the parent is not null (saw this with earlier null check) and is not a Visual // it must be a Visual3D - continue the propagation Visual3D.PropagateFlags((Visual3D)e._parent, flags, proxyFlags); return; } e = parentAsVisual; } }
/// <summary> /// Check all the children for a bit. /// </summary> private static bool DoAnyChildrenHaveABitSet( Visual pe, VisualFlags flag) { int count = pe.VisualChildrenCount; for (int i = 0; i < count; i++) { Visual v = pe.GetVisualChild(i); if (v != null && v.CheckFlagsAnd(flag)) { return true; } } return false; }
/// <summary> /// Clean a bit in a Visual node and in all its direct ancestors; /// unless the ancestor also has /// </summary> /// <param name="e">The Visual Element</param> /// <param name="treeFlag">The Flag that marks a sub tree to search</param> /// <param name="nodeFlag">The Flag that marks the node to search for.</param> internal static void ClearTreeBits( DependencyObject e, VisualFlags treeFlag, VisualFlags nodeFlag) { Visual eAsVisual; Visual3D eAsVisual3D; // This bit might not be set, but checking costs as much as setting // So it is faster to just clear it everytime. if (e != null) { eAsVisual = e as Visual; if (eAsVisual != null) { eAsVisual.SetFlags(false, nodeFlag); } else { ((Visual3D)e).SetFlags(false, nodeFlag); } } while (e != null) { eAsVisual = e as Visual; if (eAsVisual != null) { if(eAsVisual.CheckFlagsAnd(nodeFlag)) { return; // Done; if a parent also has the Node bit set. } if(DoAnyChildrenHaveABitSet(eAsVisual, treeFlag)) { return; // Done; if a other subtrees are set. } eAsVisual.SetFlags(false, treeFlag); } else { eAsVisual3D = e as Visual3D; if(eAsVisual3D.CheckFlagsAnd(nodeFlag)) { return; // Done; if a parent also has the Node bit set. } if(Visual3D.DoAnyChildrenHaveABitSet(eAsVisual3D, treeFlag)) { return; // Done; if a other subtrees are set. } eAsVisual3D.SetFlags(false, treeFlag); } e = VisualTreeHelper.GetParent(e); } }
/// <summary> /// Set a bit in a Visual node and in all its direct ancestors. /// </summary> /// <param name="e">The Visual Element</param> /// <param name="treeFlag">The Flag that marks a sub tree to search</param> /// <param name="nodeFlag">The Flag that marks the node to search for.</param> internal static void SetTreeBits( DependencyObject e, VisualFlags treeFlag, VisualFlags nodeFlag) { Visual eAsVisual; Visual3D eAsVisual3D; if (e != null) { eAsVisual = e as Visual; if (eAsVisual != null) { eAsVisual.SetFlags(true, nodeFlag); } else { ((Visual3D)e).SetFlags(true, nodeFlag); } } while (null!=e) { eAsVisual = e as Visual; if (eAsVisual != null) { // if the bit is already set, then we're done. if(eAsVisual.CheckFlagsAnd(treeFlag)) return; eAsVisual.SetFlags(true, treeFlag); } else { eAsVisual3D = e as Visual3D; // if the bit is already set, then we're done. if(eAsVisual3D.CheckFlagsAnd(treeFlag)) return; eAsVisual3D.SetFlags(true, treeFlag); } e = VisualTreeHelper.GetParent(e); } }
private void SetUIFlags(VisualFlags flags) { VisualFlags |= flags; }
/// <summary> /// Check all the children for a bit. /// </summary> internal static bool DoAnyChildrenHaveABitSet(Visual3D pe, VisualFlags flag) { int count = pe.InternalVisual2DOr3DChildrenCount; for (int i = 0; i < count; i++) { DependencyObject child = pe.InternalGet2DOr3DVisualChild(i); Visual v = null; Visual3D v3D = null; VisualTreeUtils.AsNonNullVisual(child, out v, out v3D); if (v != null && v.CheckFlagsAnd(flag)) { return true; } else if (v3D != null && v3D.CheckFlagsAnd(flag)) { return true; } } return false; }
/// <summary> /// CheckFlagsAnd returns true if all flags in the bitmask flags are set on the node. /// </summary> /// <remarks>If there aren't any bits set on the specified flags the method /// returns true</remarks> internal bool CheckFlagsAnd(VisualFlags flags) { return (_flags & flags) == flags; }
/// <summary> /// Finds the first ancestor of the given element which has the given /// flags set. /// </summary> internal DependencyObject FindFirstAncestorWithFlagsAnd(VisualFlags flag) { Visual3D current = this; do { if (current.CheckFlagsAnd(flag)) { // The other Visual crossed through this Visual's parent chain. Hence this is our // common ancestor. return current; } if (current._3DParent == null) { return VisualTreeUtils.FindFirstAncestorWithFlagsAnd(InternalVisualParent, flag); } current = current._3DParent; } while (current != null); return null; }
/// <summary> /// Finds the first ancestor of the given element which has the given /// flags set. /// </summary> internal static DependencyObject FindFirstAncestorWithFlagsAnd(DependencyObject element, VisualFlags flags) { Visual visual; Visual3D visual3D; AsVisualInternal(element, out visual, out visual3D); if (visual != null) { return visual.FindFirstAncestorWithFlagsAnd(flags); } else if (visual3D != null) { return visual3D.FindFirstAncestorWithFlagsAnd(flags); } Debug.Assert(element == null); return null; }
private void ClearFlags(VisualFlags flags) { VisualFlags &= ~flags; }
/// <summary> /// Finds the first ancestor of the given element which has the given /// flags set. /// </summary> internal static DependencyObject FindFirstAncestorWithFlagsAnd(DependencyObject element, VisualFlags flags) { Visual visual; Visual3D visual3D; AsVisualInternal(element, out visual, out visual3D); if (visual != null) { return(visual.FindFirstAncestorWithFlagsAnd(flags)); } else if (visual3D != null) { return(visual3D.FindFirstAncestorWithFlagsAnd(flags)); } Debug.Assert(element == null); return(null); }
/// <summary> /// SetFlags is used to set or unset one or multiple node flags on the node. /// </summary> internal void SetFlags(bool value, VisualFlags Flags) { _flags = value ? (_flags | Flags) : (_flags & (~Flags)); }
/// <summary> /// Checks if any of the specified flags is set on the node. /// </summary> /// <remarks>If there aren't any bits set on the specified flags the method /// returns true</remarks> internal bool CheckFlagsOr(VisualFlags flags) { return (flags == 0) || ((_flags & flags) > 0); }
/// <summary> /// Walks up the Visual tree setting or clearing the given flags. Unlike /// PropagateFlags this does not terminate when it reaches node with /// the flags already set. It always walks all the way to the root. /// </summary> internal void SetFlagsToRoot(bool value, VisualFlags flag) { Visual current = this; do { current.SetFlags(value, flag); Visual currentParent = current._parent as Visual; // if the cast to currentParent failed and yet current._parent is not null then // we have a 3D element. Call SetFlagsToRoot on it instead. if (current._parent != null && currentParent == null) { ((Visual3D)current._parent).SetFlagsToRoot(value, flag); return; } current = currentParent; } while (current != null); }
/// <summary> /// Propagates the flags up to the root. /// </summary> /// <remarks> /// The walk stops on a node with all of the required flags set. /// </remarks> internal static void PropagateFlags( Visual3D e, VisualFlags flags, VisualProxyFlags proxyFlags) { while ((e != null) && (!e.CheckFlagsAnd(flags) || !e.CheckFlagsOnAllChannels(proxyFlags))) { // These asserts are mostly for documentation when diffing the 2D/3D // implementations. Debug.Assert(!e.CheckFlagsOr(VisualFlags.ShouldPostRender), "Visual3Ds should never be the root of a tree."); Debug.Assert(!e.CheckFlagsOr(VisualFlags.NodeIsCyclicBrushRoot), "Visual3Ds should never be the root of an ICyclicBrush."); e.SetFlags(true, flags); e.SetFlagsOnAllChannels(true, proxyFlags); // If our 3D parent is null call back into VisualTreeUtils to potentially // continue the walk in 2D. if (e._3DParent == null) { Viewport3DVisual viewport = e.InternalVisualParent as Viewport3DVisual; Debug.Assert((viewport == null) == (e.InternalVisualParent == null), "Viewport3DVisual is the only supported 2D parent of a 3D visual."); if(viewport != null) { // We must notify the 2D visual that its contents have changed. // This will cause the 2D visual to set it's content dirty flag // and continue the propagation of IsDirtyForRender/Precompute. viewport.Visual3DTreeChanged(); // continue propagating flags up the 2D world Visual.PropagateFlags(viewport, flags, proxyFlags); } // Stop propagating. We are at the root of the 3D subtree. return; } e = e._3DParent; } }
/// <summary> /// Finds the first ancestor of the given element which has the given /// flags set. /// </summary> internal DependencyObject FindFirstAncestorWithFlagsAnd(VisualFlags flag) { Visual current = this; do { if (current.CheckFlagsAnd(flag)) { // The other Visual crossed through this Visual's parent chain. Hence this is our // common ancestor. return current; } DependencyObject parent = current._parent; // first attempt to see if parent is a Visual, in which case we continue the loop. // Otherwise see if it's a Visual3D, and call the similar method on it. current = parent as Visual; if (current == null) { Visual3D parentAsVisual3D = parent as Visual3D; if (parentAsVisual3D != null) { return parentAsVisual3D.FindFirstAncestorWithFlagsAnd(flag); } } } while (current != null); return null; }