1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsPopupSetFrame.h"
9 #include "nsIContent.h"
10 #include "nsPresContext.h"
11 #include "nsStyleContext.h"
12 #include "nsBoxLayoutState.h"
13 #include "nsIScrollableFrame.h"
14 #include "nsIRootBox.h"
15 #include "nsMenuPopupFrame.h"
18 NS_NewPopupSetFrame(nsIPresShell
* aPresShell
, nsStyleContext
* aContext
)
20 return new (aPresShell
) nsPopupSetFrame(aContext
);
23 NS_IMPL_FRAMEARENA_HELPERS(nsPopupSetFrame
)
26 nsPopupSetFrame::Init(nsIContent
* aContent
,
27 nsContainerFrame
* aParent
,
28 nsIFrame
* aPrevInFlow
)
30 nsBoxFrame::Init(aContent
, aParent
, aPrevInFlow
);
32 // Normally the root box is our grandparent, but in case of wrapping
33 // it can be our great-grandparent.
34 nsIRootBox
*rootBox
= nsIRootBox::GetRootBox(PresContext()->GetPresShell());
36 rootBox
->SetPopupSetFrame(this);
41 nsPopupSetFrame::GetType() const
43 return nsGkAtoms::popupSetFrame
;
47 nsPopupSetFrame::AppendFrames(ChildListID aListID
,
48 nsFrameList
& aFrameList
)
50 if (aListID
== kPopupList
) {
51 AddPopupFrameList(aFrameList
);
54 nsBoxFrame::AppendFrames(aListID
, aFrameList
);
58 nsPopupSetFrame::RemoveFrame(ChildListID aListID
,
61 if (aListID
== kPopupList
) {
62 RemovePopupFrame(aOldFrame
);
65 nsBoxFrame::RemoveFrame(aListID
, aOldFrame
);
69 nsPopupSetFrame::InsertFrames(ChildListID aListID
,
71 nsFrameList
& aFrameList
)
73 if (aListID
== kPopupList
) {
74 AddPopupFrameList(aFrameList
);
77 nsBoxFrame::InsertFrames(aListID
, aPrevFrame
, aFrameList
);
81 nsPopupSetFrame::SetInitialChildList(ChildListID aListID
,
82 nsFrameList
& aChildList
)
84 if (aListID
== kPopupList
) {
85 NS_ASSERTION(mPopupList
.IsEmpty(),
86 "SetInitialChildList on non-empty child list");
87 AddPopupFrameList(aChildList
);
90 nsBoxFrame::SetInitialChildList(aListID
, aChildList
);
94 nsPopupSetFrame::GetChildList(ChildListID aListID
) const
96 if (kPopupList
== aListID
) {
99 return nsBoxFrame::GetChildList(aListID
);
103 nsPopupSetFrame::GetChildLists(nsTArray
<ChildList
>* aLists
) const
105 nsBoxFrame::GetChildLists(aLists
);
106 mPopupList
.AppendIfNonempty(aLists
, kPopupList
);
110 nsPopupSetFrame::DestroyFrom(nsIFrame
* aDestructRoot
)
112 mPopupList
.DestroyFramesFrom(aDestructRoot
);
114 // Normally the root box is our grandparent, but in case of wrapping
115 // it can be our great-grandparent.
116 nsIRootBox
*rootBox
= nsIRootBox::GetRootBox(PresContext()->GetPresShell());
118 rootBox
->SetPopupSetFrame(nullptr);
121 nsBoxFrame::DestroyFrom(aDestructRoot
);
125 nsPopupSetFrame::DoLayout(nsBoxLayoutState
& aState
)
128 nsresult rv
= nsBoxFrame::DoLayout(aState
);
130 // lay out all of our currently open popups.
131 for (nsFrameList::Enumerator
e(mPopupList
); !e
.AtEnd(); e
.Next()) {
132 nsMenuPopupFrame
* popupChild
= static_cast<nsMenuPopupFrame
*>(e
.get());
133 popupChild
->LayoutPopup(aState
, nullptr, nullptr, false);
140 nsPopupSetFrame::RemovePopupFrame(nsIFrame
* aPopup
)
142 NS_PRECONDITION((aPopup
->GetStateBits() & NS_FRAME_OUT_OF_FLOW
) &&
143 aPopup
->GetType() == nsGkAtoms::menuPopupFrame
,
144 "removing wrong type of frame in popupset's ::popupList");
146 mPopupList
.DestroyFrame(aPopup
);
150 nsPopupSetFrame::AddPopupFrameList(nsFrameList
& aPopupFrameList
)
153 for (nsFrameList::Enumerator
e(aPopupFrameList
); !e
.AtEnd(); e
.Next()) {
154 NS_ASSERTION((e
.get()->GetStateBits() & NS_FRAME_OUT_OF_FLOW
) &&
155 e
.get()->GetType() == nsGkAtoms::menuPopupFrame
,
156 "adding wrong type of frame in popupset's ::popupList");
159 mPopupList
.InsertFrames(nullptr, nullptr, aPopupFrameList
);