Line data Source code
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/. */
5 :
6 : #include "nsPopupSetFrame.h"
7 : #include "nsGkAtoms.h"
8 : #include "nsCOMPtr.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"
16 :
17 : nsIFrame*
18 1 : NS_NewPopupSetFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
19 : {
20 1 : return new (aPresShell) nsPopupSetFrame(aContext);
21 : }
22 :
23 1 : NS_IMPL_FRAMEARENA_HELPERS(nsPopupSetFrame)
24 :
25 : void
26 1 : nsPopupSetFrame::Init(nsIContent* aContent,
27 : nsContainerFrame* aParent,
28 : nsIFrame* aPrevInFlow)
29 : {
30 1 : nsBoxFrame::Init(aContent, aParent, aPrevInFlow);
31 :
32 : // Normally the root box is our grandparent, but in case of wrapping
33 : // it can be our great-grandparent.
34 1 : nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
35 1 : if (rootBox) {
36 1 : rootBox->SetPopupSetFrame(this);
37 : }
38 1 : }
39 :
40 : void
41 6 : nsPopupSetFrame::AppendFrames(ChildListID aListID,
42 : nsFrameList& aFrameList)
43 : {
44 6 : if (aListID == kPopupList) {
45 6 : AddPopupFrameList(aFrameList);
46 6 : return;
47 : }
48 0 : nsBoxFrame::AppendFrames(aListID, aFrameList);
49 : }
50 :
51 : void
52 6 : nsPopupSetFrame::RemoveFrame(ChildListID aListID,
53 : nsIFrame* aOldFrame)
54 : {
55 6 : if (aListID == kPopupList) {
56 6 : RemovePopupFrame(aOldFrame);
57 6 : return;
58 : }
59 0 : nsBoxFrame::RemoveFrame(aListID, aOldFrame);
60 : }
61 :
62 : void
63 0 : nsPopupSetFrame::InsertFrames(ChildListID aListID,
64 : nsIFrame* aPrevFrame,
65 : nsFrameList& aFrameList)
66 : {
67 0 : if (aListID == kPopupList) {
68 0 : AddPopupFrameList(aFrameList);
69 0 : return;
70 : }
71 0 : nsBoxFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
72 : }
73 :
74 : void
75 2 : nsPopupSetFrame::SetInitialChildList(ChildListID aListID,
76 : nsFrameList& aChildList)
77 : {
78 2 : if (aListID == kPopupList) {
79 1 : NS_ASSERTION(mPopupList.IsEmpty(),
80 : "SetInitialChildList on non-empty child list");
81 1 : AddPopupFrameList(aChildList);
82 1 : return;
83 : }
84 1 : nsBoxFrame::SetInitialChildList(aListID, aChildList);
85 : }
86 :
87 : const nsFrameList&
88 30 : nsPopupSetFrame::GetChildList(ChildListID aListID) const
89 : {
90 30 : if (kPopupList == aListID) {
91 13 : return mPopupList;
92 : }
93 17 : return nsBoxFrame::GetChildList(aListID);
94 : }
95 :
96 : void
97 30 : nsPopupSetFrame::GetChildLists(nsTArray<ChildList>* aLists) const
98 : {
99 30 : nsBoxFrame::GetChildLists(aLists);
100 30 : mPopupList.AppendIfNonempty(aLists, kPopupList);
101 30 : }
102 :
103 : void
104 0 : nsPopupSetFrame::DestroyFrom(nsIFrame* aDestructRoot)
105 : {
106 0 : mPopupList.DestroyFramesFrom(aDestructRoot);
107 :
108 : // Normally the root box is our grandparent, but in case of wrapping
109 : // it can be our great-grandparent.
110 0 : nsIRootBox *rootBox = nsIRootBox::GetRootBox(PresContext()->GetPresShell());
111 0 : if (rootBox) {
112 0 : rootBox->SetPopupSetFrame(nullptr);
113 : }
114 :
115 0 : nsBoxFrame::DestroyFrom(aDestructRoot);
116 0 : }
117 :
118 : NS_IMETHODIMP
119 3 : nsPopupSetFrame::DoXULLayout(nsBoxLayoutState& aState)
120 : {
121 : // lay us out
122 3 : nsresult rv = nsBoxFrame::DoXULLayout(aState);
123 :
124 : // lay out all of our currently open popups.
125 72 : for (nsFrameList::Enumerator e(mPopupList); !e.AtEnd(); e.Next()) {
126 69 : nsMenuPopupFrame* popupChild = static_cast<nsMenuPopupFrame*>(e.get());
127 69 : popupChild->LayoutPopup(aState, nullptr, nullptr, false);
128 : }
129 :
130 3 : return rv;
131 : }
132 :
133 : void
134 6 : nsPopupSetFrame::RemovePopupFrame(nsIFrame* aPopup)
135 : {
136 6 : NS_PRECONDITION((aPopup->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
137 : aPopup->IsMenuPopupFrame(),
138 : "removing wrong type of frame in popupset's ::popupList");
139 :
140 6 : mPopupList.DestroyFrame(aPopup);
141 6 : }
142 :
143 : void
144 7 : nsPopupSetFrame::AddPopupFrameList(nsFrameList& aPopupFrameList)
145 : {
146 : #ifdef DEBUG
147 36 : for (nsFrameList::Enumerator e(aPopupFrameList); !e.AtEnd(); e.Next()) {
148 29 : NS_ASSERTION((e.get()->GetStateBits() & NS_FRAME_OUT_OF_FLOW) &&
149 : e.get()->IsMenuPopupFrame(),
150 : "adding wrong type of frame in popupset's ::popupList");
151 : }
152 : #endif
153 7 : mPopupList.InsertFrames(nullptr, nullptr, aPopupFrameList);
154 7 : }
|