private static void Copy(ArrangedElementCollection sourceList, int sourceIndex, ArrangedElementCollection destinationList, int destinationIndex, int length)
 {
     if (sourceIndex < destinationIndex)
     {
         sourceIndex += length;
         destinationIndex += length;
         while (length > 0)
         {
             destinationList.InnerList[--destinationIndex] = sourceList.InnerList[--sourceIndex];
             length--;
         }
     }
     else
     {
         while (length > 0)
         {
             destinationList.InnerList[destinationIndex++] = sourceList.InnerList[sourceIndex++];
             length--;
         }
     }
 }
예제 #2
0
 private static void Copy (ArrangedElementCollection sourceList, int sourceIndex, ArrangedElementCollection destinationList, int destinationIndex, int  length) {
     if(sourceIndex < destinationIndex) {
         // We need to copy from the back forward to prevent overwrite if source and
         // destination lists are the same, so we need to flip the source/dest indices
         // to point at the end of the spans to be copied.
         sourceIndex = sourceIndex + length;
         destinationIndex = destinationIndex + length;
         
         for(;length > 0; length--) {
             destinationList.InnerList[--destinationIndex] = sourceList.InnerList[--sourceIndex];
         }
     } else {
         for(;length > 0; length--) {
             destinationList.InnerList[destinationIndex++] = sourceList.InnerList[sourceIndex++];
         }
     }
 }
