public WithMaxWidthOffsetBy ( int maxWidth, int dx, int dy ) : |
||
maxWidth | int | |
dx | int | |
dy | int | |
return |
/// <summary> /// This routine and its overrides are used to make sure that the part of the root box between /// yTop and yBottom (measured from the top of the root) can be painted successfully. To facilitate /// the process of replacing a lazy box with real boxes, it is passed the previous box in its /// container (or null if there is none) and returns the next box which the container should /// check is prepared to paint. By default this is simply the next box, but if a lazy box expands /// (part of) itself, it should answer the replacement box. /// Most box classes are always prepared to paint and do nothing. Lazy boxes convert all or part of /// themselves to real boxes if they intersect the specified vertical range (relative to the root as /// a whole). Boxes (currently DivBoxes only) which might contain lazy boxes pass the message on /// to their children, making the appropriate adjustment to the layout transform, just as when /// asking their children to Layout. /// </summary> internal override Box PrepareToPaint(LayoutInfo transform, Box myPrevBox, int dysTop, int dysBottom) { var childMaxWidth = transform.MaxWidth - GapLeading(transform) - GapTrailing(transform); var childTransform = transform.WithMaxWidthOffsetBy(childMaxWidth, Left, Top); Box prevBox = null; for (Box box = FirstBox; box != null;) { if (transform.YOffset + box.Top > dysBottom) { // nothing further down in this can be visible. Possibly we should return null, // since presumably nothing further down in the container is visible, either. // However, it feels more robust to answer in the usual way and let the container decide // for itself. return(Next); } if (transform.YOffset + box.Bottom < dysTop) { box = box.Next; // this box is not visible, but a later one might be } else { box = box.PrepareToPaint(childTransform, prevBox, dysTop, dysBottom); } } return(Next); }
private Box ChildSetup(Box box, LayoutInfo transform, int maxBoxWidth, int left, int top) { var childTransform = transform.WithMaxWidthOffsetBy(maxBoxWidth, Left, Top); // todo: test box.Layout(childTransform); box.Left = left; box.Top = top; return box; }
private Box ChildSetup(Box box, LayoutInfo transform, int maxBoxWidth, int left, int top) { var childTransform = transform.WithMaxWidthOffsetBy(maxBoxWidth, Left, Top); // todo: test box.Layout(childTransform); box.Left = left; box.Top = top; return(box); }
public override void Layout(LayoutInfo transform) { var left = GapLeading(transform); var top = GapTop(transform); var rightGap = GapTrailing(transform); var maxHeight = 0; var maxWidth = transform.MaxWidth; Box prevBox = null; int[] columnWidths = m_ColumnWidths.ColumnWidths(NumBoxes, new LayoutInfo(transform.XOffset, transform.YOffset, transform.DpiX, transform.DpiY, transform.MaxWidth - left - rightGap, transform.VwGraphics, transform.RendererFactory)); int i = 0; if (m_WrapRow) { var leftGap = GapLeading(transform); for (var box = FirstBox; box != null; box = box.Next) { box = ChildSetup(box, transform, columnWidths[i], leftGap, top); if (leftGap + Math.Min(box.Width, columnWidths[i]) >= maxWidth && prevBox != null) { top = maxHeight + GapTop(transform); leftGap = GapLeading(transform); box = ChildSetup(box, transform, columnWidths[i], leftGap, top); maxHeight += box.Height; } else { box = ChildSetup(box, transform, columnWidths[i], leftGap, top); maxHeight = Math.Max(maxHeight, box.Height + box.Top - GapTop(transform)); } leftGap += box.Width; left = Math.Max(left, leftGap); prevBox = box; i++; } } else { for (var box = FirstBox; box != null; box = box.Next) { var childTransform = transform.WithMaxWidthOffsetBy(columnWidths[i], Left, Top); // todo: test i++; box.Layout(childTransform); box.Left = left; box.Top = top; left += box.Width; maxHeight = Math.Max(maxHeight, box.Height); } } Height = maxHeight + GapTop(transform) + GapBottom(transform); Width = left + rightGap; }
public override void Layout(LayoutInfo transform) { var left = GapLeading(transform); var top = GapTop(transform); var rightGap = GapTrailing(transform); var maxHeight = 0; var maxWidth = transform.MaxWidth; Box prevBox = null; int[] columnWidths = m_ColumnWidths.ColumnWidths(NumBoxes, new LayoutInfo(transform.XOffset, transform.YOffset, transform.DpiX, transform.DpiY, transform.MaxWidth - left - rightGap, transform.VwGraphics, transform.RendererFactory)); int i = 0; if (m_WrapRow) { var leftGap = GapLeading(transform); for (var box = FirstBox; box != null; box = box.Next) { box = ChildSetup(box, transform, columnWidths[i], leftGap, top); if (leftGap + Math.Min(box.Width, columnWidths[i]) >= maxWidth && prevBox != null) { top = maxHeight + GapTop(transform); leftGap = GapLeading(transform); box = ChildSetup(box, transform, columnWidths[i], leftGap, top); maxHeight += box.Height; } else { box = ChildSetup(box, transform, columnWidths[i], leftGap, top); maxHeight = Math.Max(maxHeight, box.Height + box.Top - GapTop(transform)); } leftGap += box.Width; left = Math.Max(left, leftGap); prevBox = box; i++; } } else { for (var box = FirstBox; box != null; box = box.Next) { var childTransform = transform.WithMaxWidthOffsetBy(columnWidths[i], Left, Top); // todo: test i++; box.Layout(childTransform); box.Left = left; box.Top = top; left += box.Width; maxHeight = Math.Max(maxHeight, box.Height); } } Height = maxHeight + GapTop(transform) + GapBottom(transform); Width = left + rightGap; }
public override void Layout(LayoutInfo transform) { var left = GapLeading(transform); var top = GapTop(transform); var rightGap = GapTrailing(transform); var maxWidth = transform.MaxWidth; Box prevBox = null; var childTransform = transform.WithMaxWidthOffsetBy(maxWidth - left - rightGap, Left, Top); for (var box = FirstBox; box != null; box = box.Next) { box.Layout(childTransform); box.Left = left; top = AdjustTopForMargins(top, transform, prevBox, box); box.Top = top; top += box.Height; prevBox = box; } Height = top + GapBottom(transform); Width = maxWidth; }
public override void Layout(LayoutInfo transform) { var left = GapLeading(transform); var top = GapTop(transform); var rightGap = GapTrailing(transform); var maxWidth = transform.MaxWidth; Box prevBox = null; var childTransform = transform.WithMaxWidthOffsetBy(maxWidth - left - rightGap, Left, Top); for (var box = FirstBox; box != null; box = box.Next) { box.Layout(childTransform); box.Left = left; top = AdjustTopForMargins(top, transform, prevBox, box); box.Top = top; top += box.Height; prevBox = box; } Height = top + GapBottom(transform); Width = maxWidth; }
/// <summary> /// Keep in sync with PileBox.Layout. /// It's important to optimize relayout of DivBox, because they can be very large, and often the height /// of a child does not actually change. Also, this is currently the implementation inherited by root box, /// and the boolean returned from Relayout on the root is ignored; this routine must accomplish all needed /// layout itself. /// We override here rather than on PileBox because non-div piles are typically small and laying out the whole /// thing is not too expensive, while it is harder to predict how changes (e.g., in width) might affect parents. /// The parents of Divs can only be divs. /// </summary> internal override bool Relayout(LayoutInfo transform, Dictionary <Box, Rectangle> fixupMap, LayoutCallbacks lcb) { if (Height == 0) { // brand new box, needs full layout but not invalidate, since it never has been visible. Layout(transform); return(false); } Rectangle oldLocation; if (!fixupMap.TryGetValue(this, out oldLocation)) { return(false); // unchanged, this box does not need to be re-laid out or invalidated. } var left = GapLeading(transform); var top = GapTop(transform); var rightGap = GapTrailing(transform); var maxWidth = 0; int oldHeight = Height; int oldWidth = Width; var topInvalidate = int.MaxValue; int prevBoxOldBottom = 0; var childTransform = transform.WithMaxWidthOffsetBy(transform.MaxWidth - left - rightGap, Left, Top); Box prevBox = null; for (var box = FirstBox; box != null; box = box.Next) { int oldBottom = box.Bottom; // before it is moved or resized (but may be spuriously 0 for new box) bool needsInvalidate = box.Relayout(childTransform, fixupMap, lcb); top = AdjustTopForMargins(top, transform, prevBox, box); // Now figure whether we need to start invalidating based on moved boxes. // If this box moved, we need to invalidate from its top down...or even from its old // top, since the preceding box may have shrunk, without this one changing internally. if (box.Top != top) // test this before we add height to top. { topInvalidate = Math.Min(topInvalidate, Math.Min(top, prevBoxOldBottom)); box.Top = top; } box.Left = left; top += box.Height; maxWidth = Math.Max(maxWidth, box.Width); // assumes our top will not move; if it does, everything gets invalidated, so this is only wasted. if (needsInvalidate) { lcb.InvalidateInRoot(box.InvalidateRect); } // The Math.Max prevents us adjusting it downwards for a new box, which originally had zero top // and height. prevBoxOldBottom = Math.Max(prevBoxOldBottom, oldBottom); prevBox = box; } Height = top + GapBottom(transform); Width = maxWidth + left + rightGap; if (oldWidth != Width) { // The new invalidate rect may not be strictly right, but in the unlikley event that this // box moves, its parent will invalidate its new location again. lcb.InvalidateInRoot(oldLocation); lcb.InvalidateInRoot(InvalidateRect); return(false); } // Even if none of the tops moved, if our height changed, we need to invalidate the difference area. if (Height != oldHeight) { topInvalidate = Math.Min(topInvalidate, Math.Min(Height, oldHeight)); } if (topInvalidate != int.MaxValue) { var bottomInvalidate = Math.Max(Height, oldHeight); // if our top moves, the whole box will get invalidated. Assuming it doesn't, // oldLocation needs it, adjusted for the bit that didn't move at the top, and possibly // to account for getting bigger at the bottom. var invalidate = new Rectangle(oldLocation.Left, oldLocation.Top + topInvalidate, oldLocation.Width, bottomInvalidate - topInvalidate + Box.InvalidateMargin * 2); lcb.InvalidateInRoot(invalidate); } return(false); }
/// <summary> /// Keep in sync with PileBox.Layout. /// It's important to optimize relayout of DivBox, because they can be very large, and often the height /// of a child does not actually change. Also, this is currently the implementation inherited by root box, /// and the boolean returned from Relayout on the root is ignored; this routine must accomplish all needed /// layout itself. /// We override here rather than on PileBox because non-div piles are typically small and laying out the whole /// thing is not too expensive, while it is harder to predict how changes (e.g., in width) might affect parents. /// The parents of Divs can only be divs. /// </summary> internal override bool Relayout(LayoutInfo transform, Dictionary<Box, Rectangle> fixupMap, LayoutCallbacks lcb) { if (Height == 0) { // brand new box, needs full layout but not invalidate, since it never has been visible. Layout(transform); return false; } Rectangle oldLocation; if (!fixupMap.TryGetValue(this, out oldLocation)) return false; // unchanged, this box does not need to be re-laid out or invalidated. var left = GapLeading(transform); var top = GapTop(transform); var rightGap = GapTrailing(transform); var maxWidth = 0; int oldHeight = Height; int oldWidth = Width; var topInvalidate = int.MaxValue; int prevBoxOldBottom = 0; var childTransform = transform.WithMaxWidthOffsetBy(transform.MaxWidth - left - rightGap, Left, Top); Box prevBox = null; for (var box = FirstBox; box != null; box = box.Next) { int oldBottom = box.Bottom; // before it is moved or resized (but may be spuriously 0 for new box) bool needsInvalidate = box.Relayout(childTransform, fixupMap, lcb); top = AdjustTopForMargins(top, transform, prevBox, box); // Now figure whether we need to start invalidating based on moved boxes. // If this box moved, we need to invalidate from its top down...or even from its old // top, since the preceding box may have shrunk, without this one changing internally. if (box.Top != top) // test this before we add height to top. { topInvalidate = Math.Min(topInvalidate, Math.Min(top, prevBoxOldBottom)); box.Top = top; } box.Left = left; top += box.Height; maxWidth = Math.Max(maxWidth, box.Width); // assumes our top will not move; if it does, everything gets invalidated, so this is only wasted. if (needsInvalidate) lcb.InvalidateInRoot(box.InvalidateRect); // The Math.Max prevents us adjusting it downwards for a new box, which originally had zero top // and height. prevBoxOldBottom = Math.Max(prevBoxOldBottom, oldBottom); prevBox = box; } Height = top + GapBottom(transform); Width = maxWidth + left + rightGap; if (oldWidth != Width) { // The new invalidate rect may not be strictly right, but in the unlikley event that this // box moves, its parent will invalidate its new location again. lcb.InvalidateInRoot(oldLocation); lcb.InvalidateInRoot(InvalidateRect); return false; } // Even if none of the tops moved, if our height changed, we need to invalidate the difference area. if (Height != oldHeight) topInvalidate = Math.Min(topInvalidate, Math.Min(Height, oldHeight)); if (topInvalidate != int.MaxValue) { var bottomInvalidate = Math.Max(Height, oldHeight); // if our top moves, the whole box will get invalidated. Assuming it doesn't, // oldLocation needs it, adjusted for the bit that didn't move at the top, and possibly // to account for getting bigger at the bottom. var invalidate = new Rectangle(oldLocation.Left, oldLocation.Top + topInvalidate, oldLocation.Width, bottomInvalidate - topInvalidate + Box.InvalidateMargin*2); lcb.InvalidateInRoot(invalidate); } return false; }
/// <summary> /// This routine and its overrides are used to make sure that the part of the root box between /// yTop and yBottom (measured from the top of the root) can be painted successfully. To facilitate /// the process of replacing a lazy box with real boxes, it is passed the previous box in its /// container (or null if there is none) and returns the next box which the container should /// check is prepared to paint. By default this is simply the next box, but if a lazy box expands /// (part of) itself, it should answer the replacement box. /// Most box classes are always prepared to paint and do nothing. Lazy boxes convert all or part of /// themselves to real boxes if they intersect the specified vertical range (relative to the root as /// a whole). Boxes (currently DivBoxes only) which might contain lazy boxes pass the message on /// to their children, making the appropriate adjustment to the layout transform, just as when /// asking their children to Layout. /// </summary> internal override Box PrepareToPaint(LayoutInfo transform, Box myPrevBox, int dysTop, int dysBottom) { var childMaxWidth = transform.MaxWidth - GapLeading(transform) - GapTrailing(transform); var childTransform = transform.WithMaxWidthOffsetBy(childMaxWidth, Left, Top); Box prevBox = null; for (Box box = FirstBox; box != null; ) { if (transform.YOffset + box.Top > dysBottom) { // nothing further down in this can be visible. Possibly we should return null, // since presumably nothing further down in the container is visible, either. // However, it feels more robust to answer in the usual way and let the container decide // for itself. return Next; } if (transform.YOffset + box.Bottom < dysTop) box = box.Next; // this box is not visible, but a later one might be else box = box.PrepareToPaint(childTransform, prevBox, dysTop, dysBottom); } return Next; }