예제 #1
0
        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);
                }
            }
        }
예제 #2
0
 internal override void InitLayoutCore(IArrangedElement element, BoundsSpecified specified)
 {
     if ((specified != BoundsSpecified.None) && CommonProperties.GetNeedsAnchorLayout(element))
     {
         UpdateAnchorInfo(element);
     }
 }
예제 #3
0
        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));
                }
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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;
                }
            }
        }
예제 #6
0
        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));
                    }
                }
            }
        }
예제 #7
0
        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);
                }
            }
예제 #8
0
        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);
                }
            }
        }
예제 #9
0
        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();
        }
예제 #10
0
        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));
        }
예제 #11
0
        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));
        }
예제 #12
0
        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;
                }
            }
        }