예제 #3
0
        private Size TryCalculatePreferredSizeRow(ContainerProxy containerProxy, ElementProxy elementProxy, int startIndex, int endIndex, Rectangle rowBounds, out int breakIndex, bool measureOnly)
        {
            Debug.Assert(startIndex < endIndex, "Loop should be in forward Z-order.");
            Point location     = rowBounds.Location;
            Size  rowSize      = Size.Empty;
            int   laidOutItems = 0;

            breakIndex = startIndex;

            bool wrapContents    = GetWrapContents(containerProxy.Container);
            bool breakOnNextItem = false;

            ArrangedElementCollection collection = containerProxy.Container.Children;

            for (int i = startIndex; i < endIndex; i++, breakIndex++)
            {
                elementProxy.Element = collection[i];
                if (!elementProxy.ParticipatesInLayout)
                {
                    continue;
                }

                // Figure out how much space this element is going to need (requiredSize)
                Size prefSize;
                if (elementProxy.AutoSize)
                {
                    Size elementConstraints = new Size(int.MaxValue, rowBounds.Height - elementProxy.Margin.Size.Height);
                    if (i == startIndex)
                    {
                        // If the element is the first in the row, attempt to pack it to the row width. (If its not 1st, it will wrap
                        // to the first on the next row if its too long and then be packed if needed by the next call to TryCalculatePreferredSizeRow).
                        elementConstraints.Width = rowBounds.Width - rowSize.Width - elementProxy.Margin.Size.Width;
                    }

                    // Make sure that subtracting the margins does not cause width/height to be <= 0, or we will
                    // size as if we had infinite space when in fact we are trying to be as small as possible.
                    elementConstraints = LayoutUtils.UnionSizes(new Size(1, 1), elementConstraints);
                    prefSize           = elementProxy.GetPreferredSize(elementConstraints);
                }
                else
                {
                    // If autosizing is turned off, we just use the element's current size as its preferred size.
                    prefSize = elementProxy.SpecifiedSize;

                    // except if it is stretching - then ignore the affect of the height dimension.
                    if (elementProxy.Stretches)
                    {
                        prefSize.Height = 0;
                    }

                    // Enforce MinimumSize
                    if (prefSize.Height < elementProxy.MinimumSize.Height)
                    {
                        prefSize.Height = elementProxy.MinimumSize.Height;
                    }
                }

                Size requiredSize = prefSize + elementProxy.Margin.Size;

                // Position the element (if applicable).
                if (!measureOnly)
                {
                    // If measureOnly = false, rowBounds.Height = measured row hieght
                    // (otherwise its the remaining displayRect of the container)

                    Rectangle cellBounds = new Rectangle(location, new Size(requiredSize.Width, rowBounds.Height));

                    // We laid out the rows with the elementProxy's margins included.
                    // We now deflate the rect to get the actual elementProxy bounds.
                    cellBounds = LayoutUtils.DeflateRect(cellBounds, elementProxy.Margin);

                    AnchorStyles anchorStyles = elementProxy.AnchorStyles;
                    containerProxy.Bounds = LayoutUtils.AlignAndStretch(prefSize, cellBounds, anchorStyles);
                }

                // Keep track of how much space is being used in this row
                location.X += requiredSize.Width;
                if (laidOutItems > 0)
                {
                    // If control does not fit on this row, exclude it from row and stop now.
                    //   Exception: If row is empty, allow this control to fit on it. So controls
                    //   that exceed the maximum row width will end up occupying their own rows.
                    if (location.X > rowBounds.Right)
                    {
                        break;
                    }
                }

                // Control fits on this row, so update the row size.
                //   rowSize.Width != location.X because with a scrollable control
                //   we could have started with a location like -100.
                rowSize.Width  = location.X - rowBounds.X;
                rowSize.Height = Math.Max(rowSize.Height, requiredSize.Height);

                // check for line breaks.
                if (wrapContents)
                {
                    if (breakOnNextItem)
                    {
                        break;
                    }
                    else if (i + 1 < endIndex && CommonProperties.GetFlowBreak(elementProxy.Element))
                    {
                        if (laidOutItems == 0)
                        {
                            breakOnNextItem = true;
                        }
                        else
                        {
                            breakIndex++;
                            break;
                        }
                    }
                }

                laidOutItems++;
            }

            return(rowSize);
        }
        private Size xLayoutRow(ContainerProxy containerProxy, ElementProxy elementProxy, int startIndex, int endIndex, Rectangle rowBounds, out int breakIndex, bool measureOnly)
        {
            Point location = rowBounds.Location;
            Size  empty    = Size.Empty;
            int   num      = 0;

            breakIndex = startIndex;
            bool wrapContents = GetWrapContents(containerProxy.Container);
            bool flag2        = false;
            ArrangedElementCollection children = containerProxy.Container.Children;
            int num2 = startIndex;

            while (num2 < endIndex)
            {
                elementProxy.Element = children[num2];
                if (elementProxy.ParticipatesInLayout)
                {
                    Size preferredSize;
                    if (elementProxy.AutoSize)
                    {
                        Size b = new Size(0x7fffffff, rowBounds.Height - elementProxy.Margin.Size.Height);
                        if (num2 == startIndex)
                        {
                            b.Width = (rowBounds.Width - empty.Width) - elementProxy.Margin.Size.Width;
                        }
                        b             = LayoutUtils.UnionSizes(new Size(1, 1), b);
                        preferredSize = elementProxy.GetPreferredSize(b);
                    }
                    else
                    {
                        preferredSize = elementProxy.SpecifiedSize;
                        if (elementProxy.Stretches)
                        {
                            preferredSize.Height = 0;
                        }
                        if (preferredSize.Height < elementProxy.MinimumSize.Height)
                        {
                            preferredSize.Height = elementProxy.MinimumSize.Height;
                        }
                    }
                    Size size4 = preferredSize + elementProxy.Margin.Size;
                    if (!measureOnly)
                    {
                        Rectangle rect = new Rectangle(location, new Size(size4.Width, rowBounds.Height));
                        rect = LayoutUtils.DeflateRect(rect, elementProxy.Margin);
                        AnchorStyles anchorStyles = elementProxy.AnchorStyles;
                        containerProxy.Bounds = LayoutUtils.AlignAndStretch(preferredSize, rect, anchorStyles);
                    }
                    location.X += size4.Width;
                    if ((num > 0) && (location.X > rowBounds.Right))
                    {
                        return(empty);
                    }
                    empty.Width  = location.X - rowBounds.X;
                    empty.Height = Math.Max(empty.Height, size4.Height);
                    if (wrapContents)
                    {
                        if (flag2)
                        {
                            return(empty);
                        }
                        if (((num2 + 1) < endIndex) && CommonProperties.GetFlowBreak(elementProxy.Element))
                        {
                            if (num == 0)
                            {
                                flag2 = true;
                            }
                            else
                            {
                                breakIndex++;
                                return(empty);
                            }
                        }
                    }
                    num++;
                }
                num2++;
                breakIndex++;
            }
            return(empty);
        }
