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 "mozilla/dom/ListBoxObject.h"
7 : #include "nsCOMPtr.h"
8 : #include "nsIFrame.h"
9 : #include "nsGkAtoms.h"
10 : #include "nsIScrollableFrame.h"
11 : #include "nsListBoxBodyFrame.h"
12 : #include "ChildIterator.h"
13 : #include "mozilla/dom/Element.h"
14 : #include "mozilla/dom/ListBoxObjectBinding.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 :
19 0 : NS_IMPL_ISUPPORTS_INHERITED(ListBoxObject, BoxObject, nsIListBoxObject,
20 : nsPIListBoxObject)
21 :
22 0 : ListBoxObject::ListBoxObject()
23 0 : : mListBoxBody(nullptr)
24 : {
25 0 : }
26 :
27 0 : ListBoxObject::~ListBoxObject()
28 : {
29 0 : }
30 :
31 0 : JSObject* ListBoxObject::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
32 : {
33 0 : return ListBoxObjectBinding::Wrap(aCx, this, aGivenProto);
34 : }
35 :
36 : // nsIListBoxObject
37 : NS_IMETHODIMP
38 0 : ListBoxObject::GetRowCount(int32_t *aResult)
39 : {
40 0 : *aResult = GetRowCount();
41 0 : return NS_OK;
42 : }
43 :
44 : NS_IMETHODIMP
45 0 : ListBoxObject::GetItemAtIndex(int32_t index, nsIDOMElement **_retval)
46 : {
47 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
48 0 : if (body) {
49 0 : return body->GetItemAtIndex(index, _retval);
50 : }
51 0 : return NS_OK;
52 : }
53 :
54 : NS_IMETHODIMP
55 0 : ListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, int32_t *aResult)
56 : {
57 0 : *aResult = 0;
58 :
59 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
60 0 : if (body) {
61 0 : return body->GetIndexOfItem(aElement, aResult);
62 : }
63 0 : return NS_OK;
64 : }
65 :
66 : // ListBoxObject
67 :
68 : int32_t
69 0 : ListBoxObject::GetRowCount()
70 : {
71 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
72 0 : if (body) {
73 0 : return body->GetRowCount();
74 : }
75 0 : return 0;
76 : }
77 :
78 : int32_t
79 0 : ListBoxObject::GetRowHeight()
80 : {
81 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
82 0 : if (body) {
83 0 : return body->GetRowHeightPixels();
84 : }
85 0 : return 0;
86 : }
87 :
88 : int32_t
89 0 : ListBoxObject::GetNumberOfVisibleRows()
90 : {
91 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
92 0 : if (body) {
93 0 : return body->GetNumberOfVisibleRows();
94 : }
95 0 : return 0;
96 : }
97 :
98 : int32_t
99 0 : ListBoxObject::GetIndexOfFirstVisibleRow()
100 : {
101 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
102 0 : if (body) {
103 0 : return body->GetIndexOfFirstVisibleRow();
104 : }
105 0 : return 0;
106 : }
107 :
108 : void
109 0 : ListBoxObject::EnsureIndexIsVisible(int32_t aRowIndex)
110 : {
111 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
112 0 : if (body) {
113 0 : body->EnsureIndexIsVisible(aRowIndex);
114 : }
115 0 : }
116 :
117 : void
118 0 : ListBoxObject::ScrollToIndex(int32_t aRowIndex)
119 : {
120 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
121 0 : if (body) {
122 0 : body->ScrollToIndex(aRowIndex);
123 : }
124 0 : }
125 :
126 : void
127 0 : ListBoxObject::ScrollByLines(int32_t aNumLines)
128 : {
129 0 : nsListBoxBodyFrame* body = GetListBoxBody(true);
130 0 : if (body) {
131 0 : body->ScrollByLines(aNumLines);
132 : }
133 0 : }
134 :
135 : already_AddRefed<Element>
136 0 : ListBoxObject::GetItemAtIndex(int32_t index)
137 : {
138 0 : nsCOMPtr<nsIDOMElement> el;
139 0 : GetItemAtIndex(index, getter_AddRefs(el));
140 0 : nsCOMPtr<Element> ret(do_QueryInterface(el));
141 0 : return ret.forget();
142 : }
143 :
144 : int32_t
145 0 : ListBoxObject::GetIndexOfItem(Element& aElement)
146 : {
147 : int32_t ret;
148 0 : nsCOMPtr<nsIDOMElement> el(do_QueryInterface(&aElement));
149 0 : GetIndexOfItem(el, &ret);
150 0 : return ret;
151 : }
152 :
153 : //////////////////////
154 :
155 : static nsIContent*
156 0 : FindBodyContent(nsIContent* aParent)
157 : {
158 0 : if (aParent->IsXULElement(nsGkAtoms::listboxbody)) {
159 0 : return aParent;
160 : }
161 :
162 0 : mozilla::dom::FlattenedChildIterator iter(aParent);
163 0 : for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
164 0 : nsIContent* result = FindBodyContent(child);
165 0 : if (result) {
166 0 : return result;
167 : }
168 : }
169 :
170 0 : return nullptr;
171 : }
172 :
173 : nsListBoxBodyFrame*
174 0 : ListBoxObject::GetListBoxBody(bool aFlush)
175 : {
176 0 : if (mListBoxBody) {
177 0 : return mListBoxBody;
178 : }
179 :
180 0 : nsIPresShell* shell = GetPresShell(false);
181 0 : if (!shell) {
182 0 : return nullptr;
183 : }
184 :
185 0 : nsIFrame* frame = aFlush ?
186 0 : GetFrame(false) /* does FlushType::Frames */ :
187 0 : mContent->GetPrimaryFrame();
188 0 : if (!frame) {
189 0 : return nullptr;
190 : }
191 :
192 : // Iterate over our content model children looking for the body.
193 0 : nsCOMPtr<nsIContent> content = FindBodyContent(frame->GetContent());
194 :
195 0 : if (!content) {
196 0 : return nullptr;
197 : }
198 :
199 : // this frame will be a nsGFXScrollFrame
200 0 : frame = content->GetPrimaryFrame();
201 0 : if (!frame) {
202 0 : return nullptr;
203 : }
204 :
205 0 : nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
206 0 : if (!scrollFrame) {
207 0 : return nullptr;
208 : }
209 :
210 : // this frame will be the one we want
211 0 : nsIFrame* yeahBaby = scrollFrame->GetScrolledFrame();
212 0 : if (!yeahBaby) {
213 0 : return nullptr;
214 : }
215 :
216 : // It's a frame. Refcounts are irrelevant.
217 0 : nsListBoxBodyFrame* listBoxBody = do_QueryFrame(yeahBaby);
218 0 : NS_ENSURE_TRUE(listBoxBody &&
219 : listBoxBody->SetBoxObject(this),
220 : nullptr);
221 0 : mListBoxBody = listBoxBody;
222 0 : return mListBoxBody;
223 : }
224 :
225 : void
226 0 : ListBoxObject::Clear()
227 : {
228 0 : ClearCachedValues();
229 0 : BoxObject::Clear();
230 0 : }
231 :
232 : void
233 0 : ListBoxObject::ClearCachedValues()
234 : {
235 0 : mListBoxBody = nullptr;
236 0 : }
237 :
238 : } // namespace dom
239 : } // namespace mozilla
240 :
241 : // Creation Routine ///////////////////////////////////////////////////////////////////////
242 :
243 : nsresult
244 0 : NS_NewListBoxObject(nsIBoxObject** aResult)
245 : {
246 0 : NS_ADDREF(*aResult = new mozilla::dom::ListBoxObject());
247 0 : return NS_OK;
248 : }
|