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 "mozilla/dom/TreeBoxObject.h"
8 #include "nsCOMPtr.h"
9 #include "nsXULElement.h"
10 #include "nsIScriptableRegion.h"
11 #include "nsTreeContentView.h"
12 #include "nsITreeSelection.h"
13 #include "ChildIterator.h"
14 #include "nsContentUtils.h"
15 #include "nsError.h"
16 #include "nsTreeBodyFrame.h"
17 #include "mozilla/dom/TreeBoxObjectBinding.h"
18 #include "nsITreeColumns.h"
19 #include "mozilla/dom/DOMRect.h"
20 #include "mozilla/dom/BindingUtils.h"
21 #include "mozilla/dom/Element.h"
22 #include "mozilla/dom/ToJSValue.h"
23 
24 namespace mozilla {
25 namespace dom {
26 
NS_IMPL_CYCLE_COLLECTION_INHERITED(TreeBoxObject,BoxObject,mView)27 NS_IMPL_CYCLE_COLLECTION_INHERITED(TreeBoxObject, BoxObject, mView)
28 
29 NS_IMPL_ADDREF_INHERITED(TreeBoxObject, BoxObject)
30 NS_IMPL_RELEASE_INHERITED(TreeBoxObject, BoxObject)
31 
32 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(TreeBoxObject)
33   NS_INTERFACE_MAP_ENTRY(nsITreeBoxObject)
34 NS_INTERFACE_MAP_END_INHERITING(BoxObject)
35 
36 void TreeBoxObject::Clear() {
37   ClearCachedValues();
38 
39   // Drop the view's ref to us.
40   if (mView) {
41     nsCOMPtr<nsITreeSelection> sel;
42     mView->GetSelection(getter_AddRefs(sel));
43     if (sel) sel->SetTree(nullptr);
44     mView->SetTree(nullptr);  // Break the circular ref between the view and us.
45   }
46   mView = nullptr;
47 
48   BoxObject::Clear();
49 }
50 
TreeBoxObject()51 TreeBoxObject::TreeBoxObject() : mTreeBody(nullptr) {}
52 
~TreeBoxObject()53 TreeBoxObject::~TreeBoxObject() {}
54 
FindBodyElement(nsIContent * aParent)55 static nsIContent* FindBodyElement(nsIContent* aParent) {
56   mozilla::dom::FlattenedChildIterator iter(aParent);
57   for (nsIContent* content = iter.GetNextChild(); content;
58        content = iter.GetNextChild()) {
59     mozilla::dom::NodeInfo* 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) return result;
70     }
71   }
72 
73   return nullptr;
74 }
75 
GetTreeBodyFrame(bool aFlushLayout)76 nsTreeBodyFrame* TreeBoxObject::GetTreeBodyFrame(bool aFlushLayout) {
77   // Make sure our frames are up to date, and layout as needed.  We
78   // have to do this before checking for our cached mTreeBody, since
79   // it might go away on style flush, and in any case if aFlushLayout
80   // is true we need to make sure to flush no matter what.
81   // XXXbz except that flushing style when we were not asked to flush
82   // layout here breaks things.  See bug 585123.
83   nsIFrame* frame = nullptr;
84   if (aFlushLayout) {
85     frame = GetFrame(aFlushLayout);
86     if (!frame) return nullptr;
87   }
88 
89   if (mTreeBody) {
90     // Have one cached already.
91     return mTreeBody;
92   }
93 
94   if (!aFlushLayout) {
95     frame = GetFrame(aFlushLayout);
96     if (!frame) return nullptr;
97   }
98 
99   // Iterate over our content model children looking for the body.
100   nsCOMPtr<nsIContent> content = FindBodyElement(frame->GetContent());
101   if (!content) return nullptr;
102 
103   frame = content->GetPrimaryFrame();
104   if (!frame) return nullptr;
105 
106   // Make sure that the treebodyframe has a pointer to |this|.
107   nsTreeBodyFrame* treeBody = do_QueryFrame(frame);
108   NS_ENSURE_TRUE(treeBody && treeBody->GetTreeBoxObject() == this, nullptr);
109 
110   mTreeBody = treeBody;
111   return mTreeBody;
112 }
113 
114 NS_IMETHODIMP
GetView(nsITreeView ** aView)115 TreeBoxObject::GetView(nsITreeView** aView) {
116   if (!mTreeBody) {
117     if (!GetTreeBodyFrame()) {
118       // Don't return an uninitialised view
119       *aView = nullptr;
120       return NS_OK;
121     }
122 
123     if (mView)
124       // Our new frame needs to initialise itself
125       return mTreeBody->GetView(aView);
126   }
127   if (!mView) {
128     RefPtr<nsXULElement> xulele = nsXULElement::FromContentOrNull(mContent);
129     if (xulele) {
130       // No tree builder, create a tree content view.
131       nsresult rv = NS_NewTreeContentView(getter_AddRefs(mView));
132       NS_ENSURE_SUCCESS(rv, rv);
133 
134       // Initialise the frame and view
135       mTreeBody->SetView(mView);
136     }
137   }
138   NS_IF_ADDREF(*aView = mView);
139   return NS_OK;
140 }
141 
GetView(CallerType)142 already_AddRefed<nsITreeView> TreeBoxObject::GetView(CallerType /* unused */) {
143   nsCOMPtr<nsITreeView> view;
144   GetView(getter_AddRefs(view));
145   return view.forget();
146 }
147 
148 NS_IMETHODIMP
SetView(nsITreeView * aView)149 TreeBoxObject::SetView(nsITreeView* aView) {
150   ErrorResult rv;
151   SetView(aView, CallerType::System, rv);
152   return rv.StealNSResult();
153 }
154 
SetView(nsITreeView * aView,CallerType aCallerType,ErrorResult & aRv)155 void TreeBoxObject::SetView(nsITreeView* aView, CallerType aCallerType,
156                             ErrorResult& aRv) {
157   if (aCallerType != CallerType::System) {
158     // Don't trust views coming from random places.
159     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
160     return;
161   }
162 
163   mView = aView;
164   nsTreeBodyFrame* body = GetTreeBodyFrame();
165   if (body) body->SetView(aView);
166 }
167 
Focused()168 bool TreeBoxObject::Focused() {
169   nsTreeBodyFrame* body = GetTreeBodyFrame();
170   if (body) return body->GetFocused();
171   return false;
172 }
173 
GetFocused(bool * aFocused)174 NS_IMETHODIMP TreeBoxObject::GetFocused(bool* aFocused) {
175   *aFocused = Focused();
176   return NS_OK;
177 }
178 
SetFocused(bool aFocused)179 NS_IMETHODIMP TreeBoxObject::SetFocused(bool aFocused) {
180   nsTreeBodyFrame* body = GetTreeBodyFrame();
181   if (body) return body->SetFocused(aFocused);
182   return NS_OK;
183 }
184 
GetTreeBody(nsIDOMElement ** aElement)185 NS_IMETHODIMP TreeBoxObject::GetTreeBody(nsIDOMElement** aElement) {
186   *aElement = nullptr;
187   nsTreeBodyFrame* body = GetTreeBodyFrame();
188   if (body) return body->GetTreeBody(aElement);
189   return NS_OK;
190 }
191 
GetTreeBody()192 already_AddRefed<Element> TreeBoxObject::GetTreeBody() {
193   nsCOMPtr<nsIDOMElement> el;
194   GetTreeBody(getter_AddRefs(el));
195   nsCOMPtr<Element> ret(do_QueryInterface(el));
196   return ret.forget();
197 }
198 
GetColumns()199 already_AddRefed<nsTreeColumns> TreeBoxObject::GetColumns() {
200   nsTreeBodyFrame* body = GetTreeBodyFrame();
201   if (body) return body->Columns();
202   return nullptr;
203 }
204 
GetColumns(nsITreeColumns ** aColumns)205 NS_IMETHODIMP TreeBoxObject::GetColumns(nsITreeColumns** aColumns) {
206   *aColumns = GetColumns().take();
207   return NS_OK;
208 }
209 
RowHeight()210 int32_t TreeBoxObject::RowHeight() {
211   nsTreeBodyFrame* body = GetTreeBodyFrame();
212   if (body) return body->RowHeight();
213   return 0;
214 }
215 
RowWidth()216 int32_t TreeBoxObject::RowWidth() {
217   nsTreeBodyFrame* body = GetTreeBodyFrame();
218   if (body) return body->RowWidth();
219   return 0;
220 }
221 
GetRowHeight(int32_t * aRowHeight)222 NS_IMETHODIMP TreeBoxObject::GetRowHeight(int32_t* aRowHeight) {
223   *aRowHeight = RowHeight();
224   return NS_OK;
225 }
226 
GetRowWidth(int32_t * aRowWidth)227 NS_IMETHODIMP TreeBoxObject::GetRowWidth(int32_t* aRowWidth) {
228   *aRowWidth = RowWidth();
229   return NS_OK;
230 }
231 
GetFirstVisibleRow()232 int32_t TreeBoxObject::GetFirstVisibleRow() {
233   nsTreeBodyFrame* body = GetTreeBodyFrame();
234   if (body) return body->FirstVisibleRow();
235   return 0;
236 }
237 
GetFirstVisibleRow(int32_t * aFirstVisibleRow)238 NS_IMETHODIMP TreeBoxObject::GetFirstVisibleRow(int32_t* aFirstVisibleRow) {
239   *aFirstVisibleRow = GetFirstVisibleRow();
240   return NS_OK;
241 }
242 
GetLastVisibleRow()243 int32_t TreeBoxObject::GetLastVisibleRow() {
244   nsTreeBodyFrame* body = GetTreeBodyFrame();
245   if (body) return body->LastVisibleRow();
246   return 0;
247 }
248 
GetLastVisibleRow(int32_t * aLastVisibleRow)249 NS_IMETHODIMP TreeBoxObject::GetLastVisibleRow(int32_t* aLastVisibleRow) {
250   *aLastVisibleRow = GetLastVisibleRow();
251   return NS_OK;
252 }
253 
HorizontalPosition()254 int32_t TreeBoxObject::HorizontalPosition() {
255   nsTreeBodyFrame* body = GetTreeBodyFrame();
256   if (body) return body->GetHorizontalPosition();
257   return 0;
258 }
259 
GetHorizontalPosition(int32_t * aHorizontalPosition)260 NS_IMETHODIMP TreeBoxObject::GetHorizontalPosition(
261     int32_t* aHorizontalPosition) {
262   *aHorizontalPosition = HorizontalPosition();
263   return NS_OK;
264 }
265 
GetPageLength()266 int32_t TreeBoxObject::GetPageLength() {
267   nsTreeBodyFrame* body = GetTreeBodyFrame();
268   if (body) return body->PageLength();
269   return 0;
270 }
271 
GetPageLength(int32_t * aPageLength)272 NS_IMETHODIMP TreeBoxObject::GetPageLength(int32_t* aPageLength) {
273   *aPageLength = GetPageLength();
274   return NS_OK;
275 }
276 
GetSelectionRegion(nsIScriptableRegion ** aRegion)277 NS_IMETHODIMP TreeBoxObject::GetSelectionRegion(nsIScriptableRegion** aRegion) {
278   *aRegion = nullptr;
279   nsTreeBodyFrame* body = GetTreeBodyFrame();
280   if (body) return body->GetSelectionRegion(aRegion);
281   return NS_OK;
282 }
283 
SelectionRegion()284 already_AddRefed<nsIScriptableRegion> TreeBoxObject::SelectionRegion() {
285   nsCOMPtr<nsIScriptableRegion> region;
286   GetSelectionRegion(getter_AddRefs(region));
287   return region.forget();
288 }
289 
290 NS_IMETHODIMP
EnsureRowIsVisible(int32_t aRow)291 TreeBoxObject::EnsureRowIsVisible(int32_t aRow) {
292   nsTreeBodyFrame* body = GetTreeBodyFrame();
293   if (body) return body->EnsureRowIsVisible(aRow);
294   return NS_OK;
295 }
296 
297 NS_IMETHODIMP
EnsureCellIsVisible(int32_t aRow,nsITreeColumn * aCol)298 TreeBoxObject::EnsureCellIsVisible(int32_t aRow, nsITreeColumn* aCol) {
299   nsTreeBodyFrame* body = GetTreeBodyFrame();
300   if (body) return body->EnsureCellIsVisible(aRow, aCol);
301   return NS_OK;
302 }
303 
304 NS_IMETHODIMP
ScrollToRow(int32_t aRow)305 TreeBoxObject::ScrollToRow(int32_t aRow) {
306   nsTreeBodyFrame* body = GetTreeBodyFrame(true);
307   if (body) return body->ScrollToRow(aRow);
308   return NS_OK;
309 }
310 
311 NS_IMETHODIMP
ScrollByLines(int32_t aNumLines)312 TreeBoxObject::ScrollByLines(int32_t aNumLines) {
313   nsTreeBodyFrame* body = GetTreeBodyFrame();
314   if (body) return body->ScrollByLines(aNumLines);
315   return NS_OK;
316 }
317 
318 NS_IMETHODIMP
ScrollByPages(int32_t aNumPages)319 TreeBoxObject::ScrollByPages(int32_t aNumPages) {
320   nsTreeBodyFrame* body = GetTreeBodyFrame();
321   if (body) return body->ScrollByPages(aNumPages);
322   return NS_OK;
323 }
324 
325 NS_IMETHODIMP
ScrollToCell(int32_t aRow,nsITreeColumn * aCol)326 TreeBoxObject::ScrollToCell(int32_t aRow, nsITreeColumn* aCol) {
327   nsTreeBodyFrame* body = GetTreeBodyFrame();
328   if (body) return body->ScrollToCell(aRow, aCol);
329   return NS_OK;
330 }
331 
332 NS_IMETHODIMP
ScrollToColumn(nsITreeColumn * aCol)333 TreeBoxObject::ScrollToColumn(nsITreeColumn* aCol) {
334   nsTreeBodyFrame* body = GetTreeBodyFrame();
335   if (body) return body->ScrollToColumn(aCol);
336   return NS_OK;
337 }
338 
339 NS_IMETHODIMP
ScrollToHorizontalPosition(int32_t aHorizontalPosition)340 TreeBoxObject::ScrollToHorizontalPosition(int32_t aHorizontalPosition) {
341   nsTreeBodyFrame* body = GetTreeBodyFrame();
342   if (body) return body->ScrollToHorizontalPosition(aHorizontalPosition);
343   return NS_OK;
344 }
345 
Invalidate()346 NS_IMETHODIMP TreeBoxObject::Invalidate() {
347   nsTreeBodyFrame* body = GetTreeBodyFrame();
348   if (body) return body->Invalidate();
349   return NS_OK;
350 }
351 
352 NS_IMETHODIMP
InvalidateColumn(nsITreeColumn * aCol)353 TreeBoxObject::InvalidateColumn(nsITreeColumn* aCol) {
354   nsTreeBodyFrame* body = GetTreeBodyFrame();
355   if (body) return body->InvalidateColumn(aCol);
356   return NS_OK;
357 }
358 
359 NS_IMETHODIMP
InvalidateRow(int32_t aIndex)360 TreeBoxObject::InvalidateRow(int32_t aIndex) {
361   nsTreeBodyFrame* body = GetTreeBodyFrame();
362   if (body) return body->InvalidateRow(aIndex);
363   return NS_OK;
364 }
365 
366 NS_IMETHODIMP
InvalidateCell(int32_t aRow,nsITreeColumn * aCol)367 TreeBoxObject::InvalidateCell(int32_t aRow, nsITreeColumn* aCol) {
368   nsTreeBodyFrame* body = GetTreeBodyFrame();
369   if (body) return body->InvalidateCell(aRow, aCol);
370   return NS_OK;
371 }
372 
373 NS_IMETHODIMP
InvalidateRange(int32_t aStart,int32_t aEnd)374 TreeBoxObject::InvalidateRange(int32_t aStart, int32_t aEnd) {
375   nsTreeBodyFrame* body = GetTreeBodyFrame();
376   if (body) return body->InvalidateRange(aStart, aEnd);
377   return NS_OK;
378 }
379 
380 NS_IMETHODIMP
InvalidateColumnRange(int32_t aStart,int32_t aEnd,nsITreeColumn * aCol)381 TreeBoxObject::InvalidateColumnRange(int32_t aStart, int32_t aEnd,
382                                      nsITreeColumn* aCol) {
383   nsTreeBodyFrame* body = GetTreeBodyFrame();
384   if (body) return body->InvalidateColumnRange(aStart, aEnd, aCol);
385   return NS_OK;
386 }
387 
388 NS_IMETHODIMP
GetRowAt(int32_t x,int32_t y,int32_t * aRow)389 TreeBoxObject::GetRowAt(int32_t x, int32_t y, int32_t* aRow) {
390   *aRow = 0;
391   nsTreeBodyFrame* body = GetTreeBodyFrame();
392   if (body) return body->GetRowAt(x, y, aRow);
393   return NS_OK;
394 }
395 
GetRowAt(int32_t x,int32_t y)396 int32_t TreeBoxObject::GetRowAt(int32_t x, int32_t y) {
397   int32_t row;
398   GetRowAt(x, y, &row);
399   return row;
400 }
401 
402 NS_IMETHODIMP
GetCellAt(int32_t aX,int32_t aY,int32_t * aRow,nsITreeColumn ** aCol,nsAString & aChildElt)403 TreeBoxObject::GetCellAt(int32_t aX, int32_t aY, int32_t* aRow,
404                          nsITreeColumn** aCol, nsAString& aChildElt) {
405   *aRow = 0;
406   *aCol = nullptr;
407   nsTreeBodyFrame* body = GetTreeBodyFrame();
408   if (body) {
409     nsAutoCString element;
410     nsresult retval = body->GetCellAt(aX, aY, aRow, aCol, element);
411     CopyUTF8toUTF16(element, aChildElt);
412     return retval;
413   }
414   return NS_OK;
415 }
416 
GetCellAt(int32_t x,int32_t y,TreeCellInfo & aRetVal,ErrorResult & aRv)417 void TreeBoxObject::GetCellAt(int32_t x, int32_t y, TreeCellInfo& aRetVal,
418                               ErrorResult& aRv) {
419   nsCOMPtr<nsITreeColumn> col;
420   GetCellAt(x, y, &aRetVal.mRow, getter_AddRefs(col), aRetVal.mChildElt);
421   aRetVal.mCol = col.forget().downcast<nsTreeColumn>();
422 }
423 
GetCellAt(JSContext * cx,int32_t x,int32_t y,JS::Handle<JSObject * > rowOut,JS::Handle<JSObject * > colOut,JS::Handle<JSObject * > childEltOut,ErrorResult & aRv)424 void TreeBoxObject::GetCellAt(JSContext* cx, int32_t x, int32_t y,
425                               JS::Handle<JSObject*> rowOut,
426                               JS::Handle<JSObject*> colOut,
427                               JS::Handle<JSObject*> childEltOut,
428                               ErrorResult& aRv) {
429   int32_t row;
430   nsITreeColumn* col;
431   nsAutoString childElt;
432   GetCellAt(x, y, &row, &col, childElt);
433 
434   JS::Rooted<JS::Value> v(cx);
435 
436   if (!ToJSValue(cx, row, &v) || !JS_SetProperty(cx, rowOut, "value", v)) {
437     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
438     return;
439   }
440   if (!dom::WrapObject(cx, col, &v) ||
441       !JS_SetProperty(cx, colOut, "value", v)) {
442     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
443     return;
444   }
445   if (!ToJSValue(cx, childElt, &v) ||
446       !JS_SetProperty(cx, childEltOut, "value", v)) {
447     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
448     return;
449   }
450 }
451 
452 NS_IMETHODIMP
GetCoordsForCellItem(int32_t aRow,nsITreeColumn * aCol,const nsAString & aElement,int32_t * aX,int32_t * aY,int32_t * aWidth,int32_t * aHeight)453 TreeBoxObject::GetCoordsForCellItem(int32_t aRow, nsITreeColumn* aCol,
454                                     const nsAString& aElement, int32_t* aX,
455                                     int32_t* aY, int32_t* aWidth,
456                                     int32_t* aHeight) {
457   *aX = *aY = *aWidth = *aHeight = 0;
458   nsTreeBodyFrame* body = GetTreeBodyFrame();
459   NS_ConvertUTF16toUTF8 element(aElement);
460   if (body)
461     return body->GetCoordsForCellItem(aRow, aCol, element, aX, aY, aWidth,
462                                       aHeight);
463   return NS_OK;
464 }
465 
GetCoordsForCellItem(int32_t row,nsTreeColumn & col,const nsAString & element,ErrorResult & aRv)466 already_AddRefed<DOMRect> TreeBoxObject::GetCoordsForCellItem(
467     int32_t row, nsTreeColumn& col, const nsAString& element,
468     ErrorResult& aRv) {
469   int32_t x, y, w, h;
470   GetCoordsForCellItem(row, &col, element, &x, &y, &w, &h);
471   RefPtr<DOMRect> rect = new DOMRect(mContent, x, y, w, h);
472   return rect.forget();
473 }
474 
GetCoordsForCellItem(JSContext * cx,int32_t row,nsTreeColumn & col,const nsAString & element,JS::Handle<JSObject * > xOut,JS::Handle<JSObject * > yOut,JS::Handle<JSObject * > widthOut,JS::Handle<JSObject * > heightOut,ErrorResult & aRv)475 void TreeBoxObject::GetCoordsForCellItem(
476     JSContext* cx, int32_t row, nsTreeColumn& col, const nsAString& element,
477     JS::Handle<JSObject*> xOut, JS::Handle<JSObject*> yOut,
478     JS::Handle<JSObject*> widthOut, JS::Handle<JSObject*> heightOut,
479     ErrorResult& aRv) {
480   int32_t x, y, w, h;
481   GetCoordsForCellItem(row, &col, element, &x, &y, &w, &h);
482   JS::Rooted<JS::Value> v(cx, JS::Int32Value(x));
483   if (!JS_SetProperty(cx, xOut, "value", v)) {
484     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
485     return;
486   }
487   v.setInt32(y);
488   if (!JS_SetProperty(cx, yOut, "value", v)) {
489     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
490     return;
491   }
492   v.setInt32(w);
493   if (!JS_SetProperty(cx, widthOut, "value", v)) {
494     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
495     return;
496   }
497   v.setInt32(h);
498   if (!JS_SetProperty(cx, heightOut, "value", v)) {
499     aRv.Throw(NS_ERROR_XPC_CANT_SET_OUT_VAL);
500     return;
501   }
502 }
503 
504 NS_IMETHODIMP
IsCellCropped(int32_t aRow,nsITreeColumn * aCol,bool * aIsCropped)505 TreeBoxObject::IsCellCropped(int32_t aRow, nsITreeColumn* aCol,
506                              bool* aIsCropped) {
507   *aIsCropped = false;
508   nsTreeBodyFrame* body = GetTreeBodyFrame();
509   if (body) return body->IsCellCropped(aRow, aCol, aIsCropped);
510   return NS_OK;
511 }
512 
IsCellCropped(int32_t row,nsITreeColumn * col,ErrorResult & aRv)513 bool TreeBoxObject::IsCellCropped(int32_t row, nsITreeColumn* col,
514                                   ErrorResult& aRv) {
515   bool ret;
516   aRv = IsCellCropped(row, col, &ret);
517   return ret;
518 }
519 
520 NS_IMETHODIMP
RowCountChanged(int32_t aIndex,int32_t aDelta)521 TreeBoxObject::RowCountChanged(int32_t aIndex, int32_t aDelta) {
522   nsTreeBodyFrame* body = GetTreeBodyFrame();
523   if (body) return body->RowCountChanged(aIndex, aDelta);
524   return NS_OK;
525 }
526 
527 NS_IMETHODIMP
BeginUpdateBatch()528 TreeBoxObject::BeginUpdateBatch() {
529   nsTreeBodyFrame* body = GetTreeBodyFrame();
530   if (body) return body->BeginUpdateBatch();
531   return NS_OK;
532 }
533 
534 NS_IMETHODIMP
EndUpdateBatch()535 TreeBoxObject::EndUpdateBatch() {
536   nsTreeBodyFrame* body = GetTreeBodyFrame();
537   if (body) return body->EndUpdateBatch();
538   return NS_OK;
539 }
540 
541 NS_IMETHODIMP
ClearStyleAndImageCaches()542 TreeBoxObject::ClearStyleAndImageCaches() {
543   nsTreeBodyFrame* body = GetTreeBodyFrame();
544   if (body) return body->ClearStyleAndImageCaches();
545   return NS_OK;
546 }
547 
548 NS_IMETHODIMP
RemoveImageCacheEntry(int32_t aRowIndex,nsITreeColumn * aCol)549 TreeBoxObject::RemoveImageCacheEntry(int32_t aRowIndex, nsITreeColumn* aCol) {
550   NS_ENSURE_ARG(aCol);
551   NS_ENSURE_TRUE(aRowIndex >= 0, NS_ERROR_INVALID_ARG);
552   nsTreeBodyFrame* body = GetTreeBodyFrame();
553   if (body) {
554     return body->RemoveImageCacheEntry(aRowIndex, aCol);
555   }
556   return NS_OK;
557 }
558 
RemoveImageCacheEntry(int32_t row,nsITreeColumn & col,ErrorResult & aRv)559 void TreeBoxObject::RemoveImageCacheEntry(int32_t row, nsITreeColumn& col,
560                                           ErrorResult& aRv) {
561   aRv = RemoveImageCacheEntry(row, &col);
562 }
563 
ClearCachedValues()564 void TreeBoxObject::ClearCachedValues() { mTreeBody = nullptr; }
565 
WrapObject(JSContext * aCx,JS::Handle<JSObject * > aGivenProto)566 JSObject* TreeBoxObject::WrapObject(JSContext* aCx,
567                                     JS::Handle<JSObject*> aGivenProto) {
568   return TreeBoxObjectBinding::Wrap(aCx, this, aGivenProto);
569 }
570 
571 }  // namespace dom
572 }  // namespace mozilla
573 
574 // Creation Routine
575 // ///////////////////////////////////////////////////////////////////////
576 
577 using namespace mozilla::dom;
578 
NS_NewTreeBoxObject(nsIBoxObject ** aResult)579 nsresult NS_NewTreeBoxObject(nsIBoxObject** aResult) {
580   NS_ADDREF(*aResult = new TreeBoxObject());
581   return NS_OK;
582 }
583