protected void ArrangeChildOverride(View view, Rect frame) { view.Arranged = frame; view.LayoutSlotWithMarginsAndAlignments = frame; LayoutInformation.SetLayoutSlot(view, frame); }
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; } }
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); } }
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); } }
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); } }
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; }
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 })
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); }
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);
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); } }
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); } }