Esempio n. 1
0
        protected void ArrangeChildOverride(View view, Rect frame)
        {
            view.Arranged = frame;
            view.LayoutSlotWithMarginsAndAlignments = frame;

            LayoutInformation.SetLayoutSlot(view, frame);
        }
Esempio n. 2
0
        public void Arrange(Rect finalRect)
        {
            if (!(this is FrameworkElement))
            {
                return;
            }

            if (Visibility == Visibility.Collapsed || finalRect == default)
            {
                LayoutInformation.SetLayoutSlot(this, finalRect);
                HideVisual();
                _isArrangeValid = true;
                return;
            }

            if (!_isArrangeValid || finalRect != LayoutSlot)
            {
                ShowVisual();

                // We must store the updated slot before natively arranging the element,
                // so the updated value can be read by indirect code that is being invoked on arrange.
                // For instance, the EffectiveViewPort computation reads that value to detect slot changes (cf. PropagateEffectiveViewportChange)
                LayoutInformation.SetLayoutSlot(this, finalRect);

                ArrangeCore(finalRect);
                _isArrangeValid = true;
            }
        }
Esempio n. 3
0
        public void Arrange(Rect finalRect)
        {
            if (!_isFrameworkElement)
            {
                return;
            }

            if (Visibility == Visibility.Collapsed
                // If the layout is clipped, and the arranged size is empty, we can skip arranging children
                // This scenario is particularly important for the Canvas which always sets its desired size
                // zero, even after measuring its children.
                || (finalRect == default && (this is not ICustomClippingElement clipElement || clipElement.AllowClippingToLayoutSlot)))
            {
                LayoutInformation.SetLayoutSlot(this, finalRect);
                HideVisual();
                ClearLayoutFlags(LayoutFlag.ArrangeDirty);
                return;
            }

            if (!IsArrangeDirty && finalRect == LayoutSlot)
            {
                return;                 // Calling Arrange would be a waste of CPU time here.
            }

            if (IsVisualTreeRoot)
            {
                ArrangeVisualTreeRoot(finalRect);
            }
            else
            {
                // If possible we avoid the try/finally which might be costly on some platforms
                DoArrange(finalRect);
            }
        }
        public void Arrange(Rect finalRect)
        {
            if (!(this is FrameworkElement))
            {
                return;
            }

            if (Visibility == Visibility.Collapsed
                // If the layout is clipped, and the arranged size is empty, we can skip arranging children
                // This scenario is particularly important for the Canvas which always sets its desired size
                // zero, even after measuring its children.
                || (finalRect == default && (this is ICustomClippingElement clipElement ? clipElement.AllowClippingToLayoutSlot : true)))
            {
                LayoutInformation.SetLayoutSlot(this, finalRect);
                HideVisual();
                _isArrangeValid = true;
                return;
            }

            if (_isArrangeValid && finalRect == LayoutSlot)
            {
                return;
            }

            if (IsVisualTreeRoot)
            {
                ArrangeVisualTreeRoot(finalRect);
            }
            else
            {
                // If possible we avoid the try/finally which might be costly on some platforms
                DoArrange(finalRect);
            }
        }
Esempio n. 5
0
        public override void LayoutSubviews()
        {
            try
            {
                try
                {
                    _inLayoutSubviews = true;

                    if (IsMeasureDirty)
                    {
                        // Add back the Margin (which is normally 'outside' the view's bounds) - the layouter will subtract it again
                        var availableSizeWithMargins = Bounds.Size.Add(Margin);
                        XamlMeasure(availableSizeWithMargins);
                    }

                    //if (IsArrangeDirty) // commented until the MEASURE_DIRTY_PATH is properly implemented for iOS
                    {
                        ClearLayoutFlags(LayoutFlag.ArrangeDirty);

                        OnBeforeArrange();

                        Rect finalRect;
                        var  parent = Superview;
                        if (parent is UIElement ||
                            parent is ISetLayoutSlots
                            // In the case of ListViewItem inside native list, its parent's parent is ListViewBaseInternalContainer
                            || parent?.Superview is ISetLayoutSlots
                            )
                        {
                            finalRect = LayoutSlotWithMarginsAndAlignments;
                        }
                        else
                        {
                            // Here the "arrange" is coming from a native element,
                            // so we convert those measurements to logical ones.
                            finalRect = RectFromUIRect(Frame);

                            // We also need to set the LayoutSlot as it was not by the parent.
                            // Note: This is only an approximation of the LayoutSlot as margin and alignment might already been applied at this point.
                            LayoutInformation.SetLayoutSlot(this, finalRect);
                            LayoutSlotWithMarginsAndAlignments = finalRect;
                        }

                        _layouter.Arrange(finalRect);

                        OnAfterArrange();
                    }
                }
                finally
                {
                    _inLayoutSubviews = false;
                }
            }
            catch (Exception e)
            {
                this.Log().Error($"Layout failed in {GetType()}", e);
            }
        }