예제 #5
0
        private static Size GetAnchorPreferredSize(IArrangedElement container)
        {
            Size prefSize = Size.Empty;

            ArrangedElementCollection children = container.Children;

            for (int i = children.Count - 1; i >= 0; i--)
            {
                IArrangedElement element = container.Children[i];
                if (!CommonProperties.GetNeedsDockLayout(element) && element.ParticipatesInLayout)
                {
                    AnchorStyles anchor       = GetAnchor(element);
                    Padding      margin       = CommonProperties.GetMargin(element);
                    Rectangle    elementSpace = LayoutUtils.InflateRect(GetCachedBounds(element), margin);

                    if (IsAnchored(anchor, AnchorStyles.Left) && !IsAnchored(anchor, AnchorStyles.Right))
                    {
                        // If we are anchored to the left we make sure the container is large enough not to clip us
                        // (unless we are right anchored, in which case growing the container will just resize us.)
                        prefSize.Width = Math.Max(prefSize.Width, elementSpace.Right);
                    }

                    if (!IsAnchored(anchor, AnchorStyles.Bottom))
                    {
                        // If we are anchored to the top we make sure the container is large enough not to clip us
                        // (unless we are bottom anchored, in which case growing the container will just resize us.)
                        prefSize.Height = Math.Max(prefSize.Height, elementSpace.Bottom);
                    }

                    if (IsAnchored(anchor, AnchorStyles.Right))
                    {
                        // If we are right anchored, see what the anchor distance between our right edge and
                        // the container is, and make sure our container is large enough to accomodate us.
                        Rectangle anchorDest = GetAnchorDestination(element, Rectangle.Empty, /*measureOnly=*/ true);
                        if (anchorDest.Width < 0)
                        {
                            prefSize.Width = Math.Max(prefSize.Width, elementSpace.Right + anchorDest.Width);
                        }
                        else
                        {
                            prefSize.Width = Math.Max(prefSize.Width, anchorDest.Right);
                        }
                    }

                    if (IsAnchored(anchor, AnchorStyles.Bottom))
                    {
                        // If we are right anchored, see what the anchor distance between our right edge and
                        // the container is, and make sure our container is large enough to accomodate us.
                        Rectangle anchorDest = GetAnchorDestination(element, Rectangle.Empty, /*measureOnly=*/ true);
                        if (anchorDest.Height < 0)
                        {
                            prefSize.Height = Math.Max(prefSize.Height, elementSpace.Bottom + anchorDest.Height);
                        }
                        else
                        {
                            prefSize.Height = Math.Max(prefSize.Height, anchorDest.Bottom);
                        }
                    }
                }
            }

            return(prefSize);
        }
예제 #6
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));
        }
