1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/editor/libeditor/html/nsHTMLAbsPosition.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,700 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <math.h> 1.9 + 1.10 +#include "mozilla/Preferences.h" 1.11 +#include "mozilla/dom/Selection.h" 1.12 +#include "mozilla/dom/Element.h" 1.13 +#include "mozilla/mozalloc.h" 1.14 +#include "nsAString.h" 1.15 +#include "nsAlgorithm.h" 1.16 +#include "nsAutoPtr.h" 1.17 +#include "nsCOMPtr.h" 1.18 +#include "nsComputedDOMStyle.h" 1.19 +#include "nsDebug.h" 1.20 +#include "nsEditProperty.h" 1.21 +#include "nsEditRules.h" 1.22 +#include "nsEditor.h" 1.23 +#include "nsEditorUtils.h" 1.24 +#include "nsError.h" 1.25 +#include "nsGkAtoms.h" 1.26 +#include "nsHTMLCSSUtils.h" 1.27 +#include "nsHTMLEditRules.h" 1.28 +#include "nsHTMLEditUtils.h" 1.29 +#include "nsHTMLEditor.h" 1.30 +#include "nsHTMLObjectResizer.h" 1.31 +#include "nsIContent.h" 1.32 +#include "nsROCSSPrimitiveValue.h" 1.33 +#include "nsIDOMCSSStyleDeclaration.h" 1.34 +#include "nsIDOMElement.h" 1.35 +#include "nsIDOMEventListener.h" 1.36 +#include "nsIDOMEventTarget.h" 1.37 +#include "nsIDOMNode.h" 1.38 +#include "nsDOMCSSRGBColor.h" 1.39 +#include "nsIDOMWindow.h" 1.40 +#include "nsIEditor.h" 1.41 +#include "nsIHTMLEditor.h" 1.42 +#include "nsIHTMLObjectResizer.h" 1.43 +#include "nsINode.h" 1.44 +#include "nsIPresShell.h" 1.45 +#include "nsISelection.h" 1.46 +#include "nsISupportsImpl.h" 1.47 +#include "nsISupportsUtils.h" 1.48 +#include "nsLiteralString.h" 1.49 +#include "nsReadableUtils.h" 1.50 +#include "nsString.h" 1.51 +#include "nsStringFwd.h" 1.52 +#include "nsTextEditRules.h" 1.53 +#include "nsTextEditUtils.h" 1.54 +#include "nscore.h" 1.55 +#include <algorithm> 1.56 + 1.57 +using namespace mozilla; 1.58 +using namespace mozilla::dom; 1.59 + 1.60 +#define BLACK_BG_RGB_TRIGGER 0xd0 1.61 + 1.62 +NS_IMETHODIMP 1.63 +nsHTMLEditor::AbsolutePositionSelection(bool aEnabled) 1.64 +{ 1.65 + nsAutoEditBatch beginBatching(this); 1.66 + nsAutoRules beginRulesSniffing(this, 1.67 + aEnabled ? EditAction::setAbsolutePosition : 1.68 + EditAction::removeAbsolutePosition, 1.69 + nsIEditor::eNext); 1.70 + 1.71 + // the line below does not match the code; should it be removed? 1.72 + // Find out if the selection is collapsed: 1.73 + nsRefPtr<Selection> selection = GetSelection(); 1.74 + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); 1.75 + 1.76 + nsTextRulesInfo ruleInfo(aEnabled ? EditAction::setAbsolutePosition : 1.77 + EditAction::removeAbsolutePosition); 1.78 + bool cancel, handled; 1.79 + // Protect the edit rules object from dying 1.80 + nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); 1.81 + nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); 1.82 + if (NS_FAILED(res) || cancel) 1.83 + return res; 1.84 + 1.85 + return mRules->DidDoAction(selection, &ruleInfo, res); 1.86 +} 1.87 + 1.88 +NS_IMETHODIMP 1.89 +nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval) 1.90 +{ 1.91 + nsCOMPtr<nsIDOMElement> element; 1.92 + nsresult res = GetSelectionContainer(getter_AddRefs(element)); 1.93 + NS_ENSURE_SUCCESS(res, res); 1.94 + 1.95 + nsAutoString positionStr; 1.96 + nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element); 1.97 + nsCOMPtr<nsIDOMNode> resultNode; 1.98 + 1.99 + while (!resultNode && node && !nsEditor::NodeIsType(node, nsEditProperty::html)) { 1.100 + res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition, 1.101 + positionStr); 1.102 + NS_ENSURE_SUCCESS(res, res); 1.103 + if (positionStr.EqualsLiteral("absolute")) 1.104 + resultNode = node; 1.105 + else { 1.106 + nsCOMPtr<nsIDOMNode> parentNode; 1.107 + res = node->GetParentNode(getter_AddRefs(parentNode)); 1.108 + NS_ENSURE_SUCCESS(res, res); 1.109 + node.swap(parentNode); 1.110 + } 1.111 + } 1.112 + 1.113 + element = do_QueryInterface(resultNode ); 1.114 + *_retval = element; 1.115 + NS_IF_ADDREF(*_retval); 1.116 + return NS_OK; 1.117 +} 1.118 + 1.119 +NS_IMETHODIMP 1.120 +nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(bool *aIsSelectionContainerAbsolutelyPositioned) 1.121 +{ 1.122 + *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nullptr); 1.123 + return NS_OK; 1.124 +} 1.125 + 1.126 +NS_IMETHODIMP 1.127 +nsHTMLEditor::GetAbsolutePositioningEnabled(bool * aIsEnabled) 1.128 +{ 1.129 + *aIsEnabled = mIsAbsolutelyPositioningEnabled; 1.130 + return NS_OK; 1.131 +} 1.132 + 1.133 +NS_IMETHODIMP 1.134 +nsHTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled) 1.135 +{ 1.136 + mIsAbsolutelyPositioningEnabled = aIsEnabled; 1.137 + return NS_OK; 1.138 +} 1.139 + 1.140 +NS_IMETHODIMP 1.141 +nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement, 1.142 + int32_t aChange, 1.143 + int32_t * aReturn) 1.144 +{ 1.145 + NS_ENSURE_ARG_POINTER(aElement); 1.146 + NS_ENSURE_ARG_POINTER(aReturn); 1.147 + if (!aChange) // early way out, no change 1.148 + return NS_OK; 1.149 + 1.150 + int32_t zIndex; 1.151 + nsresult res = GetElementZIndex(aElement, &zIndex); 1.152 + NS_ENSURE_SUCCESS(res, res); 1.153 + 1.154 + zIndex = std::max(zIndex + aChange, 0); 1.155 + SetElementZIndex(aElement, zIndex); 1.156 + *aReturn = zIndex; 1.157 + 1.158 + return NS_OK; 1.159 +} 1.160 + 1.161 +NS_IMETHODIMP 1.162 +nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement, 1.163 + int32_t aZindex) 1.164 +{ 1.165 + NS_ENSURE_ARG_POINTER(aElement); 1.166 + 1.167 + nsAutoString zIndexStr; 1.168 + zIndexStr.AppendInt(aZindex); 1.169 + 1.170 + mHTMLCSSUtils->SetCSSProperty(aElement, 1.171 + nsEditProperty::cssZIndex, 1.172 + zIndexStr, 1.173 + false); 1.174 + return NS_OK; 1.175 +} 1.176 + 1.177 +NS_IMETHODIMP 1.178 +nsHTMLEditor::RelativeChangeZIndex(int32_t aChange) 1.179 +{ 1.180 + nsAutoEditBatch beginBatching(this); 1.181 + nsAutoRules beginRulesSniffing(this, 1.182 + (aChange < 0) ? EditAction::decreaseZIndex : 1.183 + EditAction::increaseZIndex, 1.184 + nsIEditor::eNext); 1.185 + 1.186 + // brade: can we get rid of this comment? 1.187 + // Find out if the selection is collapsed: 1.188 + nsRefPtr<Selection> selection = GetSelection(); 1.189 + NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER); 1.190 + nsTextRulesInfo ruleInfo(aChange < 0 ? EditAction::decreaseZIndex : 1.191 + EditAction::increaseZIndex); 1.192 + bool cancel, handled; 1.193 + // Protect the edit rules object from dying 1.194 + nsCOMPtr<nsIEditRules> kungFuDeathGrip(mRules); 1.195 + nsresult res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled); 1.196 + if (cancel || NS_FAILED(res)) 1.197 + return res; 1.198 + 1.199 + return mRules->DidDoAction(selection, &ruleInfo, res); 1.200 +} 1.201 + 1.202 +NS_IMETHODIMP 1.203 +nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement, 1.204 + int32_t * aZindex) 1.205 +{ 1.206 + nsAutoString zIndexStr; 1.207 + *aZindex = 0; 1.208 + 1.209 + nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement, 1.210 + nsEditProperty::cssZIndex, 1.211 + zIndexStr); 1.212 + NS_ENSURE_SUCCESS(res, res); 1.213 + if (zIndexStr.EqualsLiteral("auto")) { 1.214 + // we have to look at the positioned ancestors 1.215 + // cf. CSS 2 spec section 9.9.1 1.216 + nsCOMPtr<nsIDOMNode> parentNode; 1.217 + res = aElement->GetParentNode(getter_AddRefs(parentNode)); 1.218 + NS_ENSURE_SUCCESS(res, res); 1.219 + nsCOMPtr<nsIDOMNode> node = parentNode; 1.220 + nsAutoString positionStr; 1.221 + while (node && 1.222 + zIndexStr.EqualsLiteral("auto") && 1.223 + !nsTextEditUtils::IsBody(node)) { 1.224 + res = mHTMLCSSUtils->GetComputedProperty(node, 1.225 + nsEditProperty::cssPosition, 1.226 + positionStr); 1.227 + NS_ENSURE_SUCCESS(res, res); 1.228 + if (positionStr.EqualsLiteral("absolute")) { 1.229 + // ah, we found one, what's its z-index ? If its z-index is auto, 1.230 + // we have to continue climbing the document's tree 1.231 + res = mHTMLCSSUtils->GetComputedProperty(node, 1.232 + nsEditProperty::cssZIndex, 1.233 + zIndexStr); 1.234 + NS_ENSURE_SUCCESS(res, res); 1.235 + } 1.236 + res = node->GetParentNode(getter_AddRefs(parentNode)); 1.237 + NS_ENSURE_SUCCESS(res, res); 1.238 + node = parentNode; 1.239 + } 1.240 + } 1.241 + 1.242 + if (!zIndexStr.EqualsLiteral("auto")) { 1.243 + nsresult errorCode; 1.244 + *aZindex = zIndexStr.ToInteger(&errorCode); 1.245 + } 1.246 + 1.247 + return NS_OK; 1.248 +} 1.249 + 1.250 +nsresult 1.251 +nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn) 1.252 +{ 1.253 + // let's create a grabber through the element factory 1.254 + nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"), 1.255 + aParentNode, 1.256 + NS_LITERAL_STRING("mozGrabber"), 1.257 + false, 1.258 + aReturn); 1.259 + 1.260 + NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE); 1.261 + 1.262 + // add the mouse listener so we can detect a click on a resizer 1.263 + nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn)); 1.264 + evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), 1.265 + mEventListener, false); 1.266 + 1.267 + return res; 1.268 +} 1.269 + 1.270 +NS_IMETHODIMP 1.271 +nsHTMLEditor::RefreshGrabber() 1.272 +{ 1.273 + NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER); 1.274 + 1.275 + nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject, 1.276 + mPositionedObjectX, 1.277 + mPositionedObjectY, 1.278 + mPositionedObjectWidth, 1.279 + mPositionedObjectHeight, 1.280 + mPositionedObjectBorderLeft, 1.281 + mPositionedObjectBorderTop, 1.282 + mPositionedObjectMarginLeft, 1.283 + mPositionedObjectMarginTop); 1.284 + 1.285 + NS_ENSURE_SUCCESS(res, res); 1.286 + 1.287 + SetAnonymousElementPosition(mPositionedObjectX+12, 1.288 + mPositionedObjectY-14, 1.289 + mGrabber); 1.290 + return NS_OK; 1.291 +} 1.292 + 1.293 +NS_IMETHODIMP 1.294 +nsHTMLEditor::HideGrabber() 1.295 +{ 1.296 + nsresult res = 1.297 + mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos")); 1.298 + NS_ENSURE_SUCCESS(res, res); 1.299 + 1.300 + mAbsolutelyPositionedObject = nullptr; 1.301 + NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER); 1.302 + 1.303 + // get the presshell's document observer interface. 1.304 + nsCOMPtr<nsIPresShell> ps = GetPresShell(); 1.305 + // We allow the pres shell to be null; when it is, we presume there 1.306 + // are no document observers to notify, but we still want to 1.307 + // UnbindFromTree. 1.308 + 1.309 + nsCOMPtr<nsIDOMNode> parentNode; 1.310 + res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); 1.311 + NS_ENSURE_SUCCESS(res, res); 1.312 + 1.313 + nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode); 1.314 + NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER); 1.315 + 1.316 + DeleteRefToAnonymousNode(mGrabber, parentContent, ps); 1.317 + mGrabber = nullptr; 1.318 + DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); 1.319 + mPositioningShadow = nullptr; 1.320 + 1.321 + return NS_OK; 1.322 +} 1.323 + 1.324 +NS_IMETHODIMP 1.325 +nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement) 1.326 +{ 1.327 + NS_ENSURE_ARG_POINTER(aElement); 1.328 + 1.329 + if (mGrabber) { 1.330 + NS_ERROR("call HideGrabber first"); 1.331 + return NS_ERROR_UNEXPECTED; 1.332 + } 1.333 + 1.334 + nsAutoString classValue; 1.335 + nsresult res = CheckPositionedElementBGandFG(aElement, classValue); 1.336 + NS_ENSURE_SUCCESS(res, res); 1.337 + 1.338 + res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"), 1.339 + classValue); 1.340 + NS_ENSURE_SUCCESS(res, res); 1.341 + 1.342 + // first, let's keep track of that element... 1.343 + mAbsolutelyPositionedObject = aElement; 1.344 + 1.345 + nsCOMPtr<nsIDOMNode> parentNode; 1.346 + res = aElement->GetParentNode(getter_AddRefs(parentNode)); 1.347 + NS_ENSURE_SUCCESS(res, res); 1.348 + 1.349 + res = CreateGrabber(parentNode, getter_AddRefs(mGrabber)); 1.350 + NS_ENSURE_SUCCESS(res, res); 1.351 + 1.352 + // and set its position 1.353 + return RefreshGrabber(); 1.354 +} 1.355 + 1.356 +nsresult 1.357 +nsHTMLEditor::StartMoving(nsIDOMElement *aHandle) 1.358 +{ 1.359 + nsCOMPtr<nsIDOMNode> parentNode; 1.360 + nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); 1.361 + NS_ENSURE_SUCCESS(res, res); 1.362 + 1.363 + // now, let's create the resizing shadow 1.364 + res = CreateShadow(getter_AddRefs(mPositioningShadow), 1.365 + parentNode, mAbsolutelyPositionedObject); 1.366 + NS_ENSURE_SUCCESS(res,res); 1.367 + res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject, 1.368 + mPositionedObjectX, mPositionedObjectY); 1.369 + NS_ENSURE_SUCCESS(res,res); 1.370 + 1.371 + // make the shadow appear 1.372 + mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class")); 1.373 + 1.374 + // position it 1.375 + mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, 1.376 + NS_LITERAL_STRING("width"), 1.377 + mPositionedObjectWidth); 1.378 + mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow, 1.379 + NS_LITERAL_STRING("height"), 1.380 + mPositionedObjectHeight); 1.381 + 1.382 + mIsMoving = true; 1.383 + return res; 1.384 +} 1.385 + 1.386 +void 1.387 +nsHTMLEditor::SnapToGrid(int32_t & newX, int32_t & newY) 1.388 +{ 1.389 + if (mSnapToGridEnabled && mGridSize) { 1.390 + newX = (int32_t) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize; 1.391 + newY = (int32_t) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize; 1.392 + } 1.393 +} 1.394 + 1.395 +nsresult 1.396 +nsHTMLEditor::GrabberClicked() 1.397 +{ 1.398 + // add a mouse move listener to the editor 1.399 + nsresult res = NS_OK; 1.400 + if (!mMouseMotionListenerP) { 1.401 + mMouseMotionListenerP = new ResizerMouseMotionListener(this); 1.402 + if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;} 1.403 + 1.404 + nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget(); 1.405 + NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE); 1.406 + 1.407 + res = piTarget->AddEventListener(NS_LITERAL_STRING("mousemove"), 1.408 + mMouseMotionListenerP, 1.409 + false, false); 1.410 + NS_ASSERTION(NS_SUCCEEDED(res), 1.411 + "failed to register mouse motion listener"); 1.412 + } 1.413 + mGrabberClicked = true; 1.414 + return res; 1.415 +} 1.416 + 1.417 +nsresult 1.418 +nsHTMLEditor::EndMoving() 1.419 +{ 1.420 + if (mPositioningShadow) { 1.421 + nsCOMPtr<nsIPresShell> ps = GetPresShell(); 1.422 + NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED); 1.423 + 1.424 + nsCOMPtr<nsIDOMNode> parentNode; 1.425 + nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode)); 1.426 + NS_ENSURE_SUCCESS(res, res); 1.427 + 1.428 + nsCOMPtr<nsIContent> parentContent( do_QueryInterface(parentNode) ); 1.429 + NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE); 1.430 + 1.431 + DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps); 1.432 + 1.433 + mPositioningShadow = nullptr; 1.434 + } 1.435 + nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget(); 1.436 + 1.437 + if (piTarget && mMouseMotionListenerP) { 1.438 +#ifdef DEBUG 1.439 + nsresult res = 1.440 +#endif 1.441 + piTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"), 1.442 + mMouseMotionListenerP, 1.443 + false); 1.444 + NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener"); 1.445 + } 1.446 + mMouseMotionListenerP = nullptr; 1.447 + 1.448 + mGrabberClicked = false; 1.449 + mIsMoving = false; 1.450 + nsCOMPtr<nsISelection> selection; 1.451 + GetSelection(getter_AddRefs(selection)); 1.452 + if (!selection) { 1.453 + return NS_ERROR_NOT_INITIALIZED; 1.454 + } 1.455 + return CheckSelectionStateForAnonymousButtons(selection); 1.456 +} 1.457 +nsresult 1.458 +nsHTMLEditor::SetFinalPosition(int32_t aX, int32_t aY) 1.459 +{ 1.460 + nsresult res = EndMoving(); 1.461 + NS_ENSURE_SUCCESS(res, res); 1.462 + 1.463 + // we have now to set the new width and height of the resized object 1.464 + // we don't set the x and y position because we don't control that in 1.465 + // a normal HTML layout 1.466 + int32_t newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft); 1.467 + int32_t newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop); 1.468 + 1.469 + SnapToGrid(newX, newY); 1.470 + 1.471 + nsAutoString x, y; 1.472 + x.AppendInt(newX); 1.473 + y.AppendInt(newY); 1.474 + 1.475 + // we want one transaction only from a user's point of view 1.476 + nsAutoEditBatch batchIt(this); 1.477 + 1.478 + mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject, 1.479 + nsEditProperty::cssTop, 1.480 + newY, 1.481 + false); 1.482 + mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject, 1.483 + nsEditProperty::cssLeft, 1.484 + newX, 1.485 + false); 1.486 + // keep track of that size 1.487 + mPositionedObjectX = newX; 1.488 + mPositionedObjectY = newY; 1.489 + 1.490 + return RefreshResizers(); 1.491 +} 1.492 + 1.493 +void 1.494 +nsHTMLEditor::AddPositioningOffset(int32_t & aX, int32_t & aY) 1.495 +{ 1.496 + // Get the positioning offset 1.497 + int32_t positioningOffset = 1.498 + Preferences::GetInt("editor.positioning.offset", 0); 1.499 + 1.500 + aX += positioningOffset; 1.501 + aY += positioningOffset; 1.502 +} 1.503 + 1.504 +NS_IMETHODIMP 1.505 +nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement, 1.506 + bool aEnabled) 1.507 +{ 1.508 + NS_ENSURE_ARG_POINTER(aElement); 1.509 + 1.510 + nsAutoString positionStr; 1.511 + mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition, 1.512 + positionStr); 1.513 + bool isPositioned = (positionStr.EqualsLiteral("absolute")); 1.514 + 1.515 + // nothing to do if the element is already in the state we want 1.516 + if (isPositioned == aEnabled) 1.517 + return NS_OK; 1.518 + 1.519 + nsAutoEditBatch batchIt(this); 1.520 + 1.521 + if (aEnabled) { 1.522 + int32_t x, y; 1.523 + GetElementOrigin(aElement, x, y); 1.524 + 1.525 + mHTMLCSSUtils->SetCSSProperty(aElement, 1.526 + nsEditProperty::cssPosition, 1.527 + NS_LITERAL_STRING("absolute"), 1.528 + false); 1.529 + 1.530 + AddPositioningOffset(x, y); 1.531 + SnapToGrid(x, y); 1.532 + SetElementPosition(aElement, x, y); 1.533 + 1.534 + // we may need to create a br if the positioned element is alone in its 1.535 + // container 1.536 + nsCOMPtr<nsINode> element = do_QueryInterface(aElement); 1.537 + NS_ENSURE_STATE(element); 1.538 + 1.539 + nsINode* parentNode = element->GetParentNode(); 1.540 + if (parentNode->GetChildCount() == 1) { 1.541 + nsCOMPtr<nsIDOMNode> brNode; 1.542 + nsresult res = CreateBR(parentNode->AsDOMNode(), 0, address_of(brNode)); 1.543 + NS_ENSURE_SUCCESS(res, res); 1.544 + } 1.545 + } 1.546 + else { 1.547 + mHTMLCSSUtils->RemoveCSSProperty(aElement, 1.548 + nsEditProperty::cssPosition, 1.549 + EmptyString(), false); 1.550 + mHTMLCSSUtils->RemoveCSSProperty(aElement, 1.551 + nsEditProperty::cssTop, 1.552 + EmptyString(), false); 1.553 + mHTMLCSSUtils->RemoveCSSProperty(aElement, 1.554 + nsEditProperty::cssLeft, 1.555 + EmptyString(), false); 1.556 + mHTMLCSSUtils->RemoveCSSProperty(aElement, 1.557 + nsEditProperty::cssZIndex, 1.558 + EmptyString(), false); 1.559 + 1.560 + if (!nsHTMLEditUtils::IsImage(aElement)) { 1.561 + mHTMLCSSUtils->RemoveCSSProperty(aElement, 1.562 + nsEditProperty::cssWidth, 1.563 + EmptyString(), false); 1.564 + mHTMLCSSUtils->RemoveCSSProperty(aElement, 1.565 + nsEditProperty::cssHeight, 1.566 + EmptyString(), false); 1.567 + } 1.568 + 1.569 + nsCOMPtr<dom::Element> element = do_QueryInterface(aElement); 1.570 + if (element && element->IsHTML(nsGkAtoms::div) && !HasStyleOrIdOrClass(element)) { 1.571 + nsRefPtr<nsHTMLEditRules> htmlRules = static_cast<nsHTMLEditRules*>(mRules.get()); 1.572 + NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE); 1.573 + nsresult res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement); 1.574 + NS_ENSURE_SUCCESS(res, res); 1.575 + res = RemoveContainer(aElement); 1.576 + NS_ENSURE_SUCCESS(res, res); 1.577 + } 1.578 + } 1.579 + return NS_OK; 1.580 +} 1.581 + 1.582 +NS_IMETHODIMP 1.583 +nsHTMLEditor::SetSnapToGridEnabled(bool aEnabled) 1.584 +{ 1.585 + mSnapToGridEnabled = aEnabled; 1.586 + return NS_OK; 1.587 +} 1.588 + 1.589 +NS_IMETHODIMP 1.590 +nsHTMLEditor::GetSnapToGridEnabled(bool * aIsEnabled) 1.591 +{ 1.592 + *aIsEnabled = mSnapToGridEnabled; 1.593 + return NS_OK; 1.594 +} 1.595 + 1.596 +NS_IMETHODIMP 1.597 +nsHTMLEditor::SetGridSize(uint32_t aSize) 1.598 +{ 1.599 + mGridSize = aSize; 1.600 + return NS_OK; 1.601 +} 1.602 + 1.603 +NS_IMETHODIMP 1.604 +nsHTMLEditor::GetGridSize(uint32_t * aSize) 1.605 +{ 1.606 + *aSize = mGridSize; 1.607 + return NS_OK; 1.608 +} 1.609 + 1.610 +// self-explanatory 1.611 +NS_IMETHODIMP 1.612 +nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, int32_t aX, int32_t aY) 1.613 +{ 1.614 + nsAutoEditBatch batchIt(this); 1.615 + 1.616 + mHTMLCSSUtils->SetCSSPropertyPixels(aElement, 1.617 + nsEditProperty::cssLeft, 1.618 + aX, 1.619 + false); 1.620 + mHTMLCSSUtils->SetCSSPropertyPixels(aElement, 1.621 + nsEditProperty::cssTop, 1.622 + aY, 1.623 + false); 1.624 + return NS_OK; 1.625 +} 1.626 + 1.627 +// self-explanatory 1.628 +NS_IMETHODIMP 1.629 +nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn) 1.630 +{ 1.631 + *aReturn = mAbsolutelyPositionedObject; 1.632 + NS_IF_ADDREF(*aReturn); 1.633 + return NS_OK; 1.634 +} 1.635 + 1.636 +nsresult 1.637 +nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement, 1.638 + nsAString & aReturn) 1.639 +{ 1.640 + // we are going to outline the positioned element and bring it to the 1.641 + // front to overlap any other element intersecting with it. But 1.642 + // first, let's see what's the background and foreground colors of the 1.643 + // positioned element. 1.644 + // if background-image computed value is 'none, 1.645 + // If the background color is 'auto' and R G B values of the foreground are 1.646 + // each above #d0, use a black background 1.647 + // If the background color is 'auto' and at least one of R G B values of 1.648 + // the foreground is below #d0, use a white background 1.649 + // Otherwise don't change background/foreground 1.650 + 1.651 + aReturn.Truncate(); 1.652 + 1.653 + nsAutoString bgImageStr; 1.654 + nsresult res = 1.655 + mHTMLCSSUtils->GetComputedProperty(aElement, 1.656 + nsEditProperty::cssBackgroundImage, 1.657 + bgImageStr); 1.658 + NS_ENSURE_SUCCESS(res, res); 1.659 + if (bgImageStr.EqualsLiteral("none")) { 1.660 + nsAutoString bgColorStr; 1.661 + res = 1.662 + mHTMLCSSUtils->GetComputedProperty(aElement, 1.663 + nsEditProperty::cssBackgroundColor, 1.664 + bgColorStr); 1.665 + NS_ENSURE_SUCCESS(res, res); 1.666 + if (bgColorStr.EqualsLiteral("transparent")) { 1.667 + nsRefPtr<nsComputedDOMStyle> cssDecl = 1.668 + mHTMLCSSUtils->GetComputedStyle(aElement); 1.669 + NS_ENSURE_STATE(cssDecl); 1.670 + 1.671 + // from these declarations, get the one we want and that one only 1.672 + ErrorResult error; 1.673 + nsRefPtr<dom::CSSValue> cssVal = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), error); 1.674 + NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); 1.675 + 1.676 + nsROCSSPrimitiveValue* val = cssVal->AsPrimitiveValue(); 1.677 + NS_ENSURE_TRUE(val, NS_ERROR_FAILURE); 1.678 + 1.679 + if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == val->PrimitiveType()) { 1.680 + nsDOMCSSRGBColor* rgbVal = val->GetRGBColorValue(error); 1.681 + NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); 1.682 + float r = rgbVal->Red()-> 1.683 + GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error); 1.684 + NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); 1.685 + float g = rgbVal->Green()-> 1.686 + GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error); 1.687 + NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); 1.688 + float b = rgbVal->Blue()-> 1.689 + GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, error); 1.690 + NS_ENSURE_SUCCESS(error.ErrorCode(), error.ErrorCode()); 1.691 + if (r >= BLACK_BG_RGB_TRIGGER && 1.692 + g >= BLACK_BG_RGB_TRIGGER && 1.693 + b >= BLACK_BG_RGB_TRIGGER) 1.694 + aReturn.AssignLiteral("black"); 1.695 + else 1.696 + aReturn.AssignLiteral("white"); 1.697 + return NS_OK; 1.698 + } 1.699 + } 1.700 + } 1.701 + 1.702 + return NS_OK; 1.703 +}