public static void SetAnchor(IArrangedElement container, IArrangedElement element, AnchorStyles value) { AnchorStyles anchor = GetAnchor(element); if (anchor != value) { if (CommonProperties.GetNeedsDockLayout(element)) { SetDock(element, DockStyle.None); } CommonProperties.xSetAnchor(element, value); if (CommonProperties.GetNeedsAnchorLayout(element)) { UpdateAnchorInfo(element); } else { SetAnchorInfo(element, null); } if (element.Container != null) { bool flag = IsAnchored(anchor, AnchorStyles.Right) && !IsAnchored(value, AnchorStyles.Right); bool flag2 = IsAnchored(anchor, AnchorStyles.Bottom) && !IsAnchored(value, AnchorStyles.Bottom); if ((element.Container.Container != null) && (flag || flag2)) { LayoutTransaction.DoLayout(element.Container.Container, element, PropertyNames.Anchor); } LayoutTransaction.DoLayout(element.Container, element, PropertyNames.Anchor); } } }
internal override void InitLayoutCore(IArrangedElement element, BoundsSpecified specified) { if ((specified != BoundsSpecified.None) && CommonProperties.GetNeedsAnchorLayout(element)) { UpdateAnchorInfo(element); } }
private static void LayoutAnchoredControls(IArrangedElement container) { Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "\tAnchor Processing"); Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "\t\tdisplayRect: " + container.DisplayRectangle.ToString()); Rectangle displayRectangle = container.DisplayRectangle; if (CommonProperties.GetAutoSize(container) && ((displayRectangle.Width == 0) || (displayRectangle.Height == 0))) { // we havent set oursleves to the preferred size yet. proceeding will // just set all the control widths to zero. let's return here return; } ArrangedElementCollection children = container.Children; for (int i = children.Count - 1; i >= 0; i--) { IArrangedElement element = children[i]; if (CommonProperties.GetNeedsAnchorLayout(element)) { Debug.Assert(GetAnchorInfo(element) != null, "AnchorInfo should be initialized before LayoutAnchorControls()."); SetCachedBounds(element, GetAnchorDestination(element, displayRectangle, /*measureOnly=*/ false)); } } }
private protected override void InitLayoutCore(IArrangedElement element, BoundsSpecified specified) { Debug.Assert(specified == BoundsSpecified.None || GetCachedBounds(element) == element.Bounds, "Attempt to InitLayout while element has active cached bounds."); if (specified != BoundsSpecified.None && CommonProperties.GetNeedsAnchorLayout(element)) { UpdateAnchorInfo(element); } }
private static void UpdateAnchorInfo(IArrangedElement element) { AnchorInfo anchorInfo = GetAnchorInfo(element); if (anchorInfo == null) { anchorInfo = new AnchorInfo(); SetAnchorInfo(element, anchorInfo); } if (CommonProperties.GetNeedsAnchorLayout(element) && (element.Container != null)) { GetCachedBounds(element); anchorInfo.Left = element.Bounds.Left; anchorInfo.Top = element.Bounds.Top; anchorInfo.Right = element.Bounds.Right; anchorInfo.Bottom = element.Bounds.Bottom; Rectangle displayRectangle = element.Container.DisplayRectangle; int width = displayRectangle.Width; int height = displayRectangle.Height; anchorInfo.Left -= displayRectangle.X; anchorInfo.Top -= displayRectangle.Y; anchorInfo.Right -= displayRectangle.X; anchorInfo.Bottom -= displayRectangle.Y; AnchorStyles anchor = GetAnchor(element); if (IsAnchored(anchor, AnchorStyles.Right)) { anchorInfo.Right -= width; if (!IsAnchored(anchor, AnchorStyles.Left)) { anchorInfo.Left -= width; } } else if (!IsAnchored(anchor, AnchorStyles.Left)) { anchorInfo.Right -= width / 2; anchorInfo.Left -= width / 2; } if (IsAnchored(anchor, AnchorStyles.Bottom)) { anchorInfo.Bottom -= height; if (!IsAnchored(anchor, AnchorStyles.Top)) { anchorInfo.Top -= height; } } else if (!IsAnchored(anchor, AnchorStyles.Top)) { anchorInfo.Bottom -= height / 2; anchorInfo.Top -= height / 2; } } }
private static void LayoutAnchoredControls(IArrangedElement container) { Rectangle displayRectangle = container.DisplayRectangle; if (!CommonProperties.GetAutoSize(container) || ((displayRectangle.Width != 0) && (displayRectangle.Height != 0))) { ArrangedElementCollection children = container.Children; for (int i = children.Count - 1; i >= 0; i--) { IArrangedElement element = children[i]; if (CommonProperties.GetNeedsAnchorLayout(element)) { SetCachedBounds(element, GetAnchorDestination(element, displayRectangle, false)); } } } }
public static void SetAnchor(IArrangedElement element, AnchorStyles value) { AnchorStyles oldValue = GetAnchor(element); if (oldValue != value) { if (CommonProperties.GetNeedsDockLayout(element)) { // We set dock back to none to cause the element to size back to its original bounds. SetDock(element, DockStyle.None); } CommonProperties.xSetAnchor(element, value); // Updating AnchorInfo is only needed when control is ready for layout. Oneway to check this precondition is to // check if the control is parented. This helps avoid calculating AnchorInfo with default initial values of the Control. // AnchorInfo is recalculated everytime there is a layout change. if (CommonProperties.GetNeedsAnchorLayout(element) && element is Control control && control.Parent is not null) { UpdateAnchorInfo(element); } else { SetAnchorInfo(element, null); } if (element.Container is not null) { bool rightReleased = IsAnchored(oldValue, AnchorStyles.Right) && !IsAnchored(value, AnchorStyles.Right); bool bottomReleased = IsAnchored(oldValue, AnchorStyles.Bottom) && !IsAnchored(value, AnchorStyles.Bottom); if (element.Container.Container is not null && (rightReleased || bottomReleased)) { // If the right or bottom anchor is being released, we have a special case where the element's // margin may affect preferredSize where it didn't previously. Rather than do an expensive // check for this in OnLayout, we just detect the case her and force a relayout. LayoutTransaction.DoLayout(element.Container.Container, element, PropertyNames.Anchor); } LayoutTransaction.DoLayout(element.Container, element, PropertyNames.Anchor); } }
public static void SetAnchor(IArrangedElement container, IArrangedElement element, AnchorStyles value) { AnchorStyles oldValue = GetAnchor(element); if (oldValue != value) { if (CommonProperties.GetNeedsDockLayout(element)) { // We set dock back to none to cause the element to size back to its original bounds. SetDock(element, DockStyle.None); } CommonProperties.xSetAnchor(element, value); if (CommonProperties.GetNeedsAnchorLayout(element)) { UpdateAnchorInfo(element); } else { SetAnchorInfo(element, null); } if (element.Container != null) { bool rightReleased = IsAnchored(oldValue, AnchorStyles.Right) && !IsAnchored(value, AnchorStyles.Right); bool bottomReleased = IsAnchored(oldValue, AnchorStyles.Bottom) && !IsAnchored(value, AnchorStyles.Bottom); if (element.Container.Container != null && (rightReleased || bottomReleased)) { // If the right or bottom anchor is being released, we have a special case where the element's // margin may affect preferredSize where it didn't previously. Rather than do an expensive // check for this in OnLayout, we just detect the case her and force a relayout. LayoutTransaction.DoLayout(element.Container.Container, element, PropertyNames.Anchor); } LayoutTransaction.DoLayout(element.Container, element, PropertyNames.Anchor); } } }
private static void UpdateAnchorInfo(IArrangedElement element) { Debug.Assert(!HasCachedBounds(element.Container), "Do not call this method with an active cached bounds list."); AnchorInfo anchorInfo = GetAnchorInfo(element); if (anchorInfo is null) { anchorInfo = new AnchorInfo(); SetAnchorInfo(element, anchorInfo); } Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "Update anchor info"); Debug.Indent(); Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, element.Container is null ? "No parent" : "Parent"); if (CommonProperties.GetNeedsAnchorLayout(element) && element.Container != null) { Rectangle bounds = GetCachedBounds(element); AnchorInfo oldAnchorInfo = new AnchorInfo { Left = anchorInfo.Left, Top = anchorInfo.Top, Right = anchorInfo.Right, Bottom = anchorInfo.Bottom }; anchorInfo.Left = element.Bounds.Left; anchorInfo.Top = element.Bounds.Top; anchorInfo.Right = element.Bounds.Right; anchorInfo.Bottom = element.Bounds.Bottom; Rectangle parentDisplayRect = element.Container.DisplayRectangle; Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "Parent displayRectangle" + parentDisplayRect); int parentWidth = parentDisplayRect.Width; int parentHeight = parentDisplayRect.Height; // The anchor is relative to the parent DisplayRectangle, so offset the anchor // by the DisplayRect origin anchorInfo.Left -= parentDisplayRect.X; anchorInfo.Top -= parentDisplayRect.Y; anchorInfo.Right -= parentDisplayRect.X; anchorInfo.Bottom -= parentDisplayRect.Y; AnchorStyles anchor = GetAnchor(element); if (IsAnchored(anchor, AnchorStyles.Right)) { if (DpiHelper.IsScalingRequirementMet && (anchorInfo.Right - parentWidth > 0) && (oldAnchorInfo.Right < 0)) { // parent was resized to fit its parent, or screen, we need to reuse old anchor info to prevent losing control beyond right edge anchorInfo.Right = oldAnchorInfo.Right; // control might have been resized, update Left anchor anchorInfo.Left = oldAnchorInfo.Right - bounds.Width; } else { anchorInfo.Right -= parentWidth; if (!IsAnchored(anchor, AnchorStyles.Left)) { anchorInfo.Left -= parentWidth; } } } else if (!IsAnchored(anchor, AnchorStyles.Left)) { anchorInfo.Right -= (parentWidth / 2); anchorInfo.Left -= (parentWidth / 2); } if (IsAnchored(anchor, AnchorStyles.Bottom)) { if (DpiHelper.IsScalingRequirementMet && (anchorInfo.Bottom - parentHeight > 0) && (oldAnchorInfo.Bottom < 0)) { // parent was resized to fit its parent, or screen, we need to reuse old anchor info to prevent losing control beyond bottom edge anchorInfo.Bottom = oldAnchorInfo.Bottom; // control might have been resized, update Top anchor anchorInfo.Top = oldAnchorInfo.Bottom - bounds.Height; } else { anchorInfo.Bottom -= parentHeight; if (!IsAnchored(anchor, AnchorStyles.Top)) { anchorInfo.Top -= parentHeight; } } } else if (!IsAnchored(anchor, AnchorStyles.Top)) { anchorInfo.Bottom -= (parentHeight / 2); anchorInfo.Top -= (parentHeight / 2); } Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "anchor info (l,t,r,b): (" + anchorInfo.Left + ", " + anchorInfo.Top + ", " + anchorInfo.Right + ", " + anchorInfo.Bottom + ")"); } Debug.Unindent(); }
private static bool TryCalculatePreferredSize(IArrangedElement container, bool measureOnly, out Size preferredSize) { ArrangedElementCollection children = container.Children; // PreferredSize is garbage unless measureOnly is specified preferredSize = new Size(-7103, -7105); // Short circuit for items with no children if (!measureOnly && children.Count == 0) { return(CommonProperties.GetAutoSize(container)); } bool dock = false; bool anchor = false; bool autoSize = false; for (int i = children.Count - 1; i >= 0; i--) { IArrangedElement element = children[i]; if (CommonProperties.GetNeedsDockAndAnchorLayout(element)) { if (!dock && CommonProperties.GetNeedsDockLayout(element)) { dock = true; } if (!anchor && CommonProperties.GetNeedsAnchorLayout(element)) { anchor = true; } if (!autoSize && CommonProperties.xGetAutoSizedAndAnchored(element)) { autoSize = true; } } } Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "\tanchor : " + anchor.ToString()); Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "\tdock : " + dock.ToString()); Size preferredSizeForDocking = Size.Empty; Size preferredSizeForAnchoring = Size.Empty; if (dock) { preferredSizeForDocking = LayoutDockedControls(container, measureOnly); } if (anchor && !measureOnly) { // In the case of anchor, where we currently are defines the preferred size, // so dont recalculate the positions of everything. LayoutAnchoredControls(container); } if (autoSize) { LayoutAutoSizedControls(container); } if (!measureOnly) { // Set the anchored controls to their computed positions. ApplyCachedBounds(container); } else { // Finish the preferredSize computation and clear cached anchored positions. preferredSizeForAnchoring = GetAnchorPreferredSize(container); Padding containerPadding = Padding.Empty; if (container is Control control) { // Calling this will respect Control.DefaultPadding. containerPadding = control.Padding; } else { // Not likely to happen but handle this gracefully. containerPadding = CommonProperties.GetPadding(container, Padding.Empty); } preferredSizeForAnchoring.Width -= containerPadding.Left; preferredSizeForAnchoring.Height -= containerPadding.Top; ClearCachedBounds(container); preferredSize = LayoutUtils.UnionSizes(preferredSizeForDocking, preferredSizeForAnchoring); } return(CommonProperties.GetAutoSize(container)); }
private static bool xLayout(IArrangedElement container, bool measureOnly, out Size preferredSize) { ArrangedElementCollection children = container.Children; preferredSize = new Size(-7103, -7105); if (measureOnly || (children.Count != 0)) { bool flag = false; bool flag2 = false; bool flag3 = false; for (int i = children.Count - 1; i >= 0; i--) { IArrangedElement element = children[i]; if (CommonProperties.GetNeedsDockAndAnchorLayout(element)) { if (!flag && CommonProperties.GetNeedsDockLayout(element)) { flag = true; } if (!flag2 && CommonProperties.GetNeedsAnchorLayout(element)) { flag2 = true; } if (!flag3 && CommonProperties.xGetAutoSizedAndAnchored(element)) { flag3 = true; } } } Size empty = Size.Empty; Size b = Size.Empty; if (flag) { empty = LayoutDockedControls(container, measureOnly); } if (flag2 && !measureOnly) { LayoutAnchoredControls(container); } if (flag3) { LayoutAutoSizedControls(container); } if (!measureOnly) { ApplyCachedBounds(container); } else { b = GetAnchorPreferredSize(container); Padding padding = Padding.Empty; Control control = container as Control; if (control != null) { padding = control.Padding; } else { padding = CommonProperties.GetPadding(container, Padding.Empty); } b.Width -= padding.Left; b.Height -= padding.Top; ClearCachedBounds(container); preferredSize = LayoutUtils.UnionSizes(empty, b); } } return(CommonProperties.GetAutoSize(container)); }
private static void UpdateAnchorInfo(IArrangedElement element) { AnchorInfo anchorInfo = GetAnchorInfo(element); if (anchorInfo == null) { anchorInfo = new AnchorInfo(); SetAnchorInfo(element, anchorInfo); } if (CommonProperties.GetNeedsAnchorLayout(element) && (element.Container != null)) { Rectangle cachedBounds = GetCachedBounds(element); AnchorInfo info2 = new AnchorInfo { Left = anchorInfo.Left, Top = anchorInfo.Top, Right = anchorInfo.Right, Bottom = anchorInfo.Bottom }; anchorInfo.Left = element.Bounds.Left; anchorInfo.Top = element.Bounds.Top; anchorInfo.Right = element.Bounds.Right; anchorInfo.Bottom = element.Bounds.Bottom; Rectangle displayRectangle = element.Container.DisplayRectangle; int width = displayRectangle.Width; int height = displayRectangle.Height; anchorInfo.Left -= displayRectangle.X; anchorInfo.Top -= displayRectangle.Y; anchorInfo.Right -= displayRectangle.X; anchorInfo.Bottom -= displayRectangle.Y; AnchorStyles anchor = GetAnchor(element); if (IsAnchored(anchor, AnchorStyles.Right)) { if ((System.Windows.Forms.DpiHelper.EnableAnchorLayoutHighDpiImprovements && ((anchorInfo.Right - width) > 0)) && (info2.Right < 0)) { anchorInfo.Right = info2.Right; anchorInfo.Left = info2.Right - cachedBounds.Width; } else { anchorInfo.Right -= width; if (!IsAnchored(anchor, AnchorStyles.Left)) { anchorInfo.Left -= width; } } } else if (!IsAnchored(anchor, AnchorStyles.Left)) { anchorInfo.Right -= width / 2; anchorInfo.Left -= width / 2; } if (IsAnchored(anchor, AnchorStyles.Bottom)) { if ((System.Windows.Forms.DpiHelper.EnableAnchorLayoutHighDpiImprovements && ((anchorInfo.Bottom - height) > 0)) && (info2.Bottom < 0)) { anchorInfo.Bottom = info2.Bottom; anchorInfo.Top = info2.Bottom - cachedBounds.Height; } else { anchorInfo.Bottom -= height; if (!IsAnchored(anchor, AnchorStyles.Top)) { anchorInfo.Top -= height; } } } else if (!IsAnchored(anchor, AnchorStyles.Top)) { anchorInfo.Bottom -= height / 2; anchorInfo.Top -= height / 2; } } }