1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* This Source Code is subject to the terms of the Mozilla Public License
4 * version 2.0 (the "License"). You can obtain a copy of the License at
5 * http://mozilla.org/MPL/2.0/. */
7 /* rendering object for CSS "display: grid | inline-grid" */
9 #include "nsGridContainerFrame.h"
11 #include "nsCSSAnonBoxes.h"
12 #include "nsPresContext.h"
13 #include "nsStyleContext.h"
15 using namespace mozilla
;
17 //----------------------------------------------------------------------
19 // Frame class boilerplate
20 // =======================
22 NS_QUERYFRAME_HEAD(nsGridContainerFrame
)
23 NS_QUERYFRAME_ENTRY(nsGridContainerFrame
)
24 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame
)
26 NS_IMPL_FRAMEARENA_HELPERS(nsGridContainerFrame
)
29 NS_NewGridContainerFrame(nsIPresShell
* aPresShell
,
30 nsStyleContext
* aContext
)
32 return new (aPresShell
) nsGridContainerFrame(aContext
);
36 //----------------------------------------------------------------------
38 // nsGridContainerFrame Method Implementations
39 // ===========================================
42 nsGridContainerFrame::Reflow(nsPresContext
* aPresContext
,
43 nsHTMLReflowMetrics
& aDesiredSize
,
44 const nsHTMLReflowState
& aReflowState
,
45 nsReflowStatus
& aStatus
)
47 DO_GLOBAL_REFLOW_COUNT("nsGridContainerFrame");
48 DISPLAY_REFLOW(aPresContext
, this, aReflowState
, aDesiredSize
, aStatus
);
50 if (IsFrameTreeTooDeep(aReflowState
, aDesiredSize
, aStatus
)) {
55 SanityCheckAnonymousGridItems();
58 LogicalMargin bp
= aReflowState
.ComputedLogicalBorderPadding();
59 bp
.ApplySkipSides(GetLogicalSkipSides());
60 nscoord contentBSize
= GetEffectiveComputedBSize(aReflowState
);
61 if (contentBSize
== NS_AUTOHEIGHT
) {
64 WritingMode wm
= aReflowState
.GetWritingMode();
65 LogicalSize
finalSize(wm
,
66 aReflowState
.ComputedISize() + bp
.IStartEnd(wm
),
67 contentBSize
+ bp
.BStartEnd(wm
));
68 aDesiredSize
.SetSize(wm
, finalSize
);
69 aDesiredSize
.SetOverflowAreasToDesiredBounds();
70 aStatus
= NS_FRAME_COMPLETE
;
71 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
75 nsGridContainerFrame::GetType() const
77 return nsGkAtoms::gridContainerFrame
;
80 #ifdef DEBUG_FRAME_DUMP
82 nsGridContainerFrame::GetFrameName(nsAString
& aResult
) const
84 return MakeFrameName(NS_LITERAL_STRING("GridContainer"), aResult
);
90 FrameWantsToBeInAnonymousGridItem(nsIFrame
* aFrame
)
92 // Note: This needs to match the logic in
93 // nsCSSFrameConstructor::FrameConstructionItem::NeedsAnonFlexOrGridItem()
94 return (aFrame
->IsFrameOfType(nsIFrame::eLineParticipant
) ||
95 nsGkAtoms::placeholderFrame
== aFrame
->GetType());
98 // Debugging method, to let us assert that our anonymous grid items are
99 // set up correctly -- in particular, we assert:
100 // (1) we don't have any inline non-replaced children
101 // (2) we don't have any consecutive anonymous grid items
102 // (3) we don't have any empty anonymous grid items
103 // (4) all children are on the expected child lists
105 nsGridContainerFrame::SanityCheckAnonymousGridItems() const
107 // XXX handle kOverflowContainersList / kExcessOverflowContainersList
108 // when we implement fragmentation?
109 ChildListIDs noCheckLists
= kAbsoluteList
| kFixedList
;
110 ChildListIDs checkLists
= kPrincipalList
| kOverflowList
;
111 for (nsIFrame::ChildListIterator
childLists(this);
112 !childLists
.IsDone(); childLists
.Next()) {
113 if (!checkLists
.Contains(childLists
.CurrentID())) {
114 MOZ_ASSERT(noCheckLists
.Contains(childLists
.CurrentID()),
115 "unexpected non-empty child list");
119 bool prevChildWasAnonGridItem
= false;
120 nsFrameList children
= childLists
.CurrentList();
121 for (nsFrameList::Enumerator
e(children
); !e
.AtEnd(); e
.Next()) {
122 nsIFrame
* child
= e
.get();
123 MOZ_ASSERT(!FrameWantsToBeInAnonymousGridItem(child
),
124 "frame wants to be inside an anonymous grid item, "
126 if (child
->StyleContext()->GetPseudo() ==
127 nsCSSAnonBoxes::anonymousGridItem
) {
129 XXX haven't decided yet whether to reorder children or not.
130 XXX If we do, we want this assertion instead of the one below.
131 MOZ_ASSERT(!prevChildWasAnonGridItem ||
132 HasAnyStateBits(NS_STATE_GRID_CHILDREN_REORDERED),
133 "two anon grid items in a row (shouldn't happen, unless our "
134 "children have been reordered with the 'order' property)");
136 MOZ_ASSERT(!prevChildWasAnonGridItem
, "two anon grid items in a row");
137 nsIFrame
* firstWrappedChild
= child
->GetFirstPrincipalChild();
138 MOZ_ASSERT(firstWrappedChild
,
139 "anonymous grid item is empty (shouldn't happen)");
140 prevChildWasAnonGridItem
= true;
142 prevChildWasAnonGridItem
= false;