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