michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsCoreUtils.h" michael@0: michael@0: #include "nsIAccessibleTypes.h" michael@0: michael@0: #include "nsIBaseWindow.h" michael@0: #include "nsIDocShellTreeOwner.h" michael@0: #include "nsIDocument.h" michael@0: #include "nsIDOMHTMLDocument.h" michael@0: #include "nsIDOMHTMLElement.h" michael@0: #include "nsRange.h" michael@0: #include "nsIBoxObject.h" michael@0: #include "nsIDOMXULElement.h" michael@0: #include "nsIDocShell.h" michael@0: #include "nsIPresShell.h" michael@0: #include "nsPresContext.h" michael@0: #include "nsIScrollableFrame.h" michael@0: #include "nsISelectionPrivate.h" michael@0: #include "nsISelectionController.h" michael@0: #include "mozilla/dom/TouchEvent.h" michael@0: #include "mozilla/EventListenerManager.h" michael@0: #include "mozilla/EventStateManager.h" michael@0: #include "mozilla/MouseEvents.h" michael@0: #include "mozilla/TouchEvents.h" michael@0: #include "nsView.h" michael@0: #include "nsGkAtoms.h" michael@0: michael@0: #include "nsComponentManagerUtils.h" michael@0: michael@0: #include "nsITreeBoxObject.h" michael@0: #include "nsITreeColumns.h" michael@0: #include "mozilla/dom/Element.h" michael@0: michael@0: using namespace mozilla; michael@0: michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: // nsCoreUtils michael@0: //////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: bool michael@0: nsCoreUtils::HasClickListener(nsIContent *aContent) michael@0: { michael@0: NS_ENSURE_TRUE(aContent, false); michael@0: EventListenerManager* listenerManager = michael@0: aContent->GetExistingListenerManager(); michael@0: michael@0: return listenerManager && michael@0: (listenerManager->HasListenersFor(nsGkAtoms::onclick) || michael@0: listenerManager->HasListenersFor(nsGkAtoms::onmousedown) || michael@0: listenerManager->HasListenersFor(nsGkAtoms::onmouseup)); michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::DispatchClickEvent(nsITreeBoxObject *aTreeBoxObj, michael@0: int32_t aRowIndex, nsITreeColumn *aColumn, michael@0: const nsCString& aPseudoElt) michael@0: { michael@0: nsCOMPtr tcElm; michael@0: aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm)); michael@0: if (!tcElm) michael@0: return; michael@0: michael@0: nsCOMPtr tcContent(do_QueryInterface(tcElm)); michael@0: nsIDocument *document = tcContent->GetCurrentDoc(); michael@0: if (!document) michael@0: return; michael@0: michael@0: nsCOMPtr presShell = document->GetShell(); michael@0: if (!presShell) michael@0: return; michael@0: michael@0: // Ensure row is visible. michael@0: aTreeBoxObj->EnsureRowIsVisible(aRowIndex); michael@0: michael@0: // Calculate x and y coordinates. michael@0: int32_t x = 0, y = 0, width = 0, height = 0; michael@0: nsresult rv = aTreeBoxObj->GetCoordsForCellItem(aRowIndex, aColumn, michael@0: aPseudoElt, michael@0: &x, &y, &width, &height); michael@0: if (NS_FAILED(rv)) michael@0: return; michael@0: michael@0: nsCOMPtr tcXULElm(do_QueryInterface(tcElm)); michael@0: nsCOMPtr tcBoxObj; michael@0: tcXULElm->GetBoxObject(getter_AddRefs(tcBoxObj)); michael@0: michael@0: int32_t tcX = 0; michael@0: tcBoxObj->GetX(&tcX); michael@0: michael@0: int32_t tcY = 0; michael@0: tcBoxObj->GetY(&tcY); michael@0: michael@0: // Dispatch mouse events. michael@0: nsWeakFrame tcFrame = tcContent->GetPrimaryFrame(); michael@0: nsIFrame* rootFrame = presShell->GetRootFrame(); michael@0: michael@0: nsPoint offset; michael@0: nsIWidget *rootWidget = michael@0: rootFrame->GetViewExternal()->GetNearestWidget(&offset); michael@0: michael@0: nsRefPtr presContext = presShell->GetPresContext(); michael@0: michael@0: int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) + michael@0: presContext->AppUnitsToDevPixels(offset.x); michael@0: int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) + michael@0: presContext->AppUnitsToDevPixels(offset.y); michael@0: michael@0: // XUL is just desktop, so there is no real reason for senfing touch events. michael@0: DispatchMouseEvent(NS_MOUSE_BUTTON_DOWN, cnvdX, cnvdY, michael@0: tcContent, tcFrame, presShell, rootWidget); michael@0: michael@0: DispatchMouseEvent(NS_MOUSE_BUTTON_UP, cnvdX, cnvdY, michael@0: tcContent, tcFrame, presShell, rootWidget); michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::DispatchMouseEvent(uint32_t aEventType, int32_t aX, int32_t aY, michael@0: nsIContent *aContent, nsIFrame *aFrame, michael@0: nsIPresShell *aPresShell, nsIWidget *aRootWidget) michael@0: { michael@0: WidgetMouseEvent event(true, aEventType, aRootWidget, michael@0: WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal); michael@0: michael@0: event.refPoint = LayoutDeviceIntPoint(aX, aY); michael@0: michael@0: event.clickCount = 1; michael@0: event.button = WidgetMouseEvent::eLeftButton; michael@0: event.time = PR_IntervalNow(); michael@0: event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_UNKNOWN; michael@0: michael@0: nsEventStatus status = nsEventStatus_eIgnore; michael@0: aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status); michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::DispatchTouchEvent(uint32_t aEventType, int32_t aX, int32_t aY, michael@0: nsIContent* aContent, nsIFrame* aFrame, michael@0: nsIPresShell* aPresShell, nsIWidget* aRootWidget) michael@0: { michael@0: if (!dom::TouchEvent::PrefEnabled()) michael@0: return; michael@0: michael@0: WidgetTouchEvent event(true, aEventType, aRootWidget); michael@0: michael@0: event.time = PR_IntervalNow(); michael@0: michael@0: // XXX: Touch has an identifier of -1 to hint that it is synthesized. michael@0: nsRefPtr t = new dom::Touch(-1, nsIntPoint(aX, aY), michael@0: nsIntPoint(1, 1), 0.0f, 1.0f); michael@0: t->SetTarget(aContent); michael@0: event.touches.AppendElement(t); michael@0: nsEventStatus status = nsEventStatus_eIgnore; michael@0: aPresShell->HandleEventWithTarget(&event, aFrame, aContent, &status); michael@0: } michael@0: michael@0: uint32_t michael@0: nsCoreUtils::GetAccessKeyFor(nsIContent* aContent) michael@0: { michael@0: // Accesskeys are registered by @accesskey attribute only. At first check michael@0: // whether it is presented on the given element to avoid the slow michael@0: // EventStateManager::GetRegisteredAccessKey() method. michael@0: if (!aContent->HasAttr(kNameSpaceID_None, nsGkAtoms::accesskey)) michael@0: return 0; michael@0: michael@0: nsIPresShell* presShell = aContent->OwnerDoc()->GetShell(); michael@0: if (!presShell) michael@0: return 0; michael@0: michael@0: nsPresContext *presContext = presShell->GetPresContext(); michael@0: if (!presContext) michael@0: return 0; michael@0: michael@0: EventStateManager *esm = presContext->EventStateManager(); michael@0: if (!esm) michael@0: return 0; michael@0: michael@0: return esm->GetRegisteredAccessKey(aContent); michael@0: } michael@0: michael@0: nsIContent * michael@0: nsCoreUtils::GetDOMElementFor(nsIContent *aContent) michael@0: { michael@0: if (aContent->IsElement()) michael@0: return aContent; michael@0: michael@0: if (aContent->IsNodeOfType(nsINode::eTEXT)) michael@0: return aContent->GetFlattenedTreeParent(); michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: nsINode * michael@0: nsCoreUtils::GetDOMNodeFromDOMPoint(nsINode *aNode, uint32_t aOffset) michael@0: { michael@0: if (aNode && aNode->IsElement()) { michael@0: uint32_t childCount = aNode->GetChildCount(); michael@0: NS_ASSERTION(aOffset <= childCount, "Wrong offset of the DOM point!"); michael@0: michael@0: // The offset can be after last child of container node that means DOM point michael@0: // is placed immediately after the last child. In this case use the DOM node michael@0: // from the given DOM point is used as result node. michael@0: if (aOffset != childCount) michael@0: return aNode->GetChildAt(aOffset); michael@0: } michael@0: michael@0: return aNode; michael@0: } michael@0: michael@0: nsIContent* michael@0: nsCoreUtils::GetRoleContent(nsINode *aNode) michael@0: { michael@0: nsCOMPtr content(do_QueryInterface(aNode)); michael@0: if (!content) { michael@0: nsCOMPtr doc(do_QueryInterface(aNode)); michael@0: if (doc) { michael@0: nsCOMPtr htmlDoc(do_QueryInterface(aNode)); michael@0: if (htmlDoc) { michael@0: nsCOMPtr bodyElement; michael@0: htmlDoc->GetBody(getter_AddRefs(bodyElement)); michael@0: content = do_QueryInterface(bodyElement); michael@0: } michael@0: else { michael@0: return doc->GetDocumentElement(); michael@0: } michael@0: } michael@0: } michael@0: michael@0: return content; michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsAncestorOf(nsINode *aPossibleAncestorNode, michael@0: nsINode *aPossibleDescendantNode, michael@0: nsINode *aRootNode) michael@0: { michael@0: NS_ENSURE_TRUE(aPossibleAncestorNode && aPossibleDescendantNode, false); michael@0: michael@0: nsINode *parentNode = aPossibleDescendantNode; michael@0: while ((parentNode = parentNode->GetParentNode()) && michael@0: parentNode != aRootNode) { michael@0: if (parentNode == aPossibleAncestorNode) michael@0: return true; michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: nsresult michael@0: nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange, michael@0: uint32_t aScrollType) michael@0: { michael@0: nsIPresShell::ScrollAxis vertical, horizontal; michael@0: ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal); michael@0: michael@0: return ScrollSubstringTo(aFrame, aRange, vertical, horizontal); michael@0: } michael@0: michael@0: nsresult michael@0: nsCoreUtils::ScrollSubstringTo(nsIFrame* aFrame, nsRange* aRange, michael@0: nsIPresShell::ScrollAxis aVertical, michael@0: nsIPresShell::ScrollAxis aHorizontal) michael@0: { michael@0: if (!aFrame) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: nsPresContext *presContext = aFrame->PresContext(); michael@0: michael@0: nsCOMPtr selCon; michael@0: aFrame->GetSelectionController(presContext, getter_AddRefs(selCon)); michael@0: NS_ENSURE_TRUE(selCon, NS_ERROR_FAILURE); michael@0: michael@0: nsCOMPtr selection; michael@0: selCon->GetSelection(nsISelectionController::SELECTION_ACCESSIBILITY, michael@0: getter_AddRefs(selection)); michael@0: michael@0: nsCOMPtr privSel(do_QueryInterface(selection)); michael@0: selection->RemoveAllRanges(); michael@0: selection->AddRange(aRange); michael@0: michael@0: privSel->ScrollIntoViewInternal( michael@0: nsISelectionController::SELECTION_ANCHOR_REGION, michael@0: true, aVertical, aHorizontal); michael@0: michael@0: selection->CollapseToStart(); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::ScrollFrameToPoint(nsIFrame *aScrollableFrame, michael@0: nsIFrame *aFrame, michael@0: const nsIntPoint& aPoint) michael@0: { michael@0: nsIScrollableFrame* scrollableFrame = do_QueryFrame(aScrollableFrame); michael@0: if (!scrollableFrame) michael@0: return; michael@0: michael@0: nsPoint point = michael@0: aPoint.ToAppUnits(aFrame->PresContext()->AppUnitsPerDevPixel()); michael@0: nsRect frameRect = aFrame->GetScreenRectInAppUnits(); michael@0: nsPoint deltaPoint(point.x - frameRect.x, point.y - frameRect.y); michael@0: michael@0: nsPoint scrollPoint = scrollableFrame->GetScrollPosition(); michael@0: scrollPoint -= deltaPoint; michael@0: michael@0: scrollableFrame->ScrollTo(scrollPoint, nsIScrollableFrame::INSTANT); michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::ConvertScrollTypeToPercents(uint32_t aScrollType, michael@0: nsIPresShell::ScrollAxis *aVertical, michael@0: nsIPresShell::ScrollAxis *aHorizontal) michael@0: { michael@0: int16_t whereY, whereX; michael@0: nsIPresShell::WhenToScroll whenY, whenX; michael@0: switch (aScrollType) michael@0: { michael@0: case nsIAccessibleScrollType::SCROLL_TYPE_TOP_LEFT: michael@0: whereY = nsIPresShell::SCROLL_TOP; michael@0: whenY = nsIPresShell::SCROLL_ALWAYS; michael@0: whereX = nsIPresShell::SCROLL_LEFT; michael@0: whenX = nsIPresShell::SCROLL_ALWAYS; michael@0: break; michael@0: case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_RIGHT: michael@0: whereY = nsIPresShell::SCROLL_BOTTOM; michael@0: whenY = nsIPresShell::SCROLL_ALWAYS; michael@0: whereX = nsIPresShell::SCROLL_RIGHT; michael@0: whenX = nsIPresShell::SCROLL_ALWAYS; michael@0: break; michael@0: case nsIAccessibleScrollType::SCROLL_TYPE_TOP_EDGE: michael@0: whereY = nsIPresShell::SCROLL_TOP; michael@0: whenY = nsIPresShell::SCROLL_ALWAYS; michael@0: whereX = nsIPresShell::SCROLL_MINIMUM; michael@0: whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; michael@0: break; michael@0: case nsIAccessibleScrollType::SCROLL_TYPE_BOTTOM_EDGE: michael@0: whereY = nsIPresShell::SCROLL_BOTTOM; michael@0: whenY = nsIPresShell::SCROLL_ALWAYS; michael@0: whereX = nsIPresShell::SCROLL_MINIMUM; michael@0: whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; michael@0: break; michael@0: case nsIAccessibleScrollType::SCROLL_TYPE_LEFT_EDGE: michael@0: whereY = nsIPresShell::SCROLL_MINIMUM; michael@0: whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; michael@0: whereX = nsIPresShell::SCROLL_LEFT; michael@0: whenX = nsIPresShell::SCROLL_ALWAYS; michael@0: break; michael@0: case nsIAccessibleScrollType::SCROLL_TYPE_RIGHT_EDGE: michael@0: whereY = nsIPresShell::SCROLL_MINIMUM; michael@0: whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; michael@0: whereX = nsIPresShell::SCROLL_RIGHT; michael@0: whenX = nsIPresShell::SCROLL_ALWAYS; michael@0: break; michael@0: default: michael@0: whereY = nsIPresShell::SCROLL_MINIMUM; michael@0: whenY = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; michael@0: whereX = nsIPresShell::SCROLL_MINIMUM; michael@0: whenX = nsIPresShell::SCROLL_IF_NOT_FULLY_VISIBLE; michael@0: } michael@0: *aVertical = nsIPresShell::ScrollAxis(whereY, whenY); michael@0: *aHorizontal = nsIPresShell::ScrollAxis(whereX, whenX); michael@0: } michael@0: michael@0: nsIntPoint michael@0: nsCoreUtils::GetScreenCoordsForWindow(nsINode *aNode) michael@0: { michael@0: nsIntPoint coords(0, 0); michael@0: nsCOMPtr treeItem(GetDocShellFor(aNode)); michael@0: if (!treeItem) michael@0: return coords; michael@0: michael@0: nsCOMPtr treeOwner; michael@0: treeItem->GetTreeOwner(getter_AddRefs(treeOwner)); michael@0: if (!treeOwner) michael@0: return coords; michael@0: michael@0: nsCOMPtr baseWindow = do_QueryInterface(treeOwner); michael@0: if (baseWindow) michael@0: baseWindow->GetPosition(&coords.x, &coords.y); // in device pixels michael@0: michael@0: return coords; michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetDocShellFor(nsINode *aNode) michael@0: { michael@0: if (!aNode) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr docShell = aNode->OwnerDoc()->GetDocShell(); michael@0: return docShell.forget(); michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsRootDocument(nsIDocument *aDocument) michael@0: { michael@0: nsCOMPtr docShellTreeItem = aDocument->GetDocShell(); michael@0: NS_ASSERTION(docShellTreeItem, "No document shell for document!"); michael@0: michael@0: nsCOMPtr parentTreeItem; michael@0: docShellTreeItem->GetParent(getter_AddRefs(parentTreeItem)); michael@0: michael@0: return !parentTreeItem; michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsContentDocument(nsIDocument *aDocument) michael@0: { michael@0: nsCOMPtr docShellTreeItem = aDocument->GetDocShell(); michael@0: NS_ASSERTION(docShellTreeItem, "No document shell tree item for document!"); michael@0: michael@0: return (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent); michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsTabDocument(nsIDocument* aDocumentNode) michael@0: { michael@0: nsCOMPtr treeItem(aDocumentNode->GetDocShell()); michael@0: michael@0: nsCOMPtr parentTreeItem; michael@0: treeItem->GetParent(getter_AddRefs(parentTreeItem)); michael@0: michael@0: // Tab document running in own process doesn't have parent. michael@0: if (XRE_GetProcessType() == GeckoProcessType_Content) michael@0: return !parentTreeItem; michael@0: michael@0: // Parent of docshell for tab document running in chrome process is root. michael@0: nsCOMPtr rootTreeItem; michael@0: treeItem->GetRootTreeItem(getter_AddRefs(rootTreeItem)); michael@0: michael@0: return parentTreeItem == rootTreeItem; michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsErrorPage(nsIDocument *aDocument) michael@0: { michael@0: nsIURI *uri = aDocument->GetDocumentURI(); michael@0: bool isAboutScheme = false; michael@0: uri->SchemeIs("about", &isAboutScheme); michael@0: if (!isAboutScheme) michael@0: return false; michael@0: michael@0: nsAutoCString path; michael@0: uri->GetPath(path); michael@0: michael@0: NS_NAMED_LITERAL_CSTRING(neterror, "neterror"); michael@0: NS_NAMED_LITERAL_CSTRING(certerror, "certerror"); michael@0: michael@0: return StringBeginsWith(path, neterror) || StringBeginsWith(path, certerror); michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::GetID(nsIContent *aContent, nsAString& aID) michael@0: { michael@0: nsIAtom *idAttribute = aContent->GetIDAttributeName(); michael@0: return idAttribute ? aContent->GetAttr(kNameSpaceID_None, idAttribute, aID) : false; michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::GetUIntAttr(nsIContent *aContent, nsIAtom *aAttr, int32_t *aUInt) michael@0: { michael@0: nsAutoString value; michael@0: aContent->GetAttr(kNameSpaceID_None, aAttr, value); michael@0: if (!value.IsEmpty()) { michael@0: nsresult error = NS_OK; michael@0: int32_t integer = value.ToInteger(&error); michael@0: if (NS_SUCCEEDED(error) && integer > 0) { michael@0: *aUInt = integer; michael@0: return true; michael@0: } michael@0: } michael@0: michael@0: return false; michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::GetLanguageFor(nsIContent *aContent, nsIContent *aRootContent, michael@0: nsAString& aLanguage) michael@0: { michael@0: aLanguage.Truncate(); michael@0: michael@0: nsIContent *walkUp = aContent; michael@0: while (walkUp && walkUp != aRootContent && michael@0: !walkUp->GetAttr(kNameSpaceID_None, nsGkAtoms::lang, aLanguage)) michael@0: walkUp = walkUp->GetParent(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetTreeBodyBoxObject(nsITreeBoxObject *aTreeBoxObj) michael@0: { michael@0: nsCOMPtr tcElm; michael@0: aTreeBoxObj->GetTreeBody(getter_AddRefs(tcElm)); michael@0: nsCOMPtr tcXULElm(do_QueryInterface(tcElm)); michael@0: if (!tcXULElm) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr boxObj; michael@0: tcXULElm->GetBoxObject(getter_AddRefs(boxObj)); michael@0: return boxObj.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetTreeBoxObject(nsIContent *aContent) michael@0: { michael@0: // Find DOMNode's parents recursively until reach the tag michael@0: nsIContent* currentContent = aContent; michael@0: while (currentContent) { michael@0: if (currentContent->NodeInfo()->Equals(nsGkAtoms::tree, michael@0: kNameSpaceID_XUL)) { michael@0: // We will get the nsITreeBoxObject from the tree node michael@0: nsCOMPtr xulElement(do_QueryInterface(currentContent)); michael@0: if (xulElement) { michael@0: nsCOMPtr box; michael@0: xulElement->GetBoxObject(getter_AddRefs(box)); michael@0: nsCOMPtr treeBox(do_QueryInterface(box)); michael@0: if (treeBox) michael@0: return treeBox.forget(); michael@0: } michael@0: } michael@0: currentContent = currentContent->GetFlattenedTreeParent(); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetFirstSensibleColumn(nsITreeBoxObject *aTree) michael@0: { michael@0: nsCOMPtr cols; michael@0: aTree->GetColumns(getter_AddRefs(cols)); michael@0: if (!cols) michael@0: return nullptr; michael@0: michael@0: nsCOMPtr column; michael@0: cols->GetFirstColumn(getter_AddRefs(column)); michael@0: if (column && IsColumnHidden(column)) michael@0: return GetNextSensibleColumn(column); michael@0: michael@0: return column.forget(); michael@0: } michael@0: michael@0: uint32_t michael@0: nsCoreUtils::GetSensibleColumnCount(nsITreeBoxObject *aTree) michael@0: { michael@0: uint32_t count = 0; michael@0: michael@0: nsCOMPtr cols; michael@0: aTree->GetColumns(getter_AddRefs(cols)); michael@0: if (!cols) michael@0: return count; michael@0: michael@0: nsCOMPtr column; michael@0: cols->GetFirstColumn(getter_AddRefs(column)); michael@0: michael@0: while (column) { michael@0: if (!IsColumnHidden(column)) michael@0: count++; michael@0: michael@0: nsCOMPtr nextColumn; michael@0: column->GetNext(getter_AddRefs(nextColumn)); michael@0: column.swap(nextColumn); michael@0: } michael@0: michael@0: return count; michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetSensibleColumnAt(nsITreeBoxObject *aTree, uint32_t aIndex) michael@0: { michael@0: uint32_t idx = aIndex; michael@0: michael@0: nsCOMPtr column = GetFirstSensibleColumn(aTree); michael@0: while (column) { michael@0: if (idx == 0) michael@0: return column.forget(); michael@0: michael@0: idx--; michael@0: column = GetNextSensibleColumn(column); michael@0: } michael@0: michael@0: return nullptr; michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetNextSensibleColumn(nsITreeColumn *aColumn) michael@0: { michael@0: nsCOMPtr nextColumn; michael@0: aColumn->GetNext(getter_AddRefs(nextColumn)); michael@0: michael@0: while (nextColumn && IsColumnHidden(nextColumn)) { michael@0: nsCOMPtr tempColumn; michael@0: nextColumn->GetNext(getter_AddRefs(tempColumn)); michael@0: nextColumn.swap(tempColumn); michael@0: } michael@0: michael@0: return nextColumn.forget(); michael@0: } michael@0: michael@0: already_AddRefed michael@0: nsCoreUtils::GetPreviousSensibleColumn(nsITreeColumn *aColumn) michael@0: { michael@0: nsCOMPtr prevColumn; michael@0: aColumn->GetPrevious(getter_AddRefs(prevColumn)); michael@0: michael@0: while (prevColumn && IsColumnHidden(prevColumn)) { michael@0: nsCOMPtr tempColumn; michael@0: prevColumn->GetPrevious(getter_AddRefs(tempColumn)); michael@0: prevColumn.swap(tempColumn); michael@0: } michael@0: michael@0: return prevColumn.forget(); michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsColumnHidden(nsITreeColumn *aColumn) michael@0: { michael@0: nsCOMPtr element; michael@0: aColumn->GetElement(getter_AddRefs(element)); michael@0: nsCOMPtr content = do_QueryInterface(element); michael@0: return content->AttrValueIs(kNameSpaceID_None, nsGkAtoms::hidden, michael@0: nsGkAtoms::_true, eCaseMatters); michael@0: } michael@0: michael@0: void michael@0: nsCoreUtils::ScrollTo(nsIPresShell* aPresShell, nsIContent* aContent, michael@0: uint32_t aScrollType) michael@0: { michael@0: nsIPresShell::ScrollAxis vertical, horizontal; michael@0: ConvertScrollTypeToPercents(aScrollType, &vertical, &horizontal); michael@0: aPresShell->ScrollContentIntoView(aContent, vertical, horizontal, michael@0: nsIPresShell::SCROLL_OVERFLOW_HIDDEN); michael@0: } michael@0: michael@0: bool michael@0: nsCoreUtils::IsWhitespaceString(const nsSubstring& aString) michael@0: { michael@0: nsSubstring::const_char_iterator iterBegin, iterEnd; michael@0: michael@0: aString.BeginReading(iterBegin); michael@0: aString.EndReading(iterEnd); michael@0: michael@0: while (iterBegin != iterEnd && IsWhitespace(*iterBegin)) michael@0: ++iterBegin; michael@0: michael@0: return iterBegin == iterEnd; michael@0: }