private static void LayoutAutoSizedControls(IArrangedElement container) { ArrangedElementCollection children = container.Children; for (int i = children.Count - 1; i >= 0; i--) { IArrangedElement element = children[i]; if (CommonProperties.xGetAutoSizedAndAnchored(element)) { Rectangle bounds = GetCachedBounds(element); AnchorStyles anchor = GetAnchor(element); Size proposedConstraints = LayoutUtils.MaxSize; if ((anchor & (AnchorStyles.Left | AnchorStyles.Right)) == (AnchorStyles.Left | AnchorStyles.Right)) { proposedConstraints.Width = bounds.Width; } if ((anchor & (AnchorStyles.Top | AnchorStyles.Bottom)) == (AnchorStyles.Top | AnchorStyles.Bottom)) { proposedConstraints.Height = bounds.Height; } Size prefSize = element.GetPreferredSize(proposedConstraints); Rectangle newBounds = bounds; if (CommonProperties.GetAutoSizeMode(element) == AutoSizeMode.GrowAndShrink) { // this is the case for simple things like radio button, checkbox, etc. newBounds = GetGrowthBounds(element, prefSize); } else { // we had whacked this check, but it turns out it causes undesirable // behavior in things like panel. a panel with no elements sizes to 0,0. if (bounds.Width < prefSize.Width || bounds.Height < prefSize.Height) { Size newSize = LayoutUtils.UnionSizes(bounds.Size, prefSize); newBounds = GetGrowthBounds(element, newSize); } } if (newBounds != bounds) { SetCachedBounds(element, newBounds); } } } }
private static void LayoutAutoSizedControls(IArrangedElement container) { ArrangedElementCollection children = container.Children; for (int i = children.Count - 1; i >= 0; i--) { IArrangedElement element = children[i]; if (CommonProperties.xGetAutoSizedAndAnchored(element)) { Rectangle cachedBounds = GetCachedBounds(element); AnchorStyles anchor = GetAnchor(element); Size preferredSize = element.DisplayRectangle.Size; //Size maxSize = cachedBounds.Size; if ((anchor & (AnchorStyles.Right | AnchorStyles.Left)) == (AnchorStyles.Right | AnchorStyles.Left)) { preferredSize.Width = cachedBounds.Width; } if ((anchor & (AnchorStyles.Bottom | AnchorStyles.Top)) == (AnchorStyles.Bottom | AnchorStyles.Top)) { preferredSize.Height = cachedBounds.Height; } Rectangle bounds = cachedBounds; if (CommonProperties.GetAutoSizeMode(element) == AutoSizeMode.GrowAndShrink) { bounds = GetGrowthBounds(element, preferredSize); } else if ((cachedBounds.Width < preferredSize.Width) || (cachedBounds.Height < preferredSize.Height)) { Size newSize = LayoutUtils.UnionSizes(cachedBounds.Size, preferredSize); bounds = GetGrowthBounds(element, newSize); } if (bounds != cachedBounds) { SetCachedBounds(element, bounds); } } } }
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)); }
// LayoutRow and MeasureRow both forward to this method. The measureOnly flag determines which behavior we get. private Size xLayoutRow(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(Int32.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 xLayoutRow). 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); }