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 michael@0: michael@0: #include "mozilla/Preferences.h" michael@0: #include "mozilla/dom/Selection.h" michael@0: #include "mozilla/dom/Element.h" michael@0: #include "mozilla/mozalloc.h" michael@0: #include "nsAString.h" michael@0: #include "nsAlgorithm.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "nsCOMPtr.h" michael@0: #include "nsComputedDOMStyle.h" michael@0: #include "nsDebug.h" michael@0: #include "nsEditProperty.h" michael@0: #include "nsEditRules.h" michael@0: #include "nsEditor.h" michael@0: #include "nsEditorUtils.h" michael@0: #include "nsError.h" michael@0: #include "nsGkAtoms.h" michael@0: #include "nsHTMLCSSUtils.h" michael@0: #include "nsHTMLEditRules.h" michael@0: #include "nsHTMLEditUtils.h" michael@0: #include "nsHTMLEditor.h" michael@0: #include "nsHTMLObjectResizer.h" michael@0: #include "nsIContent.h" michael@0: #include "nsROCSSPrimitiveValue.h" michael@0: #include "nsIDOMCSSStyleDeclaration.h" michael@0: #include "nsIDOMElement.h" michael@0: #include "nsIDOMEventListener.h" michael@0: #include "nsIDOMEventTarget.h" michael@0: #include "nsIDOMNode.h" michael@0: #include "nsDOMCSSRGBColor.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "nsIEditor.h" michael@0: #include "nsIHTMLEditor.h" michael@0: #include "nsIHTMLObjectResizer.h" michael@0: #include "nsINode.h" michael@0: #include "nsIPresShell.h" michael@0: #include "nsISelection.h" michael@0: #include "nsISupportsImpl.h" michael@0: #include "nsISupportsUtils.h" michael@0: #include "nsLiteralString.h" michael@0: #include "nsReadableUtils.h" michael@0: #include "nsString.h" michael@0: #include "nsStringFwd.h" michael@0: #include "nsTextEditRules.h" michael@0: #include "nsTextEditUtils.h" michael@0: #include "nscore.h" michael@0: #include michael@0: michael@0: using namespace mozilla; michael@0: using namespace mozilla::dom; michael@0: michael@0: #define BLACK_BG_RGB_TRIGGER 0xd0 michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::AbsolutePositionSelection(bool aEnabled) michael@0: { michael@0: nsAutoEditBatch beginBatching(this); michael@0: nsAutoRules beginRulesSniffing(this, michael@0: aEnabled ? EditAction::setAbsolutePosition : michael@0: EditAction::removeAbsolutePosition, michael@0: nsIEditor::eNext); michael@0: michael@0: // the line below does not match the code; should it be removed? michael@0: // Find out if the selection is collapsed: michael@0: nsRefPtr selection = GetSelection(); michael@0: NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); michael@0: michael@0: nsTextRulesInfo ruleInfo(aEnabled ? EditAction::setAbsolutePosition : michael@0: EditAction::removeAbsolutePosition); michael@0: bool cancel, handled; michael@0: // Protect the edit rules object from dying michael@0: nsCOMPtr kungFuDeathGrip(mRules); michael@0: nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); michael@0: if (NS_FAILED(res) || cancel) michael@0: return res; michael@0: michael@0: return mRules->DidDoAction(selection, &ruleInfo, res); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval) michael@0: { michael@0: nsCOMPtr element; michael@0: nsresult res = GetSelectionContainer(getter_AddRefs(element)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: nsAutoString positionStr; michael@0: nsCOMPtr node = do_QueryInterface(element); michael@0: nsCOMPtr resultNode; michael@0: michael@0: while (!resultNode && node && !nsEditor::NodeIsType(node, nsEditProperty::html)) { michael@0: res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition, michael@0: positionStr); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: if (positionStr.EqualsLiteral("absolute")) michael@0: resultNode = node; michael@0: else { michael@0: nsCOMPtr parentNode; michael@0: res = node->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: node.swap(parentNode); michael@0: } michael@0: } michael@0: michael@0: element = do_QueryInterface(resultNode ); michael@0: *_retval = element; michael@0: NS_IF_ADDREF(*_retval); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(bool *aIsSelectionContainerAbsolutelyPositioned) michael@0: { michael@0: *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nullptr); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetAbsolutePositioningEnabled(bool * aIsEnabled) michael@0: { michael@0: *aIsEnabled = mIsAbsolutelyPositioningEnabled; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled) michael@0: { michael@0: mIsAbsolutelyPositioningEnabled = aIsEnabled; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement, michael@0: int32_t aChange, michael@0: int32_t * aReturn) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aElement); michael@0: NS_ENSURE_ARG_POINTER(aReturn); michael@0: if (!aChange) // early way out, no change michael@0: return NS_OK; michael@0: michael@0: int32_t zIndex; michael@0: nsresult res = GetElementZIndex(aElement, &zIndex); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: zIndex = std::max(zIndex + aChange, 0); michael@0: SetElementZIndex(aElement, zIndex); michael@0: *aReturn = zIndex; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement, michael@0: int32_t aZindex) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aElement); michael@0: michael@0: nsAutoString zIndexStr; michael@0: zIndexStr.AppendInt(aZindex); michael@0: michael@0: mHTMLCSSUtils->SetCSSProperty(aElement, michael@0: nsEditProperty::cssZIndex, michael@0: zIndexStr, michael@0: false); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::RelativeChangeZIndex(int32_t aChange) michael@0: { michael@0: nsAutoEditBatch beginBatching(this); michael@0: nsAutoRules beginRulesSniffing(this, michael@0: (aChange < 0) ? EditAction::decreaseZIndex : michael@0: EditAction::increaseZIndex, michael@0: nsIEditor::eNext); michael@0: michael@0: // brade: can we get rid of this comment? michael@0: // Find out if the selection is collapsed: michael@0: nsRefPtr selection = GetSelection(); michael@0: NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); michael@0: nsTextRulesInfo ruleInfo(aChange < 0 ? EditAction::decreaseZIndex : michael@0: EditAction::increaseZIndex); michael@0: bool cancel, handled; michael@0: // Protect the edit rules object from dying michael@0: nsCOMPtr kungFuDeathGrip(mRules); michael@0: nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); michael@0: if (cancel || NS_FAILED(res)) michael@0: return res; michael@0: michael@0: return mRules->DidDoAction(selection, &ruleInfo, res); michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement, michael@0: int32_t * aZindex) michael@0: { michael@0: nsAutoString zIndexStr; michael@0: *aZindex = 0; michael@0: michael@0: nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement, michael@0: nsEditProperty::cssZIndex, michael@0: zIndexStr); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: if (zIndexStr.EqualsLiteral("auto")) { michael@0: // we have to look at the positioned ancestors michael@0: // cf. CSS 2 spec section 9.9.1 michael@0: nsCOMPtr parentNode; michael@0: res = aElement->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: nsCOMPtr node = parentNode; michael@0: nsAutoString positionStr; michael@0: while (node && michael@0: zIndexStr.EqualsLiteral("auto") && michael@0: !nsTextEditUtils::IsBody(node)) { michael@0: res = mHTMLCSSUtils->GetComputedProperty(node, michael@0: nsEditProperty::cssPosition, michael@0: positionStr); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: if (positionStr.EqualsLiteral("absolute")) { michael@0: // ah, we found one, what's its z-index ? If its z-index is auto, michael@0: // we have to continue climbing the document's tree michael@0: res = mHTMLCSSUtils->GetComputedProperty(node, michael@0: nsEditProperty::cssZIndex, michael@0: zIndexStr); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: } michael@0: res = node->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: node = parentNode; michael@0: } michael@0: } michael@0: michael@0: if (!zIndexStr.EqualsLiteral("auto")) { michael@0: nsresult errorCode; michael@0: *aZindex = zIndexStr.ToInteger(&errorCode); michael@0: } michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn) michael@0: { michael@0: // let's create a grabber through the element factory michael@0: nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"), michael@0: aParentNode, michael@0: NS_LITERAL_STRING("mozGrabber"), michael@0: false, michael@0: aReturn); michael@0: michael@0: NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE); michael@0: michael@0: // add the mouse listener so we can detect a click on a resizer michael@0: nsCOMPtr evtTarget(do_QueryInterface(*aReturn)); michael@0: evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), michael@0: mEventListener, false); michael@0: michael@0: return res; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::RefreshGrabber() michael@0: { michael@0: NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER); michael@0: michael@0: nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject, michael@0: mPositionedObjectX, michael@0: mPositionedObjectY, michael@0: mPositionedObjectWidth, michael@0: mPositionedObjectHeight, michael@0: mPositionedObjectBorderLeft, michael@0: mPositionedObjectBorderTop, michael@0: mPositionedObjectMarginLeft, michael@0: mPositionedObjectMarginTop); michael@0: michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: SetAnonymousElementPosition(mPositionedObjectX+12, michael@0: mPositionedObjectY-14, michael@0: mGrabber); michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::HideGrabber() michael@0: { michael@0: nsresult res = michael@0: mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos")); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: mAbsolutelyPositionedObject = nullptr; michael@0: NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER); michael@0: michael@0: // get the presshell's document observer interface. michael@0: nsCOMPtr ps = GetPresShell(); michael@0: // We allow the pres shell to be null; when it is, we presume there michael@0: // are no document observers to notify, but we still want to michael@0: // UnbindFromTree. michael@0: michael@0: nsCOMPtr parentNode; michael@0: res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: nsCOMPtr parentContent = do_QueryInterface(parentNode); michael@0: NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER); michael@0: michael@0: DeleteRefToAnonymousNode(mGrabber, parentContent, ps); michael@0: mGrabber = nullptr; michael@0: DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); michael@0: mPositioningShadow = nullptr; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aElement); michael@0: michael@0: if (mGrabber) { michael@0: NS_ERROR("call HideGrabber first"); michael@0: return NS_ERROR_UNEXPECTED; michael@0: } michael@0: michael@0: nsAutoString classValue; michael@0: nsresult res = CheckPositionedElementBGandFG(aElement, classValue); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"), michael@0: classValue); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: // first, let's keep track of that element... michael@0: mAbsolutelyPositionedObject = aElement; michael@0: michael@0: nsCOMPtr parentNode; michael@0: res = aElement->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: res = CreateGrabber(parentNode, getter_AddRefs(mGrabber)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: // and set its position michael@0: return RefreshGrabber(); michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLEditor::StartMoving(nsIDOMElement *aHandle) michael@0: { michael@0: nsCOMPtr parentNode; michael@0: nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: // now, let's create the resizing shadow michael@0: res = CreateShadow(getter_AddRefs(mPositioningShadow), michael@0: parentNode, mAbsolutelyPositionedObject); michael@0: NS_ENSURE_SUCCESS(res,res); michael@0: res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject, michael@0: mPositionedObjectX, mPositionedObjectY); michael@0: NS_ENSURE_SUCCESS(res,res); michael@0: michael@0: // make the shadow appear michael@0: mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class")); michael@0: michael@0: // position it michael@0: mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, michael@0: NS_LITERAL_STRING("width"), michael@0: mPositionedObjectWidth); michael@0: mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, michael@0: NS_LITERAL_STRING("height"), michael@0: mPositionedObjectHeight); michael@0: michael@0: mIsMoving = true; michael@0: return res; michael@0: } michael@0: michael@0: void michael@0: nsHTMLEditor::SnapToGrid(int32_t & newX, int32_t & newY) michael@0: { michael@0: if (mSnapToGridEnabled && mGridSize) { michael@0: newX = (int32_t) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize; michael@0: newY = (int32_t) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize; michael@0: } michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLEditor::GrabberClicked() michael@0: { michael@0: // add a mouse move listener to the editor michael@0: nsresult res = NS_OK; michael@0: if (!mMouseMotionListenerP) { michael@0: mMouseMotionListenerP = new ResizerMouseMotionListener(this); michael@0: if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;} michael@0: michael@0: nsCOMPtr piTarget = GetDOMEventTarget(); michael@0: NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE); michael@0: michael@0: res = piTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), michael@0: mMouseMotionListenerP, michael@0: false, false); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), michael@0: "failed to register mouse motion listener"); michael@0: } michael@0: mGrabberClicked = true; michael@0: return res; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLEditor::EndMoving() michael@0: { michael@0: if (mPositioningShadow) { michael@0: nsCOMPtr ps = GetPresShell(); michael@0: NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED); michael@0: michael@0: nsCOMPtr parentNode; michael@0: nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: nsCOMPtr parentContent( do_QueryInterface(parentNode) ); michael@0: NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE); michael@0: michael@0: DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); michael@0: michael@0: mPositioningShadow = nullptr; michael@0: } michael@0: nsCOMPtr piTarget = GetDOMEventTarget(); michael@0: michael@0: if (piTarget && mMouseMotionListenerP) { michael@0: #ifdef DEBUG michael@0: nsresult res = michael@0: #endif michael@0: piTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), michael@0: mMouseMotionListenerP, michael@0: false); michael@0: NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener"); michael@0: } michael@0: mMouseMotionListenerP = nullptr; michael@0: michael@0: mGrabberClicked = false; michael@0: mIsMoving = false; michael@0: nsCOMPtr selection; michael@0: GetSelection(getter_AddRefs(selection)); michael@0: if (!selection) { michael@0: return NS_ERROR_NOT_INITIALIZED; michael@0: } michael@0: return CheckSelectionStateForAnonymousButtons(selection); michael@0: } michael@0: nsresult michael@0: nsHTMLEditor::SetFinalPosition(int32_t aX, int32_t aY) michael@0: { michael@0: nsresult res = EndMoving(); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: michael@0: // we have now to set the new width and height of the resized object michael@0: // we don't set the x and y position because we don't control that in michael@0: // a normal HTML layout michael@0: int32_t newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft); michael@0: int32_t newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop); michael@0: michael@0: SnapToGrid(newX, newY); michael@0: michael@0: nsAutoString x, y; michael@0: x.AppendInt(newX); michael@0: y.AppendInt(newY); michael@0: michael@0: // we want one transaction only from a user's point of view michael@0: nsAutoEditBatch batchIt(this); michael@0: michael@0: mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject, michael@0: nsEditProperty::cssTop, michael@0: newY, michael@0: false); michael@0: mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject, michael@0: nsEditProperty::cssLeft, michael@0: newX, michael@0: false); michael@0: // keep track of that size michael@0: mPositionedObjectX = newX; michael@0: mPositionedObjectY = newY; michael@0: michael@0: return RefreshResizers(); michael@0: } michael@0: michael@0: void michael@0: nsHTMLEditor::AddPositioningOffset(int32_t & aX, int32_t & aY) michael@0: { michael@0: // Get the positioning offset michael@0: int32_t positioningOffset = michael@0: Preferences::GetInt("editor.positioning.offset", 0); michael@0: michael@0: aX += positioningOffset; michael@0: aY += positioningOffset; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement, michael@0: bool aEnabled) michael@0: { michael@0: NS_ENSURE_ARG_POINTER(aElement); michael@0: michael@0: nsAutoString positionStr; michael@0: mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition, michael@0: positionStr); michael@0: bool isPositioned = (positionStr.EqualsLiteral("absolute")); michael@0: michael@0: // nothing to do if the element is already in the state we want michael@0: if (isPositioned == aEnabled) michael@0: return NS_OK; michael@0: michael@0: nsAutoEditBatch batchIt(this); michael@0: michael@0: if (aEnabled) { michael@0: int32_t x, y; michael@0: GetElementOrigin(aElement, x, y); michael@0: michael@0: mHTMLCSSUtils->SetCSSProperty(aElement, michael@0: nsEditProperty::cssPosition, michael@0: NS_LITERAL_STRING("absolute"), michael@0: false); michael@0: michael@0: AddPositioningOffset(x, y); michael@0: SnapToGrid(x, y); michael@0: SetElementPosition(aElement, x, y); michael@0: michael@0: // we may need to create a br if the positioned element is alone in its michael@0: // container michael@0: nsCOMPtr element = do_QueryInterface(aElement); michael@0: NS_ENSURE_STATE(element); michael@0: michael@0: nsINode* parentNode = element->GetParentNode(); michael@0: if (parentNode->GetChildCount() == 1) { michael@0: nsCOMPtr brNode; michael@0: nsresult res = CreateBR(parentNode->AsDOMNode(), 0, address_of(brNode)); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: } michael@0: } michael@0: else { michael@0: mHTMLCSSUtils->RemoveCSSProperty(aElement, michael@0: nsEditProperty::cssPosition, michael@0: EmptyString(), false); michael@0: mHTMLCSSUtils->RemoveCSSProperty(aElement, michael@0: nsEditProperty::cssTop, michael@0: EmptyString(), false); michael@0: mHTMLCSSUtils->RemoveCSSProperty(aElement, michael@0: nsEditProperty::cssLeft, michael@0: EmptyString(), false); michael@0: mHTMLCSSUtils->RemoveCSSProperty(aElement, michael@0: nsEditProperty::cssZIndex, michael@0: EmptyString(), false); michael@0: michael@0: if (!nsHTMLEditUtils::IsImage(aElement)) { michael@0: mHTMLCSSUtils->RemoveCSSProperty(aElement, michael@0: nsEditProperty::cssWidth, michael@0: EmptyString(), false); michael@0: mHTMLCSSUtils->RemoveCSSProperty(aElement, michael@0: nsEditProperty::cssHeight, michael@0: EmptyString(), false); michael@0: } michael@0: michael@0: nsCOMPtr element = do_QueryInterface(aElement); michael@0: if (element && element->IsHTML(nsGkAtoms::div) && !HasStyleOrIdOrClass(element)) { michael@0: nsRefPtr htmlRules = static_cast(mRules.get()); michael@0: NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE); michael@0: nsresult res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: res = RemoveContainer(aElement); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: } michael@0: } michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::SetSnapToGridEnabled(bool aEnabled) michael@0: { michael@0: mSnapToGridEnabled = aEnabled; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetSnapToGridEnabled(bool * aIsEnabled) michael@0: { michael@0: *aIsEnabled = mSnapToGridEnabled; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::SetGridSize(uint32_t aSize) michael@0: { michael@0: mGridSize = aSize; michael@0: return NS_OK; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetGridSize(uint32_t * aSize) michael@0: { michael@0: *aSize = mGridSize; michael@0: return NS_OK; michael@0: } michael@0: michael@0: // self-explanatory michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, int32_t aX, int32_t aY) michael@0: { michael@0: nsAutoEditBatch batchIt(this); michael@0: michael@0: mHTMLCSSUtils->SetCSSPropertyPixels(aElement, michael@0: nsEditProperty::cssLeft, michael@0: aX, michael@0: false); michael@0: mHTMLCSSUtils->SetCSSPropertyPixels(aElement, michael@0: nsEditProperty::cssTop, michael@0: aY, michael@0: false); michael@0: return NS_OK; michael@0: } michael@0: michael@0: // self-explanatory michael@0: NS_IMETHODIMP michael@0: nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn) michael@0: { michael@0: *aReturn = mAbsolutelyPositionedObject; michael@0: NS_IF_ADDREF(*aReturn); michael@0: return NS_OK; michael@0: } michael@0: michael@0: nsresult michael@0: nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement, michael@0: nsAString & aReturn) michael@0: { michael@0: // we are going to outline the positioned element and bring it to the michael@0: // front to overlap any other element intersecting with it. But michael@0: // first, let's see what's the background and foreground colors of the michael@0: // positioned element. michael@0: // if background-image computed value is 'none, michael@0: // If the background color is 'auto' and R G B values of the foreground are michael@0: // each above #d0, use a black background michael@0: // If the background color is 'auto' and at least one of R G B values of michael@0: // the foreground is below #d0, use a white background michael@0: // Otherwise don't change background/foreground michael@0: michael@0: aReturn.Truncate(); michael@0: michael@0: nsAutoString bgImageStr; michael@0: nsresult res = michael@0: mHTMLCSSUtils->GetComputedProperty(aElement, michael@0: nsEditProperty::cssBackgroundImage, michael@0: bgImageStr); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: if (bgImageStr.EqualsLiteral("none")) { michael@0: nsAutoString bgColorStr; michael@0: res = michael@0: mHTMLCSSUtils->GetComputedProperty(aElement, michael@0: nsEditProperty::cssBackgroundColor, michael@0: bgColorStr); michael@0: NS_ENSURE_SUCCESS(res, res); michael@0: if (bgColorStr.EqualsLiteral("transparent")) { michael@0: nsRefPtr cssDecl = michael@0: mHTMLCSSUtils->GetComputedStyle(aElement); michael@0: NS_ENSURE_STATE(cssDecl); michael@0: michael@0: // from these declarations, get the one we want and that one only michael@0: ErrorResult error; michael@0: nsRefPtr cssVal = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), error); michael@0: NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); michael@0: michael@0: nsROCSSPrimitiveValue* val = cssVal->AsPrimitiveValue(); michael@0: NS_ENSURE_TRUE(val, NS_ERROR_FAILURE); michael@0: michael@0: if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == val->PrimitiveType()) { michael@0: nsDOMCSSRGBColor* rgbVal = val->GetRGBColorValue(error); michael@0: NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); michael@0: float r = rgbVal->Red()-> michael@0: GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error); michael@0: NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); michael@0: float g = rgbVal->Green()-> michael@0: GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error); michael@0: NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); michael@0: float b = rgbVal->Blue()-> michael@0: GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error); michael@0: NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); michael@0: if (r >= BLACK_BG_RGB_TRIGGER && michael@0: g >= BLACK_BG_RGB_TRIGGER && michael@0: b >= BLACK_BG_RGB_TRIGGER) michael@0: aReturn.AssignLiteral("black"); michael@0: else michael@0: aReturn.AssignLiteral("white"); michael@0: return NS_OK; michael@0: } michael@0: } michael@0: } michael@0: michael@0: return NS_OK; michael@0: }