Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
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 "nsTreeBoxObject.h"
7 #include "nsCOMPtr.h"
8 #include "nsIDOMXULElement.h"
9 #include "nsIXULTemplateBuilder.h"
10 #include "nsTreeContentView.h"
11 #include "nsITreeSelection.h"
12 #include "ChildIterator.h"
13 #include "nsContentUtils.h"
14 #include "nsError.h"
15 #include "nsTreeBodyFrame.h"
17 NS_IMPL_CYCLE_COLLECTION(nsTreeBoxObject, mView)
19 NS_IMPL_ADDREF_INHERITED(nsTreeBoxObject, nsBoxObject)
20 NS_IMPL_RELEASE_INHERITED(nsTreeBoxObject, nsBoxObject)
22 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsTreeBoxObject)
23 NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject)
24 NS_INTERFACE_MAP_END_INHERITING(nsBoxObject)
26 void
27 nsTreeBoxObject::Clear()
28 {
29 ClearCachedValues();
31 // Drop the view's ref to us.
32 if (mView) {
33 nsCOMPtr<nsITreeSelection> sel;
34 mView->GetSelection(getter_AddRefs(sel));
35 if (sel)
36 sel->SetTree(nullptr);
37 mView->SetTree(nullptr); // Break the circular ref between the view and us.
38 }
39 mView = nullptr;
41 nsBoxObject::Clear();
42 }
45 nsTreeBoxObject::nsTreeBoxObject()
46 : mTreeBody(nullptr)
47 {
48 }
50 nsTreeBoxObject::~nsTreeBoxObject()
51 {
52 /* destructor code */
53 }
55 static nsIContent* FindBodyElement(nsIContent* aParent)
56 {
57 mozilla::dom::FlattenedChildIterator iter(aParent);
58 for (nsIContent* content = iter.GetNextChild(); content; content = iter.GetNextChild()) {
59 nsINodeInfo *ni = content->NodeInfo();
60 if (ni->Equals(nsGkAtoms::treechildren, kNameSpaceID_XUL)) {
61 return content;
62 } else if (ni->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
63 // There are nesting tree elements. Only the innermost should
64 // find the treechilren.
65 return nullptr;
66 } else if (content->IsElement() &&
67 !ni->Equals(nsGkAtoms::_template, kNameSpaceID_XUL)) {
68 nsIContent* result = FindBodyElement(content);
69 if (result)
70 return result;
71 }
72 }
74 return nullptr;
75 }
77 nsTreeBodyFrame*
78 nsTreeBoxObject::GetTreeBody(bool aFlushLayout)
79 {
80 // Make sure our frames are up to date, and layout as needed. We
81 // have to do this before checking for our cached mTreeBody, since
82 // it might go away on style flush, and in any case if aFlushLayout
83 // is true we need to make sure to flush no matter what.
84 // XXXbz except that flushing style when we were not asked to flush
85 // layout here breaks things. See bug 585123.
86 nsIFrame* frame;
87 if (aFlushLayout) {
88 frame = GetFrame(aFlushLayout);
89 if (!frame)
90 return nullptr;
91 }
93 if (mTreeBody) {
94 // Have one cached already.
95 return mTreeBody;
96 }
98 if (!aFlushLayout) {
99 frame = GetFrame(aFlushLayout);
100 if (!frame)
101 return nullptr;
102 }
104 // Iterate over our content model children looking for the body.
105 nsCOMPtr<nsIContent> content = FindBodyElement(frame->GetContent());
106 if (!content)
107 return nullptr;
109 frame = content->GetPrimaryFrame();
110 if (!frame)
111 return nullptr;
113 // Make sure that the treebodyframe has a pointer to |this|.
114 nsTreeBodyFrame *treeBody = do_QueryFrame(frame);
115 NS_ENSURE_TRUE(treeBody && treeBody->GetTreeBoxObject() == this, nullptr);
117 mTreeBody = treeBody;
118 return mTreeBody;
119 }
121 NS_IMETHODIMP nsTreeBoxObject::GetView(nsITreeView * *aView)
122 {
123 if (!mTreeBody) {
124 if (!GetTreeBody()) {
125 // Don't return an uninitialised view
126 *aView = nullptr;
127 return NS_OK;
128 }
130 if (mView)
131 // Our new frame needs to initialise itself
132 return mTreeBody->GetView(aView);
133 }
134 if (!mView) {
135 nsCOMPtr<nsIDOMXULElement> xulele = do_QueryInterface(mContent);
136 if (xulele) {
137 // See if there is a XUL tree builder associated with the element
138 nsCOMPtr<nsIXULTemplateBuilder> builder;
139 xulele->GetBuilder(getter_AddRefs(builder));
140 mView = do_QueryInterface(builder);
142 if (!mView) {
143 // No tree builder, create a tree content view.
144 nsresult rv = NS_NewTreeContentView(getter_AddRefs(mView));
145 NS_ENSURE_SUCCESS(rv, rv);
146 }
148 // Initialise the frame and view
149 mTreeBody->SetView(mView);
150 }
151 }
152 NS_IF_ADDREF(*aView = mView);
153 return NS_OK;
154 }
156 static bool
157 CanTrustView(nsISupports* aValue)
158 {
159 // Untrusted content is only allowed to specify known-good views
160 if (nsContentUtils::IsCallerChrome())
161 return true;
162 nsCOMPtr<nsINativeTreeView> nativeTreeView = do_QueryInterface(aValue);
163 if (!nativeTreeView || NS_FAILED(nativeTreeView->EnsureNative())) {
164 // XXX ERRMSG need a good error here for developers
165 return false;
166 }
167 return true;
168 }
170 NS_IMETHODIMP nsTreeBoxObject::SetView(nsITreeView * aView)
171 {
172 if (!CanTrustView(aView))
173 return NS_ERROR_DOM_SECURITY_ERR;
175 mView = aView;
176 nsTreeBodyFrame* body = GetTreeBody();
177 if (body)
178 body->SetView(aView);
180 return NS_OK;
181 }
183 NS_IMETHODIMP nsTreeBoxObject::GetFocused(bool* aFocused)
184 {
185 *aFocused = false;
186 nsTreeBodyFrame* body = GetTreeBody();
187 if (body)
188 return body->GetFocused(aFocused);
189 return NS_OK;
190 }
192 NS_IMETHODIMP nsTreeBoxObject::SetFocused(bool aFocused)
193 {
194 nsTreeBodyFrame* body = GetTreeBody();
195 if (body)
196 return body->SetFocused(aFocused);
197 return NS_OK;
198 }
200 NS_IMETHODIMP nsTreeBoxObject::GetTreeBody(nsIDOMElement** aElement)
201 {
202 *aElement = nullptr;
203 nsTreeBodyFrame* body = GetTreeBody();
204 if (body)
205 return body->GetTreeBody(aElement);
206 return NS_OK;
207 }
209 NS_IMETHODIMP nsTreeBoxObject::GetColumns(nsITreeColumns** aColumns)
210 {
211 *aColumns = nullptr;
212 nsTreeBodyFrame* body = GetTreeBody();
213 if (body)
214 *aColumns = body->Columns().take();
215 return NS_OK;
216 }
218 NS_IMETHODIMP nsTreeBoxObject::GetRowHeight(int32_t* aRowHeight)
219 {
220 *aRowHeight = 0;
221 nsTreeBodyFrame* body = GetTreeBody();
222 if (body)
223 return body->GetRowHeight(aRowHeight);
224 return NS_OK;
225 }
227 NS_IMETHODIMP nsTreeBoxObject::GetRowWidth(int32_t *aRowWidth)
228 {
229 *aRowWidth = 0;
230 nsTreeBodyFrame* body = GetTreeBody();
231 if (body)
232 return body->GetRowWidth(aRowWidth);
233 return NS_OK;
234 }
236 NS_IMETHODIMP nsTreeBoxObject::GetFirstVisibleRow(int32_t *aFirstVisibleRow)
237 {
238 *aFirstVisibleRow = 0;
239 nsTreeBodyFrame* body = GetTreeBody();
240 if (body)
241 *aFirstVisibleRow = body->FirstVisibleRow();
242 return NS_OK;
243 }
245 NS_IMETHODIMP nsTreeBoxObject::GetLastVisibleRow(int32_t *aLastVisibleRow)
246 {
247 *aLastVisibleRow = 0;
248 nsTreeBodyFrame* body = GetTreeBody();
249 if (body)
250 *aLastVisibleRow = body->LastVisibleRow();
251 return NS_OK;
252 }
254 NS_IMETHODIMP nsTreeBoxObject::GetHorizontalPosition(int32_t *aHorizontalPosition)
255 {
256 *aHorizontalPosition = 0;
257 nsTreeBodyFrame* body = GetTreeBody();
258 if (body)
259 return body->GetHorizontalPosition(aHorizontalPosition);
260 return NS_OK;
261 }
263 NS_IMETHODIMP nsTreeBoxObject::GetPageLength(int32_t *aPageLength)
264 {
265 *aPageLength = 0;
266 nsTreeBodyFrame* body = GetTreeBody();
267 if (body)
268 *aPageLength = body->PageLength();
269 return NS_OK;
270 }
272 NS_IMETHODIMP nsTreeBoxObject::GetSelectionRegion(nsIScriptableRegion **aRegion)
273 {
274 *aRegion = nullptr;
275 nsTreeBodyFrame* body = GetTreeBody();
276 if (body)
277 return body->GetSelectionRegion(aRegion);
278 return NS_OK;
279 }
281 NS_IMETHODIMP
282 nsTreeBoxObject::EnsureRowIsVisible(int32_t aRow)
283 {
284 nsTreeBodyFrame* body = GetTreeBody();
285 if (body)
286 return body->EnsureRowIsVisible(aRow);
287 return NS_OK;
288 }
290 NS_IMETHODIMP
291 nsTreeBoxObject::EnsureCellIsVisible(int32_t aRow, nsITreeColumn* aCol)
292 {
293 nsTreeBodyFrame* body = GetTreeBody();
294 if (body)
295 return body->EnsureCellIsVisible(aRow, aCol);
296 return NS_OK;
297 return NS_ERROR_NOT_IMPLEMENTED;
298 }
300 NS_IMETHODIMP
301 nsTreeBoxObject::ScrollToRow(int32_t aRow)
302 {
303 nsTreeBodyFrame* body = GetTreeBody(true);
304 if (body)
305 return body->ScrollToRow(aRow);
306 return NS_OK;
307 }
309 NS_IMETHODIMP
310 nsTreeBoxObject::ScrollByLines(int32_t aNumLines)
311 {
312 nsTreeBodyFrame* body = GetTreeBody();
313 if (body)
314 return body->ScrollByLines(aNumLines);
315 return NS_OK;
316 }
318 NS_IMETHODIMP
319 nsTreeBoxObject::ScrollByPages(int32_t aNumPages)
320 {
321 nsTreeBodyFrame* body = GetTreeBody();
322 if (body)
323 return body->ScrollByPages(aNumPages);
324 return NS_OK;
325 }
327 NS_IMETHODIMP
328 nsTreeBoxObject::ScrollToCell(int32_t aRow, nsITreeColumn* aCol)
329 {
330 nsTreeBodyFrame* body = GetTreeBody();
331 if (body)
332 return body->ScrollToCell(aRow, aCol);
333 return NS_OK;
334 }
336 NS_IMETHODIMP
337 nsTreeBoxObject::ScrollToColumn(nsITreeColumn* aCol)
338 {
339 nsTreeBodyFrame* body = GetTreeBody();
340 if (body)
341 return body->ScrollToColumn(aCol);
342 return NS_OK;
343 }
345 NS_IMETHODIMP
346 nsTreeBoxObject::ScrollToHorizontalPosition(int32_t aHorizontalPosition)
347 {
348 nsTreeBodyFrame* body = GetTreeBody();
349 if (body)
350 return body->ScrollToHorizontalPosition(aHorizontalPosition);
351 return NS_OK;
352 }
354 NS_IMETHODIMP nsTreeBoxObject::Invalidate()
355 {
356 nsTreeBodyFrame* body = GetTreeBody();
357 if (body)
358 return body->Invalidate();
359 return NS_OK;
360 }
362 NS_IMETHODIMP nsTreeBoxObject::InvalidateColumn(nsITreeColumn* aCol)
363 {
364 nsTreeBodyFrame* body = GetTreeBody();
365 if (body)
366 return body->InvalidateColumn(aCol);
367 return NS_OK;
368 }
370 NS_IMETHODIMP nsTreeBoxObject::InvalidateRow(int32_t aIndex)
371 {
372 nsTreeBodyFrame* body = GetTreeBody();
373 if (body)
374 return body->InvalidateRow(aIndex);
375 return NS_OK;
376 }
378 NS_IMETHODIMP nsTreeBoxObject::InvalidateCell(int32_t aRow, nsITreeColumn* aCol)
379 {
380 nsTreeBodyFrame* body = GetTreeBody();
381 if (body)
382 return body->InvalidateCell(aRow, aCol);
383 return NS_OK;
384 }
386 NS_IMETHODIMP nsTreeBoxObject::InvalidateRange(int32_t aStart, int32_t aEnd)
387 {
388 nsTreeBodyFrame* body = GetTreeBody();
389 if (body)
390 return body->InvalidateRange(aStart, aEnd);
391 return NS_OK;
392 }
394 NS_IMETHODIMP nsTreeBoxObject::InvalidateColumnRange(int32_t aStart, int32_t aEnd, nsITreeColumn* aCol)
395 {
396 nsTreeBodyFrame* body = GetTreeBody();
397 if (body)
398 return body->InvalidateColumnRange(aStart, aEnd, aCol);
399 return NS_OK;
400 }
402 NS_IMETHODIMP nsTreeBoxObject::GetRowAt(int32_t x, int32_t y, int32_t *aRow)
403 {
404 *aRow = 0;
405 nsTreeBodyFrame* body = GetTreeBody();
406 if (body)
407 return body->GetRowAt(x, y, aRow);
408 return NS_OK;
409 }
411 NS_IMETHODIMP nsTreeBoxObject::GetCellAt(int32_t aX, int32_t aY, int32_t *aRow, nsITreeColumn** aCol,
412 nsACString& aChildElt)
413 {
414 *aRow = 0;
415 *aCol = nullptr;
416 nsTreeBodyFrame* body = GetTreeBody();
417 if (body)
418 return body->GetCellAt(aX, aY, aRow, aCol, aChildElt);
419 return NS_OK;
420 }
422 NS_IMETHODIMP
423 nsTreeBoxObject::GetCoordsForCellItem(int32_t aRow, nsITreeColumn* aCol, const nsACString& aElement,
424 int32_t *aX, int32_t *aY, int32_t *aWidth, int32_t *aHeight)
425 {
426 *aX = *aY = *aWidth = *aHeight = 0;
427 nsTreeBodyFrame* body = GetTreeBody();
428 if (body)
429 return body->GetCoordsForCellItem(aRow, aCol, aElement, aX, aY, aWidth, aHeight);
430 return NS_OK;
431 }
433 NS_IMETHODIMP
434 nsTreeBoxObject::IsCellCropped(int32_t aRow, nsITreeColumn* aCol, bool *aIsCropped)
435 {
436 *aIsCropped = false;
437 nsTreeBodyFrame* body = GetTreeBody();
438 if (body)
439 return body->IsCellCropped(aRow, aCol, aIsCropped);
440 return NS_OK;
441 }
443 NS_IMETHODIMP nsTreeBoxObject::RowCountChanged(int32_t aIndex, int32_t aDelta)
444 {
445 nsTreeBodyFrame* body = GetTreeBody();
446 if (body)
447 return body->RowCountChanged(aIndex, aDelta);
448 return NS_OK;
449 }
451 NS_IMETHODIMP nsTreeBoxObject::BeginUpdateBatch()
452 {
453 nsTreeBodyFrame* body = GetTreeBody();
454 if (body)
455 return body->BeginUpdateBatch();
456 return NS_OK;
457 }
459 NS_IMETHODIMP nsTreeBoxObject::EndUpdateBatch()
460 {
461 nsTreeBodyFrame* body = GetTreeBody();
462 if (body)
463 return body->EndUpdateBatch();
464 return NS_OK;
465 }
467 NS_IMETHODIMP nsTreeBoxObject::ClearStyleAndImageCaches()
468 {
469 nsTreeBodyFrame* body = GetTreeBody();
470 if (body)
471 return body->ClearStyleAndImageCaches();
472 return NS_OK;
473 }
475 void
476 nsTreeBoxObject::ClearCachedValues()
477 {
478 mTreeBody = nullptr;
479 }
481 // Creation Routine ///////////////////////////////////////////////////////////////////////
483 nsresult
484 NS_NewTreeBoxObject(nsIBoxObject** aResult)
485 {
486 *aResult = new nsTreeBoxObject;
487 if (!*aResult)
488 return NS_ERROR_OUT_OF_MEMORY;
489 NS_ADDREF(*aResult);
490 return NS_OK;
491 }