Bug 1492664 - vendor taskcluster-urls; r=gps
[gecko.git] / layout / xul / nsBox.cpp
blobae834de91d8584c73188594230988157d363ae40
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "nsBoxLayoutState.h"
8 #include "nsBox.h"
9 #include "nsBoxFrame.h"
10 #include "nsDOMAttributeMap.h"
11 #include "nsPresContext.h"
12 #include "nsCOMPtr.h"
13 #include "nsIContent.h"
14 #include "nsContainerFrame.h"
15 #include "nsNameSpaceManager.h"
16 #include "nsGkAtoms.h"
17 #include "nsITheme.h"
18 #include "nsIServiceManager.h"
19 #include "nsBoxLayout.h"
20 #include "FrameLayerBuilder.h"
21 #include "mozilla/dom/Attr.h"
22 #include "mozilla/dom/Element.h"
23 #include <algorithm>
25 using namespace mozilla;
27 nsresult nsBox::BeginXULLayout(nsBoxLayoutState& aState) {
28 // mark ourselves as dirty so no child under us
29 // can post an incremental layout.
30 // XXXldb Is this still needed?
31 AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
33 if (GetStateBits() & NS_FRAME_IS_DIRTY) {
34 // If the parent is dirty, all the children are dirty (ReflowInput
35 // does this too).
36 nsIFrame* box;
37 for (box = GetChildXULBox(this); box; box = GetNextXULBox(box))
38 box->AddStateBits(NS_FRAME_IS_DIRTY);
41 // Another copy-over from ReflowInput.
42 // Since we are in reflow, we don't need to store these properties anymore.
43 DeleteProperty(UsedBorderProperty());
44 DeleteProperty(UsedPaddingProperty());
45 DeleteProperty(UsedMarginProperty());
47 return NS_OK;
50 NS_IMETHODIMP
51 nsBox::DoXULLayout(nsBoxLayoutState& aState) { return NS_OK; }
53 nsresult nsBox::EndXULLayout(nsBoxLayoutState& aState) {
54 return SyncLayout(aState);
57 bool nsBox::gGotTheme = false;
58 StaticRefPtr<nsITheme> nsBox::gTheme;
60 nsBox::nsBox(ClassID aID) : nsIFrame(aID) {
61 MOZ_COUNT_CTOR(nsBox);
62 if (!gGotTheme) {
63 gTheme = do_GetNativeTheme();
64 if (gTheme) {
65 gGotTheme = true;
70 nsBox::~nsBox() {
71 // NOTE: This currently doesn't get called for |nsBoxToBlockAdaptor|
72 // objects, so don't rely on putting anything here.
73 MOZ_COUNT_DTOR(nsBox);
76 /* static */ void nsBox::Shutdown() {
77 gGotTheme = false;
78 gTheme = nullptr;
81 nsresult nsBox::XULRelayoutChildAtOrdinal(nsIFrame* aChild) { return NS_OK; }
83 nsresult nsIFrame::GetXULClientRect(nsRect& aClientRect) {
84 aClientRect = mRect;
85 aClientRect.MoveTo(0, 0);
87 nsMargin borderPadding;
88 GetXULBorderAndPadding(borderPadding);
90 aClientRect.Deflate(borderPadding);
92 if (aClientRect.width < 0) aClientRect.width = 0;
94 if (aClientRect.height < 0) aClientRect.height = 0;
96 return NS_OK;
99 void nsBox::SetXULBounds(nsBoxLayoutState& aState, const nsRect& aRect,
100 bool aRemoveOverflowAreas) {
101 nsRect rect(mRect);
103 uint32_t flags = GetXULLayoutFlags();
105 uint32_t stateFlags = aState.LayoutFlags();
107 flags |= stateFlags;
109 if ((flags & NS_FRAME_NO_MOVE_FRAME) == NS_FRAME_NO_MOVE_FRAME)
110 SetSize(aRect.Size());
111 else
112 SetRect(aRect);
114 // Nuke the overflow area. The caller is responsible for restoring
115 // it if necessary.
116 if (aRemoveOverflowAreas) {
117 // remove the previously stored overflow area
118 ClearOverflowRects();
121 if (!(flags & NS_FRAME_NO_MOVE_VIEW)) {
122 nsContainerFrame::PositionFrameView(this);
123 if ((rect.x != aRect.x) || (rect.y != aRect.y))
124 nsContainerFrame::PositionChildViews(this);
128 nsresult nsIFrame::GetXULBorderAndPadding(nsMargin& aBorderAndPadding) {
129 aBorderAndPadding.SizeTo(0, 0, 0, 0);
130 nsresult rv = GetXULBorder(aBorderAndPadding);
131 if (NS_FAILED(rv)) return rv;
133 nsMargin padding;
134 rv = GetXULPadding(padding);
135 if (NS_FAILED(rv)) return rv;
137 aBorderAndPadding += padding;
139 return rv;
142 nsresult nsBox::GetXULBorder(nsMargin& aMargin) {
143 aMargin.SizeTo(0, 0, 0, 0);
145 const nsStyleDisplay* disp = StyleDisplay();
146 if (disp->HasAppearance() && gTheme) {
147 // Go to the theme for the border.
148 nsPresContext* context = PresContext();
149 if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) {
150 LayoutDeviceIntMargin margin = gTheme->GetWidgetBorder(
151 context->DeviceContext(), this, disp->mAppearance);
152 aMargin =
153 LayoutDevicePixel::ToAppUnits(margin, context->AppUnitsPerDevPixel());
154 return NS_OK;
158 aMargin = StyleBorder()->GetComputedBorder();
160 return NS_OK;
163 nsresult nsBox::GetXULPadding(nsMargin& aPadding) {
164 const nsStyleDisplay* disp = StyleDisplay();
165 if (disp->HasAppearance() && gTheme) {
166 // Go to the theme for the padding.
167 nsPresContext* context = PresContext();
168 if (gTheme->ThemeSupportsWidget(context, this, disp->mAppearance)) {
169 LayoutDeviceIntMargin padding;
170 bool useThemePadding = gTheme->GetWidgetPadding(
171 context->DeviceContext(), this, disp->mAppearance, &padding);
172 if (useThemePadding) {
173 aPadding = LayoutDevicePixel::ToAppUnits(
174 padding, context->AppUnitsPerDevPixel());
175 return NS_OK;
180 aPadding.SizeTo(0, 0, 0, 0);
181 StylePadding()->GetPadding(aPadding);
183 return NS_OK;
186 nsresult nsBox::GetXULMargin(nsMargin& aMargin) {
187 aMargin.SizeTo(0, 0, 0, 0);
188 StyleMargin()->GetMargin(aMargin);
190 return NS_OK;
193 void nsBox::SizeNeedsRecalc(nsSize& aSize) {
194 aSize.width = -1;
195 aSize.height = -1;
198 void nsBox::CoordNeedsRecalc(nscoord& aFlex) { aFlex = -1; }
200 bool nsBox::DoesNeedRecalc(const nsSize& aSize) {
201 return (aSize.width == -1 || aSize.height == -1);
204 bool nsBox::DoesNeedRecalc(nscoord aCoord) { return (aCoord == -1); }
206 nsSize nsBox::GetXULPrefSize(nsBoxLayoutState& aState) {
207 NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
209 nsSize pref(0, 0);
210 DISPLAY_PREF_SIZE(this, pref);
212 if (IsXULCollapsed()) return pref;
214 AddBorderAndPadding(pref);
215 bool widthSet, heightSet;
216 nsIFrame::AddXULPrefSize(this, pref, widthSet, heightSet);
218 nsSize minSize = GetXULMinSize(aState);
219 nsSize maxSize = GetXULMaxSize(aState);
220 return BoundsCheck(minSize, pref, maxSize);
223 nsSize nsBox::GetXULMinSize(nsBoxLayoutState& aState) {
224 NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
226 nsSize min(0, 0);
227 DISPLAY_MIN_SIZE(this, min);
229 if (IsXULCollapsed()) return min;
231 AddBorderAndPadding(min);
232 bool widthSet, heightSet;
233 nsIFrame::AddXULMinSize(aState, this, min, widthSet, heightSet);
234 return min;
237 nsSize nsBox::GetXULMinSizeForScrollArea(nsBoxLayoutState& aBoxLayoutState) {
238 return nsSize(0, 0);
241 nsSize nsBox::GetXULMaxSize(nsBoxLayoutState& aState) {
242 NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
244 nsSize maxSize(NS_INTRINSICSIZE, NS_INTRINSICSIZE);
245 DISPLAY_MAX_SIZE(this, maxSize);
247 if (IsXULCollapsed()) return maxSize;
249 AddBorderAndPadding(maxSize);
250 bool widthSet, heightSet;
251 nsIFrame::AddXULMaxSize(this, maxSize, widthSet, heightSet);
252 return maxSize;
255 nscoord nsBox::GetXULFlex() {
256 nscoord flex = 0;
258 nsIFrame::AddXULFlex(this, flex);
260 return flex;
263 uint32_t nsIFrame::GetXULOrdinal() {
264 uint32_t ordinal = StyleXUL()->mBoxOrdinal;
266 // When present, attribute value overrides CSS.
267 nsIContent* content = GetContent();
268 if (content && content->IsXULElement()) {
269 nsresult error;
270 nsAutoString value;
272 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::ordinal, value);
273 if (!value.IsEmpty()) {
274 ordinal = value.ToInteger(&error);
278 return ordinal;
281 nscoord nsBox::GetXULBoxAscent(nsBoxLayoutState& aState) {
282 if (IsXULCollapsed()) return 0;
284 return GetXULPrefSize(aState).height;
287 bool nsBox::IsXULCollapsed() {
288 return StyleVisibility()->mVisible == NS_STYLE_VISIBILITY_COLLAPSE;
291 nsresult nsIFrame::XULLayout(nsBoxLayoutState& aState) {
292 NS_ASSERTION(aState.GetRenderingContext(), "must have rendering context");
294 nsBox* box = static_cast<nsBox*>(this);
295 DISPLAY_LAYOUT(box);
297 box->BeginXULLayout(aState);
299 box->DoXULLayout(aState);
301 box->EndXULLayout(aState);
303 return NS_OK;
306 bool nsBox::DoesClipChildren() {
307 const nsStyleDisplay* display = StyleDisplay();
308 NS_ASSERTION(
309 (display->mOverflowY == StyleOverflow::MozHiddenUnscrollable) ==
310 (display->mOverflowX == StyleOverflow::MozHiddenUnscrollable),
311 "If one overflow is -moz-hidden-unscrollable, the other should be too");
312 return display->mOverflowX == StyleOverflow::MozHiddenUnscrollable;
315 nsresult nsBox::SyncLayout(nsBoxLayoutState& aState) {
317 if (IsXULCollapsed()) {
318 CollapseChild(aState, this, true);
319 return NS_OK;
323 if (GetStateBits() & NS_FRAME_IS_DIRTY) XULRedraw(aState);
325 RemoveStateBits(NS_FRAME_HAS_DIRTY_CHILDREN | NS_FRAME_IS_DIRTY |
326 NS_FRAME_FIRST_REFLOW | NS_FRAME_IN_REFLOW);
328 nsPresContext* presContext = aState.PresContext();
330 uint32_t flags = GetXULLayoutFlags();
332 uint32_t stateFlags = aState.LayoutFlags();
334 flags |= stateFlags;
336 nsRect visualOverflow;
338 if (ComputesOwnOverflowArea()) {
339 visualOverflow = GetVisualOverflowRect();
340 } else {
341 nsRect rect(nsPoint(0, 0), GetSize());
342 nsOverflowAreas overflowAreas(rect, rect);
343 if (!DoesClipChildren() && !IsXULCollapsed()) {
344 // See if our child frames caused us to overflow after being laid
345 // out. If so, store the overflow area. This normally can't happen
346 // in XUL, but it can happen with the CSS 'outline' property and
347 // possibly with other exotic stuff (e.g. relatively positioned
348 // frames in HTML inside XUL).
349 nsLayoutUtils::UnionChildOverflow(this, overflowAreas);
352 FinishAndStoreOverflow(overflowAreas, GetSize());
353 visualOverflow = overflowAreas.VisualOverflow();
356 nsView* view = GetView();
357 if (view) {
358 // Make sure the frame's view is properly sized and positioned and has
359 // things like opacity correct
360 nsContainerFrame::SyncFrameViewAfterReflow(presContext, this, view,
361 visualOverflow, flags);
364 return NS_OK;
367 nsresult nsIFrame::XULRedraw(nsBoxLayoutState& aState) {
368 if (aState.PaintingDisabled()) return NS_OK;
370 // nsStackLayout, at least, expects us to repaint descendants even
371 // if a damage rect is provided
372 InvalidateFrameSubtree();
374 return NS_OK;
377 bool nsIFrame::AddXULPrefSize(nsIFrame* aBox, nsSize& aSize, bool& aWidthSet,
378 bool& aHeightSet) {
379 aWidthSet = false;
380 aHeightSet = false;
382 // add in the css min, max, pref
383 const nsStylePosition* position = aBox->StylePosition();
385 // see if the width or height was specifically set
386 // XXX Handle eStyleUnit_Enumerated?
387 // (Handling the eStyleUnit_Enumerated types requires
388 // GetXULPrefSize/GetXULMinSize methods that don't consider
389 // (min-/max-/)(width/height) properties.)
390 const nsStyleCoord& width = position->mWidth;
391 if (width.GetUnit() == eStyleUnit_Coord) {
392 aSize.width = width.GetCoordValue();
393 aWidthSet = true;
394 } else if (width.IsCalcUnit()) {
395 if (!width.CalcHasPercent()) {
396 // pass 0 for percentage basis since we know there are no %s
397 aSize.width = width.ComputeComputedCalc(0);
398 if (aSize.width < 0) aSize.width = 0;
399 aWidthSet = true;
403 const nsStyleCoord& height = position->mHeight;
404 if (height.GetUnit() == eStyleUnit_Coord) {
405 aSize.height = height.GetCoordValue();
406 aHeightSet = true;
407 } else if (height.IsCalcUnit()) {
408 if (!height.CalcHasPercent()) {
409 // pass 0 for percentage basis since we know there are no %s
410 aSize.height = height.ComputeComputedCalc(0);
411 if (aSize.height < 0) aSize.height = 0;
412 aHeightSet = true;
416 nsIContent* content = aBox->GetContent();
417 // ignore 'height' and 'width' attributes if the actual element is not XUL
418 // For example, we might be magic XUL frames whose primary content is an HTML
419 // <select>
420 if (content && content->IsXULElement()) {
421 nsAutoString value;
422 nsresult error;
424 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::width, value);
425 if (!value.IsEmpty()) {
426 value.Trim("%");
428 aSize.width = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
429 aWidthSet = true;
432 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::height, value);
433 if (!value.IsEmpty()) {
434 value.Trim("%");
436 aSize.height =
437 nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
438 aHeightSet = true;
442 return (aWidthSet && aHeightSet);
445 // This returns the scrollbar width we want to use when either native
446 // theme is disabled, or the native theme claims that it doesn't support
447 // scrollbar.
448 static nscoord GetScrollbarWidthNoTheme(nsIFrame* aBox) {
449 ComputedStyle* scrollbarStyle = nsLayoutUtils::StyleForScrollbar(aBox);
450 switch (scrollbarStyle->StyleUIReset()->mScrollbarWidth) {
451 default:
452 case StyleScrollbarWidth::Auto:
453 return 12 * AppUnitsPerCSSPixel();
454 case StyleScrollbarWidth::Thin:
455 return 6 * AppUnitsPerCSSPixel();
456 case StyleScrollbarWidth::None:
457 return 0;
461 bool nsIFrame::AddXULMinSize(nsBoxLayoutState& aState, nsIFrame* aBox,
462 nsSize& aSize, bool& aWidthSet, bool& aHeightSet) {
463 aWidthSet = false;
464 aHeightSet = false;
466 bool canOverride = true;
468 // See if a native theme wants to supply a minimum size.
469 const nsStyleDisplay* display = aBox->StyleDisplay();
470 if (display->HasAppearance()) {
471 nsITheme* theme = aState.PresContext()->GetTheme();
472 if (theme && theme->ThemeSupportsWidget(aState.PresContext(), aBox,
473 display->mAppearance)) {
474 LayoutDeviceIntSize size;
475 theme->GetMinimumWidgetSize(aState.PresContext(), aBox,
476 display->mAppearance, &size, &canOverride);
477 if (size.width) {
478 aSize.width = aState.PresContext()->DevPixelsToAppUnits(size.width);
479 aWidthSet = true;
481 if (size.height) {
482 aSize.height = aState.PresContext()->DevPixelsToAppUnits(size.height);
483 aHeightSet = true;
485 } else {
486 switch (display->mAppearance) {
487 case StyleAppearance::ScrollbarVertical:
488 aSize.width = GetScrollbarWidthNoTheme(aBox);
489 aWidthSet = true;
490 break;
491 case StyleAppearance::ScrollbarHorizontal:
492 aSize.height = GetScrollbarWidthNoTheme(aBox);
493 aHeightSet = true;
494 break;
495 default:
496 break;
501 // add in the css min, max, pref
502 const nsStylePosition* position = aBox->StylePosition();
504 // same for min size. Unfortunately min size is always set to 0. So for now
505 // we will assume 0 (as a coord) means not set.
506 const nsStyleCoord& minWidth = position->mMinWidth;
507 if ((minWidth.GetUnit() == eStyleUnit_Coord &&
508 minWidth.GetCoordValue() != 0) ||
509 (minWidth.IsCalcUnit() && !minWidth.CalcHasPercent())) {
510 nscoord min = minWidth.ComputeCoordPercentCalc(0);
511 if (!aWidthSet || (min > aSize.width && canOverride)) {
512 aSize.width = min;
513 aWidthSet = true;
515 } else if (minWidth.GetUnit() == eStyleUnit_Percent) {
516 NS_ASSERTION(minWidth.GetPercentValue() == 0.0f,
517 "Non-zero percentage values not currently supported");
518 aSize.width = 0;
519 aWidthSet = true; // FIXME: should we really do this for
520 // nonzero values?
522 // XXX Handle eStyleUnit_Enumerated?
523 // (Handling the eStyleUnit_Enumerated types requires
524 // GetXULPrefSize/GetXULMinSize methods that don't consider
525 // (min-/max-/)(width/height) properties.
526 // calc() with percentage is treated like '0' (unset)
528 const nsStyleCoord& minHeight = position->mMinHeight;
529 if ((minHeight.GetUnit() == eStyleUnit_Coord &&
530 minHeight.GetCoordValue() != 0) ||
531 (minHeight.IsCalcUnit() && !minHeight.CalcHasPercent())) {
532 nscoord min = minHeight.ComputeCoordPercentCalc(0);
533 if (!aHeightSet || (min > aSize.height && canOverride)) {
534 aSize.height = min;
535 aHeightSet = true;
537 } else if (minHeight.GetUnit() == eStyleUnit_Percent) {
538 NS_ASSERTION(position->mMinHeight.GetPercentValue() == 0.0f,
539 "Non-zero percentage values not currently supported");
540 aSize.height = 0;
541 aHeightSet = true; // FIXME: should we really do this for
542 // nonzero values?
544 // calc() with percentage is treated like '0' (unset)
546 nsIContent* content = aBox->GetContent();
547 if (content && content->IsXULElement()) {
548 nsAutoString value;
549 nsresult error;
551 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::minwidth,
552 value);
553 if (!value.IsEmpty()) {
554 value.Trim("%");
556 nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
557 if (val > aSize.width) aSize.width = val;
558 aWidthSet = true;
561 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::minheight,
562 value);
563 if (!value.IsEmpty()) {
564 value.Trim("%");
566 nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
567 if (val > aSize.height) aSize.height = val;
569 aHeightSet = true;
573 return (aWidthSet && aHeightSet);
576 bool nsIFrame::AddXULMaxSize(nsIFrame* aBox, nsSize& aSize, bool& aWidthSet,
577 bool& aHeightSet) {
578 aWidthSet = false;
579 aHeightSet = false;
581 // add in the css min, max, pref
582 const nsStylePosition* position = aBox->StylePosition();
584 // and max
585 // see if the width or height was specifically set
586 // XXX Handle eStyleUnit_Enumerated?
587 // (Handling the eStyleUnit_Enumerated types requires
588 // GetXULPrefSize/GetXULMinSize methods that don't consider
589 // (min-/max-/)(width/height) properties.)
590 const nsStyleCoord maxWidth = position->mMaxWidth;
591 if (maxWidth.ConvertsToLength()) {
592 aSize.width = maxWidth.ComputeCoordPercentCalc(0);
593 aWidthSet = true;
595 // percentages and calc() with percentages are treated like 'none'
597 const nsStyleCoord& maxHeight = position->mMaxHeight;
598 if (maxHeight.ConvertsToLength()) {
599 aSize.height = maxHeight.ComputeCoordPercentCalc(0);
600 aHeightSet = true;
602 // percentages and calc() with percentages are treated like 'none'
604 nsIContent* content = aBox->GetContent();
605 if (content && content->IsXULElement()) {
606 nsAutoString value;
607 nsresult error;
609 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::maxwidth,
610 value);
611 if (!value.IsEmpty()) {
612 value.Trim("%");
614 nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
615 aSize.width = val;
616 aWidthSet = true;
619 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::maxheight,
620 value);
621 if (!value.IsEmpty()) {
622 value.Trim("%");
624 nscoord val = nsPresContext::CSSPixelsToAppUnits(value.ToInteger(&error));
625 aSize.height = val;
627 aHeightSet = true;
631 return (aWidthSet || aHeightSet);
634 bool nsIFrame::AddXULFlex(nsIFrame* aBox, nscoord& aFlex) {
635 bool flexSet = false;
637 // get the flexibility
638 aFlex = aBox->StyleXUL()->mBoxFlex;
640 // attribute value overrides CSS
641 nsIContent* content = aBox->GetContent();
642 if (content && content->IsXULElement()) {
643 nsresult error;
644 nsAutoString value;
646 content->AsElement()->GetAttr(kNameSpaceID_None, nsGkAtoms::flex, value);
647 if (!value.IsEmpty()) {
648 value.Trim("%");
649 aFlex = value.ToInteger(&error);
650 flexSet = true;
654 if (aFlex < 0) aFlex = 0;
655 if (aFlex >= nscoord_MAX) aFlex = nscoord_MAX - 1;
657 return flexSet || aFlex > 0;
660 void nsBox::AddBorderAndPadding(nsSize& aSize) {
661 AddBorderAndPadding(this, aSize);
664 void nsBox::AddBorderAndPadding(nsIFrame* aBox, nsSize& aSize) {
665 nsMargin borderPadding(0, 0, 0, 0);
666 aBox->GetXULBorderAndPadding(borderPadding);
667 AddMargin(aSize, borderPadding);
670 void nsBox::AddMargin(nsIFrame* aChild, nsSize& aSize) {
671 nsMargin margin(0, 0, 0, 0);
672 aChild->GetXULMargin(margin);
673 AddMargin(aSize, margin);
676 void nsBox::AddMargin(nsSize& aSize, const nsMargin& aMargin) {
677 if (aSize.width != NS_INTRINSICSIZE)
678 aSize.width += aMargin.left + aMargin.right;
680 if (aSize.height != NS_INTRINSICSIZE)
681 aSize.height += aMargin.top + aMargin.bottom;
684 nscoord nsBox::BoundsCheck(nscoord aMin, nscoord aPref, nscoord aMax) {
685 if (aPref > aMax) aPref = aMax;
687 if (aPref < aMin) aPref = aMin;
689 return aPref;
692 nsSize nsBox::BoundsCheckMinMax(const nsSize& aMinSize,
693 const nsSize& aMaxSize) {
694 return nsSize(std::max(aMaxSize.width, aMinSize.width),
695 std::max(aMaxSize.height, aMinSize.height));
698 nsSize nsBox::BoundsCheck(const nsSize& aMinSize, const nsSize& aPrefSize,
699 const nsSize& aMaxSize) {
700 return nsSize(
701 BoundsCheck(aMinSize.width, aPrefSize.width, aMaxSize.width),
702 BoundsCheck(aMinSize.height, aPrefSize.height, aMaxSize.height));
705 /*static*/ nsIFrame* nsBox::GetChildXULBox(const nsIFrame* aFrame) {
706 // box layout ends at box-wrapped frames, so don't allow these frames
707 // to report child boxes.
708 return aFrame->IsXULBoxFrame() ? aFrame->PrincipalChildList().FirstChild()
709 : nullptr;
712 /*static*/ nsIFrame* nsBox::GetNextXULBox(const nsIFrame* aFrame) {
713 return aFrame->GetParent() && aFrame->GetParent()->IsXULBoxFrame()
714 ? aFrame->GetNextSibling()
715 : nullptr;
718 /*static*/ nsIFrame* nsBox::GetParentXULBox(const nsIFrame* aFrame) {
719 return aFrame->GetParent() && aFrame->GetParent()->IsXULBoxFrame()
720 ? aFrame->GetParent()
721 : nullptr;