Esempio n. 6
0
        public override void LayoutSubviews()
        {
            if (Visibility == Visibility.Collapsed)
            {
                // //Don't layout collapsed views
                return;
            }

            try
            {
                try
                {
                    _inLayoutSubviews = true;

                    if (IsMeasureDirty)
                    {
                        // Add back the Margin (which is normally 'outside' the view's bounds) - the layouter will subtract it again
                        XamlMeasure(Bounds.Size.Add(Margin));
                    }

                    OnBeforeArrange();

                    Rect finalRect;
                    var  parent = Superview;
                    if (parent is UIElement || parent is ISetLayoutSlots)
                    {
                        finalRect = LayoutSlotWithMarginsAndAlignments;
                    }
                    else
                    {
                        // Here the "arrange" is coming from a native element,
                        // so we convert those measurements to logical ones.
                        finalRect = RectFromUIRect(Frame);

                        // We also need to set the LayoutSlot as it was not by the parent.
                        // Note: This is only an approximation of the LayoutSlot as margin and alignment might already been applied at this point.
                        LayoutInformation.SetLayoutSlot(this, finalRect);
                        LayoutSlotWithMarginsAndAlignments = finalRect;
                    }

                    _layouter.Arrange(finalRect);

                    OnAfterArrange();
                }
                finally
                {
                    _inLayoutSubviews = false;
                    IsArrangeDirty    = false;
                }
            }
            catch (Exception e)
            {
                this.Log().Error($"Layout failed in {GetType()}", e);
            }
        }
Esempio n. 7
0
        private void DoArrange(Rect finalRect)
        {
            ShowVisual();

            // We must store the updated slot before natively arranging the element,
            // so the updated value can be read by indirect code that is being invoked on arrange.
            // For instance, the EffectiveViewPort computation reads that value to detect slot changes (cf. PropagateEffectiveViewportChange)
            LayoutInformation.SetLayoutSlot(this, finalRect);

            ArrangeCore(finalRect);
            _isArrangeValid = true;
        }