예제 #7
0
        private static Size LayoutDockedControls(IArrangedElement container, bool measureOnly)
        {
            Debug.WriteLineIf(CompModSwitches.RichLayout.TraceInfo, "\tDock Processing");
            Debug.Assert(!HasCachedBounds(container), "Do not call this method with an active cached bounds list.");

            // If measuring, we start with an empty rectangle and add as needed.
            // If doing actual layout, we start with the container's rect and subtract as we layout.
            Rectangle remainingBounds = measureOnly ? Rectangle.Empty : container.DisplayRectangle;
            Size      preferredSize   = Size.Empty;

            IArrangedElement mdiClient = null;

            // Docking layout is order dependent. After much debate, we decided to use z-order as the
            // docking order. (Introducing a DockOrder property was a close second)
            ArrangedElementCollection children = container.Children;

            for (int i = children.Count - 1; i >= 0; i--)
            {
                IArrangedElement element = children[i];
                Debug.Assert(element.Bounds == GetCachedBounds(element), "Why do we have cachedBounds for a docked element?");
                if (CommonProperties.GetNeedsDockLayout(element))
                {
                    // Some controls modify their bounds when you call SetBoundsCore. We
                    // therefore need to read the value of bounds back when adjusting our layout rectangle.
                    switch (GetDock(element))
                    {
                    case DockStyle.Top:
                    {
                        Size      elementSize      = GetVerticalDockedSize(element, remainingBounds.Size, measureOnly);
                        Rectangle newElementBounds = new Rectangle(remainingBounds.X, remainingBounds.Y, elementSize.Width, elementSize.Height);

                        TryCalculatePreferredSizeDockedControl(element, newElementBounds, measureOnly, ref preferredSize, ref remainingBounds);

                        // What we are really doing here: top += element.Bounds.Height;
                        remainingBounds.Y      += element.Bounds.Height;
                        remainingBounds.Height -= element.Bounds.Height;
                        break;
                    }

                    case DockStyle.Bottom:
                    {
                        Size      elementSize      = GetVerticalDockedSize(element, remainingBounds.Size, measureOnly);
                        Rectangle newElementBounds = new Rectangle(remainingBounds.X, remainingBounds.Bottom - elementSize.Height, elementSize.Width, elementSize.Height);

                        TryCalculatePreferredSizeDockedControl(element, newElementBounds, measureOnly, ref preferredSize, ref remainingBounds);

                        // What we are really doing here: bottom -= element.Bounds.Height;
                        remainingBounds.Height -= element.Bounds.Height;

                        break;
                    }

                    case DockStyle.Left:
                    {
                        Size      elementSize      = GetHorizontalDockedSize(element, remainingBounds.Size, measureOnly);
                        Rectangle newElementBounds = new Rectangle(remainingBounds.X, remainingBounds.Y, elementSize.Width, elementSize.Height);

                        TryCalculatePreferredSizeDockedControl(element, newElementBounds, measureOnly, ref preferredSize, ref remainingBounds);

                        // What we are really doing here: left += element.Bounds.Width;
                        remainingBounds.X     += element.Bounds.Width;
                        remainingBounds.Width -= element.Bounds.Width;
                        break;
                    }

                    case DockStyle.Right:
                    {
                        Size      elementSize      = GetHorizontalDockedSize(element, remainingBounds.Size, measureOnly);
                        Rectangle newElementBounds = new Rectangle(remainingBounds.Right - elementSize.Width, remainingBounds.Y, elementSize.Width, elementSize.Height);

                        TryCalculatePreferredSizeDockedControl(element, newElementBounds, measureOnly, ref preferredSize, ref remainingBounds);

                        // What we are really doing here: right -= element.Bounds.Width;
                        remainingBounds.Width -= element.Bounds.Width;
                        break;
                    }

                    case DockStyle.Fill:
                        if (element is MdiClient)
                        {
                            Debug.Assert(mdiClient is null, "How did we end up with multiple MdiClients?");
                            mdiClient = element;
                        }
                        else
                        {
                            Size      elementSize      = remainingBounds.Size;
                            Rectangle newElementBounds = new Rectangle(remainingBounds.X, remainingBounds.Y, elementSize.Width, elementSize.Height);

                            TryCalculatePreferredSizeDockedControl(element, newElementBounds, measureOnly, ref preferredSize, ref remainingBounds);
                        }
                        break;

                    default:
                        Debug.Fail("Unsupported value for dock.");
                        break;
                    }
                }

                // Treat the MDI client specially, since it's supposed to blend in with the parent form
                if (mdiClient != null)
                {
                    SetCachedBounds(mdiClient, remainingBounds);
                }
            }

            return(preferredSize);
        }
예제 #8
0
        private static void Copy(ArrangedElementCollection sourceList, int sourceIndex, ArrangedElementCollection destinationList, int destinationIndex, int length)
        {
            if (sourceIndex < destinationIndex)
            {
                // We need to copy from the back forward to prevent overwrite if source and
                // destination lists are the same, so we need to flip the source/dest indices
                // to point at the end of the spans to be copied.
                sourceIndex      = sourceIndex + length;
                destinationIndex = destinationIndex + length;

                for (; length > 0; length--)
                {
                    destinationList.InnerList[--destinationIndex] = sourceList.InnerList[--sourceIndex];
                }
            }
            else
            {
                for (; length > 0; length--)
                {
                    destinationList.InnerList[destinationIndex++] = sourceList.InnerList[sourceIndex++];
                }
            }
        }