layout/xul/nsListBoxObject.cpp

branch
TOR_BUG_9701
changeset 3
141e0f1194b1
equal deleted inserted replaced
-1:000000000000 0:8a72588e4263
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 "nsCOMPtr.h"
7 #include "nsPIListBoxObject.h"
8 #include "nsBoxObject.h"
9 #include "nsIFrame.h"
10 #include "nsBindingManager.h"
11 #include "nsIDOMElement.h"
12 #include "nsIDOMNodeList.h"
13 #include "nsGkAtoms.h"
14 #include "nsIScrollableFrame.h"
15 #include "nsListBoxBodyFrame.h"
16 #include "ChildIterator.h"
17
18 class nsListBoxObject : public nsPIListBoxObject, public nsBoxObject
19 {
20 public:
21 NS_DECL_ISUPPORTS_INHERITED
22 NS_DECL_NSILISTBOXOBJECT
23
24 // nsPIListBoxObject
25 virtual nsListBoxBodyFrame* GetListBoxBody(bool aFlush) MOZ_OVERRIDE;
26
27 nsListBoxObject();
28
29 // nsPIBoxObject
30 virtual void Clear() MOZ_OVERRIDE;
31 virtual void ClearCachedValues() MOZ_OVERRIDE;
32
33 protected:
34 nsListBoxBodyFrame *mListBoxBody;
35 };
36
37 NS_IMPL_ISUPPORTS_INHERITED(nsListBoxObject, nsBoxObject, nsIListBoxObject,
38 nsPIListBoxObject)
39
40 nsListBoxObject::nsListBoxObject()
41 : mListBoxBody(nullptr)
42 {
43 }
44
45 //////////////////////////////////////////////////////////////////////////
46 //// nsIListBoxObject
47
48 NS_IMETHODIMP
49 nsListBoxObject::GetRowCount(int32_t *aResult)
50 {
51 nsListBoxBodyFrame* body = GetListBoxBody(true);
52 if (body)
53 return body->GetRowCount(aResult);
54 return NS_OK;
55 }
56
57 NS_IMETHODIMP
58 nsListBoxObject::GetNumberOfVisibleRows(int32_t *aResult)
59 {
60 nsListBoxBodyFrame* body = GetListBoxBody(true);
61 if (body)
62 return body->GetNumberOfVisibleRows(aResult);
63 return NS_OK;
64 }
65
66 NS_IMETHODIMP
67 nsListBoxObject::GetIndexOfFirstVisibleRow(int32_t *aResult)
68 {
69 nsListBoxBodyFrame* body = GetListBoxBody(true);
70 if (body)
71 return body->GetIndexOfFirstVisibleRow(aResult);
72 return NS_OK;
73 }
74
75 NS_IMETHODIMP nsListBoxObject::EnsureIndexIsVisible(int32_t aRowIndex)
76 {
77 nsListBoxBodyFrame* body = GetListBoxBody(true);
78 if (body)
79 return body->EnsureIndexIsVisible(aRowIndex);
80 return NS_OK;
81 }
82
83 NS_IMETHODIMP
84 nsListBoxObject::ScrollToIndex(int32_t aRowIndex)
85 {
86 nsListBoxBodyFrame* body = GetListBoxBody(true);
87 if (body)
88 return body->ScrollToIndex(aRowIndex);
89 return NS_OK;
90 }
91
92 NS_IMETHODIMP
93 nsListBoxObject::ScrollByLines(int32_t aNumLines)
94 {
95 nsListBoxBodyFrame* body = GetListBoxBody(true);
96 if (body)
97 return body->ScrollByLines(aNumLines);
98 return NS_OK;
99 }
100
101 NS_IMETHODIMP
102 nsListBoxObject::GetItemAtIndex(int32_t index, nsIDOMElement **_retval)
103 {
104 nsListBoxBodyFrame* body = GetListBoxBody(true);
105 if (body)
106 return body->GetItemAtIndex(index, _retval);
107 return NS_OK;
108 }
109
110 NS_IMETHODIMP
111 nsListBoxObject::GetIndexOfItem(nsIDOMElement* aElement, int32_t *aResult)
112 {
113 *aResult = 0;
114
115 nsListBoxBodyFrame* body = GetListBoxBody(true);
116 if (body)
117 return body->GetIndexOfItem(aElement, aResult);
118 return NS_OK;
119 }
120
121 //////////////////////
122
123 static nsIContent*
124 FindBodyContent(nsIContent* aParent)
125 {
126 if (aParent->Tag() == nsGkAtoms::listboxbody) {
127 return aParent;
128 }
129
130 mozilla::dom::FlattenedChildIterator iter(aParent);
131 for (nsIContent* child = iter.GetNextChild(); child; child = iter.GetNextChild()) {
132 nsIContent* result = FindBodyContent(child);
133 if (result) {
134 return result;
135 }
136 }
137
138 return nullptr;
139 }
140
141 nsListBoxBodyFrame*
142 nsListBoxObject::GetListBoxBody(bool aFlush)
143 {
144 if (mListBoxBody) {
145 return mListBoxBody;
146 }
147
148 nsIPresShell* shell = GetPresShell(false);
149 if (!shell) {
150 return nullptr;
151 }
152
153 nsIFrame* frame = aFlush ?
154 GetFrame(false) /* does Flush_Frames */ :
155 mContent->GetPrimaryFrame();
156 if (!frame)
157 return nullptr;
158
159 // Iterate over our content model children looking for the body.
160 nsCOMPtr<nsIContent> content = FindBodyContent(frame->GetContent());
161
162 if (!content)
163 return nullptr;
164
165 // this frame will be a nsGFXScrollFrame
166 frame = content->GetPrimaryFrame();
167 if (!frame)
168 return nullptr;
169 nsIScrollableFrame* scrollFrame = do_QueryFrame(frame);
170 if (!scrollFrame)
171 return nullptr;
172
173 // this frame will be the one we want
174 nsIFrame* yeahBaby = scrollFrame->GetScrolledFrame();
175 if (!yeahBaby)
176 return nullptr;
177
178 // It's a frame. Refcounts are irrelevant.
179 nsListBoxBodyFrame* listBoxBody = do_QueryFrame(yeahBaby);
180 NS_ENSURE_TRUE(listBoxBody &&
181 listBoxBody->SetBoxObject(this),
182 nullptr);
183 mListBoxBody = listBoxBody;
184 return mListBoxBody;
185 }
186
187 void
188 nsListBoxObject::Clear()
189 {
190 ClearCachedValues();
191
192 nsBoxObject::Clear();
193 }
194
195 void
196 nsListBoxObject::ClearCachedValues()
197 {
198 mListBoxBody = nullptr;
199 }
200
201 // Creation Routine ///////////////////////////////////////////////////////////////////////
202
203 nsresult
204 NS_NewListBoxObject(nsIBoxObject** aResult)
205 {
206 *aResult = new nsListBoxObject;
207 if (!*aResult)
208 return NS_ERROR_OUT_OF_MEMORY;
209 NS_ADDREF(*aResult);
210 return NS_OK;
211 }

mercurial