Esempio n. 8
0
        private void DoArrange(Rect finalRect)
        {
            var isFirstArrange = !IsLayoutFlagSet(LayoutFlag.FirstArrangeDone);

            var isDirty =
                isFirstArrange ||
                IsArrangeDirty ||
                finalRect != LayoutSlot;

            if (!isDirty && !IsArrangeDirtyPath)
            {
                return;                 // Nothing do to
            }

            var remainingTries = MaxLayoutIterations;

            while (--remainingTries > 0)
            {
                if (IsMeasureDirtyOrMeasureDirtyPath)
                {
                    DoMeasure(LastAvailableSize);
                }

                if (isDirty)
                {
                    ShowVisual();

                    // We must store the updated slot before natively arranging the element,
                    // so the updated value can be read by indirect code that is being invoked on arrange.
                    // For instance, the EffectiveViewPort computation reads that value to detect slot changes (cf. PropagateEffectiveViewportChange)
                    LayoutInformation.SetLayoutSlot(this, finalRect);

                    // We must reset the flag **BEFORE** doing the actual arrange, so the elements are able to re-invalidate themselves
                    ClearLayoutFlags(LayoutFlag.ArrangeDirty | LayoutFlag.ArrangeDirtyPath);

                    ArrangeCore(finalRect);

                    SetLayoutFlags(LayoutFlag.FirstArrangeDone);

                    break;
                }
                else if (IsArrangeDirtyPath)
                {
                    ClearLayoutFlags(LayoutFlag.ArrangeDirtyPath);

                    var children = GetChildren().GetEnumerator();

                    while (children.MoveNext())
                    {
                        var child = children.Current;

                        if (child is { IsArrangeDirtyOrArrangeDirtyPath : true })
Esempio n. 9
0
        private void DoArrange(Rect finalRect)
        {
            ShowVisual();

            // We must store the updated slot before natively arranging the element,
            // so the updated value can be read by indirect code that is being invoked on arrange.
            // For instance, the EffectiveViewPort computation reads that value to detect slot changes (cf. PropagateEffectiveViewportChange)
            LayoutInformation.SetLayoutSlot(this, finalRect);

            // We must reset the flag **BEFORE** doing the actual arrange, so the elements are able to re-invalidate themselves
            ClearLayoutFlags(LayoutFlag.ArrangeDirty);

            ArrangeCore(finalRect);
        }
Esempio n. 10
0
        public void When_UpdateLayout_Then_TreeNotMeasuredUsingCachedValue()
        {
            if (Window.Current.RootElement is Panel root)
            {
                var sut = new Grid
                {
                    HorizontalAlignment = HorizontalAlignment.Stretch,
                    VerticalAlignment   = VerticalAlignment.Stretch
                };

                var originalRootAvailableSize = LayoutInformation.GetAvailableSize(root);
                var originalRootDesiredSize   = LayoutInformation.GetDesiredSize(root);
                var originalRootLayoutSlot    = LayoutInformation.GetLayoutSlot(root);

                Size availableSize;
                Rect layoutSlot;
                try
                {
                    LayoutInformation.SetAvailableSize(root, default);
                    LayoutInformation.SetDesiredSize(root, default);
                    LayoutInformation.SetLayoutSlot(root, default);

                    root.Children.Add(sut);
                    sut.UpdateLayout();

                    availableSize = LayoutInformation.GetAvailableSize(sut);
                    layoutSlot    = LayoutInformation.GetLayoutSlot(sut);
                }
                finally
                {
                    LayoutInformation.SetAvailableSize(root, originalRootAvailableSize);
                    LayoutInformation.SetDesiredSize(root, originalRootDesiredSize);
                    LayoutInformation.SetLayoutSlot(root, originalRootLayoutSlot);

                    root.Children.Remove(sut);
                    try { root.UpdateLayout(); }
                    catch { }                     // Make sure to restore visual tree if test has failed!
                }

                Assert.AreNotEqual(default, availableSize);
Esempio n. 11
0
        public void Arrange(Rect finalRect)
        {
            if (!(this is FrameworkElement))
            {
                return;
            }

            if (Visibility == Visibility.Collapsed || finalRect == default)
            {
                LayoutInformation.SetLayoutSlot(this, finalRect);
                HideVisual();
                _isArrangeValid = true;
                return;
            }

            if (_isArrangeValid && finalRect == LayoutSlot)
            {
                return;
            }

            if (IsVisualTreeRoot)
            {
                try
                {
                    _isLayoutingVisualTreeRoot = true;
                    DoArrange(finalRect);
                }
                finally
                {
                    _isLayoutingVisualTreeRoot = false;
                }
            }
            else
            {
                // If possible we avoid the try/finally which might be costly on some platforms
                DoArrange(finalRect);
            }
        }
Esempio n. 12
0
        protected override void OnLayoutCore(bool changed, int left, int top, int right, int bottom)
        {
            try
            {
                base.OnLayoutCore(changed, left, top, right, bottom);

                Rect finalRect;
                if (TransientArrangeFinalRect is Rect tafr)
                {
                    // If the parent element is from managed code,
                    // we can recover the "Arrange" with double accuracy.
                    // We use that because the conversion to android's "int" is loosing too much precision.
                    finalRect = tafr;
                }
                else
                {
                    // Here the "arrange" is coming from a native element,
                    // so we convert those measurements to logical ones.
                    finalRect = new Rect(left, top, right - left, bottom - top).PhysicalToLogicalPixels();

                    // We also need to set the LayoutSlot as it was not set by the parent.
                    // Note: This is only an approximation of the LayoutSlot as margin and alignment might already been applied at this point.
                    LayoutInformation.SetLayoutSlot(this, finalRect);
                    LayoutSlotWithMarginsAndAlignments = finalRect;
                }

                if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
                {
                    this.Log().DebugFormat(
                        "[{0}/{1}] OnLayoutCore({2}, {3}, {4}, {5}) (parent: {5},{6})",
                        GetType(),
                        Name,
                        left, top, right, bottom,
                        MeasuredWidth,
                        MeasuredHeight
                        );
                }

                var previousSize = AssignedActualSize;
                AssignedActualSize = finalRect.Size;

                if (
                    // If the layout has changed, but the final size has not, this is just a translation.
                    // So unless there was a layout requested, we can skip arranging the children.
                    (changed && _lastLayoutSize != finalRect.Size)

                    // Even if nothing changed, but a layout was requested, arrange the children.
                    || IsLayoutRequested
                    )
                {
                    _lastLayoutSize = finalRect.Size;

                    OnBeforeArrange();

                    _layouter.Arrange(finalRect);

                    OnAfterArrange();
                }

                if (previousSize != finalRect.Size)
                {
                    SizeChanged?.Invoke(this, new SizeChangedEventArgs(this, previousSize, finalRect.Size));
                    _renderTransform?.UpdateSize(finalRect.Size);
                }
            }
            catch (Exception e)
            {
                Application.Current.RaiseRecoverableUnhandledExceptionOrLog(e, this);
            }
        }