Exemplo n.º 1
0
        public static PropagationPaths Build(VisualElement elem, EventBase evt)
        {
            PropagationPaths paths = s_Pool.Get();
            var eventCategory      = evt.eventCategory;

            // Skip element if it has no event callbacks, default action, or default action at target
            if (elem.HasEventCallbacksOrDefaultActions(eventCategory))
            {
                paths.targetElements.Add(elem);
            }

            // Go through the entire hierarchy. Don't bother checking elem.HasParentEventCallbacks because
            // 1. It too goes through the entire parent hierarchy, and
            // 2. It would require dirtying the parent categories when we set isCompositeRoot, so more overhead
            for (var ve = elem.nextParentWithEventCallback; ve != null; ve = ve.nextParentWithEventCallback)
            {
                if (ve.isCompositeRoot && !evt.ignoreCompositeRoots)
                {
                    // Callback for elem must be called at the Target phase. Skip if no callback.
                    if (ve.HasEventCallbacksOrDefaultActions(eventCategory))
                    {
                        paths.targetElements.Add(ve);
                    }
                }
                else if (ve.HasEventCallbacks(eventCategory))
                {
                    if (evt.tricklesDown && ve.HasTrickleDownHandlers())
                    {
                        paths.trickleDownPath.Add(ve);
                    }
                    if (evt.bubbles && ve.HasBubbleUpHandlers())
                    {
                        paths.bubbleUpPath.Add(ve);
                    }
                }
            }
            return(paths);
        }
Exemplo n.º 2
0
        private void UpdateSubTree(VisualElement ve, bool isDisplayed, List <KeyValuePair <Rect, VisualElement> > changeEvents)
        {
            Rect yogaLayoutRect = new Rect(ve.yogaNode.LayoutX, ve.yogaNode.LayoutY, ve.yogaNode.LayoutWidth, ve.yogaNode.LayoutHeight);

            // we encode right/bottom into width/height
            Rect rawPadding = new Rect(ve.yogaNode.LayoutPaddingLeft, ve.yogaNode.LayoutPaddingLeft, ve.yogaNode.LayoutPaddingRight, ve.yogaNode.LayoutPaddingBottom);

            // This is not the "real" padding rect: it may differ in size and position because the borders are ignored.
            // Alone, it cannot be used to identify padding size changes, because the bottom and right values depend on the
            // layout rect width/height. A change in layout rect width/height with a corresponding variation in
            // right/bottom values may yield the same pseudoPaddingRect. Fortunately, the layout rect size and padding rect
            // size change trigger the same code path which explains why we haven't seen any issue with this so far.
            Rect yogaPseudoPaddingRect = new Rect(
                rawPadding.x,
                rawPadding.y,
                yogaLayoutRect.width - (rawPadding.x + rawPadding.width),
                yogaLayoutRect.height - (rawPadding.y + rawPadding.height));
            Rect lastLayoutRect        = ve.lastLayout;
            Rect lastPseudoPaddingRect = ve.lastPseudoPadding;
            bool wasHierarchyDisplayed = ve.isHierarchyDisplayed;

            VersionChangeType changeType = 0;
            // Changing the layout/padding size should trigger the following version changes:
            // - Size:    to update the clipping rect, when required
            // - Repaint: to update the geometry inside the new rect
            bool layoutSizeChanged        = lastLayoutRect.size != yogaLayoutRect.size;
            bool pseudoPaddingSizeChanged = lastPseudoPaddingRect.size != yogaPseudoPaddingRect.size;

            if (layoutSizeChanged || pseudoPaddingSizeChanged)
            {
                changeType |= VersionChangeType.Size | VersionChangeType.Repaint;
            }

            // Changing the layout/padding position should trigger the following version change:
            // - Transform: to draw the element and content at the right position
            bool layoutPositionChanged  = yogaLayoutRect.position != lastLayoutRect.position;
            bool paddingPositionChanged = yogaPseudoPaddingRect.position != lastPseudoPaddingRect.position;

            if (layoutPositionChanged || paddingPositionChanged)
            {
                changeType |= VersionChangeType.Transform;
            }

            isDisplayed            &= ve.resolvedStyle.display != DisplayStyle.None;
            ve.isHierarchyDisplayed = isDisplayed;

            if (changeType != 0)
            {
                ve.IncrementVersion(changeType);
            }

            ve.lastLayout        = yogaLayoutRect;
            ve.lastPseudoPadding = yogaPseudoPaddingRect;

            // ignore clean sub trees
            bool hasNewLayout = ve.yogaNode.HasNewLayout;

            if (hasNewLayout)
            {
                var childCount = ve.hierarchy.childCount;
                for (int i = 0; i < childCount; ++i)
                {
                    var child = ve.hierarchy[i];

                    if (child.yogaNode.HasNewLayout)
                    {
                        UpdateSubTree(child, isDisplayed, changeEvents);
                    }
                }
            }

            // Only send GeometryChanged events when the layout changes
            // (padding changes don't affect the element's outer geometry).
            if ((layoutSizeChanged || layoutPositionChanged) && ve.HasEventCallbacksOrDefaultActions(GeometryChangedEvent.EventCategory))
            {
                changeEvents.Add(new KeyValuePair <Rect, VisualElement>(lastLayoutRect, ve));
            }

            if (hasNewLayout)
            {
                ve.yogaNode.MarkLayoutSeen();
            }
        }