Bug 1769952 - Fix running raptor on a Win10-64 VM r=sparky
[gecko.git] / dom / xul / XULTreeElement.cpp
blobe190b22556c13e059a846c275b4f14ea36be279e
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/. */
7 #include "nsCOMPtr.h"
8 #include "nsTreeContentView.h"
9 #include "nsITreeSelection.h"
10 #include "ChildIterator.h"
11 #include "nsError.h"
12 #include "nsTreeBodyFrame.h"
13 #include "mozilla/dom/DOMRect.h"
14 #include "mozilla/dom/BindingUtils.h"
15 #include "mozilla/dom/Element.h"
16 #include "mozilla/dom/ToJSValue.h"
17 #include "mozilla/dom/XULTreeElement.h"
18 #include "mozilla/dom/XULTreeElementBinding.h"
20 namespace mozilla::dom {
22 NS_IMPL_ISUPPORTS_CYCLE_COLLECTION_INHERITED_0(XULTreeElement, nsXULElement)
23 NS_IMPL_CYCLE_COLLECTION_INHERITED(XULTreeElement, nsXULElement, mView)
25 JSObject* XULTreeElement::WrapNode(JSContext* aCx,
26 JS::Handle<JSObject*> aGivenProto) {
27 return XULTreeElement_Binding::Wrap(aCx, this, aGivenProto);
30 void XULTreeElement::UnbindFromTree(bool aNullParent) {
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);
38 mView->SetTree(nullptr); // Break the circular ref between the view and us.
40 mView = nullptr;
42 nsXULElement::UnbindFromTree(aNullParent);
45 void XULTreeElement::DestroyContent() {
46 // Drop the view's ref to us.
47 if (mView) {
48 nsCOMPtr<nsITreeSelection> sel;
49 mView->GetSelection(getter_AddRefs(sel));
50 if (sel) {
51 sel->SetTree(nullptr);
53 mView->SetTree(nullptr); // Break the circular ref between the view and us.
55 mView = nullptr;
57 nsXULElement::DestroyContent();
60 static nsIContent* FindBodyElement(nsIContent* aParent) {
61 mozilla::dom::FlattenedChildIterator iter(aParent);
62 for (nsIContent* content = iter.GetNextChild(); content;
63 content = iter.GetNextChild()) {
64 mozilla::dom::NodeInfo* ni = content->NodeInfo();
65 if (ni->Equals(nsGkAtoms::treechildren, kNameSpaceID_XUL)) {
66 return content;
67 } else if (ni->Equals(nsGkAtoms::tree, kNameSpaceID_XUL)) {
68 // There are nesting tree elements. Only the innermost should
69 // find the treechilren.
70 return nullptr;
71 } else if (content->IsElement() &&
72 !ni->Equals(nsGkAtoms::_template, kNameSpaceID_XUL)) {
73 nsIContent* result = FindBodyElement(content);
74 if (result) return result;
78 return nullptr;
81 nsTreeBodyFrame* XULTreeElement::GetTreeBodyFrame(FlushType aFlushType) {
82 MOZ_ASSERT(aFlushType == FlushType::Frames ||
83 aFlushType == FlushType::Layout || aFlushType == FlushType::None);
84 nsCOMPtr<nsIContent> kungFuDeathGrip = this; // keep a reference
86 // Make sure our frames are up to date, and layout as needed. We
87 // have to do this before checking for our cached mTreeBody, since
88 // it might go away on style flush, and in any case if aFlushLayout
89 // is true we need to make sure to flush no matter what.
90 if (aFlushType != FlushType::None) {
91 if (RefPtr<Document> doc = GetComposedDoc()) {
92 doc->FlushPendingNotifications(aFlushType);
96 if (mTreeBody) {
97 // Have one cached already.
98 return mTreeBody;
101 if (nsCOMPtr<nsIContent> tree = FindBodyElement(this)) {
102 mTreeBody = do_QueryFrame(tree->GetPrimaryFrame());
105 return mTreeBody;
108 already_AddRefed<nsITreeView> XULTreeElement::GetView(FlushType aFlushType) {
109 if (!mTreeBody) {
110 if (!GetTreeBodyFrame(aFlushType)) {
111 return nullptr;
114 if (mView) {
115 nsCOMPtr<nsITreeView> view;
116 // Our new frame needs to initialise itself
117 mTreeBody->GetView(getter_AddRefs(view));
118 return view.forget();
121 if (!mView) {
122 // No tree builder, create a tree content view.
123 if (NS_FAILED(NS_NewTreeContentView(getter_AddRefs(mView)))) {
124 return nullptr;
127 // Initialise the frame and view
128 mTreeBody->SetView(mView);
131 return do_AddRef(mView);
134 void XULTreeElement::SetView(nsITreeView* aView, CallerType aCallerType,
135 ErrorResult& aRv) {
136 if (aCallerType != CallerType::System) {
137 // Don't trust views coming from random places.
138 aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
139 return;
142 mView = aView;
143 nsTreeBodyFrame* body = GetTreeBodyFrame();
144 if (body) {
145 body->SetView(aView);
149 bool XULTreeElement::Focused() {
150 nsTreeBodyFrame* body = GetTreeBodyFrame();
151 if (body) {
152 return body->GetFocused();
154 return false;
157 void XULTreeElement::SetFocused(bool aFocused) {
158 nsTreeBodyFrame* body = GetTreeBodyFrame();
159 if (body) {
160 body->SetFocused(aFocused);
164 already_AddRefed<Element> XULTreeElement::GetTreeBody() {
165 nsTreeBodyFrame* body = GetTreeBodyFrame();
166 if (body) {
167 nsCOMPtr<Element> element;
168 body->GetTreeBody(getter_AddRefs(element));
169 return element.forget();
172 return nullptr;
175 already_AddRefed<nsTreeColumns> XULTreeElement::GetColumns(
176 FlushType aFlushType) {
177 if (nsTreeBodyFrame* body = GetTreeBodyFrame(aFlushType)) {
178 return body->Columns();
180 return nullptr;
183 int32_t XULTreeElement::RowHeight() {
184 nsTreeBodyFrame* body = GetTreeBodyFrame();
185 if (body) {
186 return body->RowHeight();
188 return 0;
191 int32_t XULTreeElement::RowWidth() {
192 nsTreeBodyFrame* body = GetTreeBodyFrame();
193 if (body) {
194 return body->RowWidth();
196 return 0;
199 int32_t XULTreeElement::GetFirstVisibleRow() {
200 nsTreeBodyFrame* body = GetTreeBodyFrame();
201 if (body) {
202 return body->FirstVisibleRow();
204 return 0;
207 int32_t XULTreeElement::GetLastVisibleRow() {
208 nsTreeBodyFrame* body = GetTreeBodyFrame();
209 if (body) {
210 return body->LastVisibleRow();
212 return 0;
215 int32_t XULTreeElement::HorizontalPosition() {
216 nsTreeBodyFrame* body = GetTreeBodyFrame();
217 if (body) {
218 return body->GetHorizontalPosition();
220 return 0;
223 int32_t XULTreeElement::GetPageLength() {
224 nsTreeBodyFrame* body = GetTreeBodyFrame();
225 if (body) {
226 return body->PageLength();
228 return 0;
231 void XULTreeElement::EnsureRowIsVisible(int32_t aRow) {
232 nsTreeBodyFrame* body = GetTreeBodyFrame();
233 if (body) {
234 body->EnsureRowIsVisible(aRow);
238 void XULTreeElement::EnsureCellIsVisible(int32_t aRow, nsTreeColumn* aCol,
239 ErrorResult& aRv) {
240 nsTreeBodyFrame* body = GetTreeBodyFrame();
241 if (body) {
242 nsresult rv = body->EnsureCellIsVisible(aRow, aCol);
243 if (NS_FAILED(rv)) {
244 aRv.Throw(rv);
249 void XULTreeElement::ScrollToRow(int32_t aRow) {
250 nsTreeBodyFrame* body = GetTreeBodyFrame(FlushType::Layout);
251 if (!body) {
252 return;
255 body->ScrollToRow(aRow);
258 void XULTreeElement::ScrollByLines(int32_t aNumLines) {
259 nsTreeBodyFrame* body = GetTreeBodyFrame();
260 if (!body) {
261 return;
263 body->ScrollByLines(aNumLines);
266 void XULTreeElement::ScrollByPages(int32_t aNumPages) {
267 nsTreeBodyFrame* body = GetTreeBodyFrame();
268 if (body) {
269 body->ScrollByPages(aNumPages);
273 void XULTreeElement::Invalidate() {
274 nsTreeBodyFrame* body = GetTreeBodyFrame();
275 if (body) {
276 body->Invalidate();
280 void XULTreeElement::InvalidateColumn(nsTreeColumn* aCol) {
281 nsTreeBodyFrame* body = GetTreeBodyFrame();
282 if (body) {
283 body->InvalidateColumn(aCol);
287 void XULTreeElement::InvalidateRow(int32_t aIndex) {
288 nsTreeBodyFrame* body = GetTreeBodyFrame();
289 if (body) {
290 body->InvalidateRow(aIndex);
294 void XULTreeElement::InvalidateCell(int32_t aRow, nsTreeColumn* aCol) {
295 nsTreeBodyFrame* body = GetTreeBodyFrame();
296 if (body) {
297 body->InvalidateCell(aRow, aCol);
301 void XULTreeElement::InvalidateRange(int32_t aStart, int32_t aEnd) {
302 nsTreeBodyFrame* body = GetTreeBodyFrame();
303 if (body) {
304 body->InvalidateRange(aStart, aEnd);
308 int32_t XULTreeElement::GetRowAt(int32_t x, int32_t y) {
309 nsTreeBodyFrame* body = GetTreeBodyFrame();
310 if (!body) {
311 return 0;
313 return body->GetRowAt(x, y);
316 void XULTreeElement::GetCellAt(int32_t aX, int32_t aY, TreeCellInfo& aRetVal,
317 ErrorResult& aRv) {
318 aRetVal.mRow = 0;
319 aRetVal.mCol = nullptr;
321 nsTreeBodyFrame* body = GetTreeBodyFrame();
322 if (body) {
323 nsAutoCString element;
324 body->GetCellAt(aX, aY, &aRetVal.mRow, getter_AddRefs(aRetVal.mCol),
325 element);
326 CopyUTF8toUTF16(element, aRetVal.mChildElt);
330 nsIntRect XULTreeElement::GetCoordsForCellItem(int32_t aRow, nsTreeColumn* aCol,
331 const nsAString& aElement,
332 nsresult& rv) {
333 rv = NS_OK;
334 nsIntRect rect;
336 nsTreeBodyFrame* body = GetTreeBodyFrame();
337 NS_ConvertUTF16toUTF8 element(aElement);
338 if (body) {
339 rv = body->GetCoordsForCellItem(aRow, aCol, element, &rect.x, &rect.y,
340 &rect.width, &rect.height);
343 return rect;
346 already_AddRefed<DOMRect> XULTreeElement::GetCoordsForCellItem(
347 int32_t aRow, nsTreeColumn& aCol, const nsAString& aElement,
348 ErrorResult& aRv) {
349 nsresult rv;
350 nsIntRect rect = GetCoordsForCellItem(aRow, &aCol, aElement, rv);
351 aRv = rv;
353 RefPtr<DOMRect> domRect = new DOMRect(ToSupports(OwnerDoc()), rect.x, rect.y,
354 rect.width, rect.height);
355 return domRect.forget();
358 bool XULTreeElement::IsCellCropped(int32_t aRow, nsTreeColumn* aCol,
359 ErrorResult& aRv) {
360 bool cropped = false;
362 nsTreeBodyFrame* body = GetTreeBodyFrame();
363 if (body) {
364 aRv = body->IsCellCropped(aRow, aCol, &cropped);
367 return cropped;
370 void XULTreeElement::RowCountChanged(int32_t aIndex, int32_t aDelta) {
371 nsTreeBodyFrame* body = GetTreeBodyFrame();
372 if (body) {
373 body->RowCountChanged(aIndex, aDelta);
377 void XULTreeElement::BeginUpdateBatch() {
378 nsTreeBodyFrame* body = GetTreeBodyFrame();
379 if (body) {
380 body->BeginUpdateBatch();
384 void XULTreeElement::EndUpdateBatch() {
385 nsTreeBodyFrame* body = GetTreeBodyFrame();
386 if (body) {
387 body->EndUpdateBatch();
391 void XULTreeElement::ClearStyleAndImageCaches() {
392 nsTreeBodyFrame* body = GetTreeBodyFrame();
393 if (body) {
394 body->ClearStyleAndImageCaches();
398 void XULTreeElement::RemoveImageCacheEntry(int32_t aRowIndex,
399 nsTreeColumn& aCol,
400 ErrorResult& aRv) {
401 if (NS_WARN_IF(aRowIndex < 0)) {
402 aRv.Throw(NS_ERROR_INVALID_ARG);
403 return;
405 nsTreeBodyFrame* body = GetTreeBodyFrame();
406 if (body) {
407 body->RemoveImageCacheEntry(aRowIndex, &aCol);
411 } // namespace mozilla::dom