Back to index

lightning-sunbird  0.9+nobinonly
nsHTMLAbsPosition.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is Mozilla.org.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corp.
00018  * Portions created by the Initial Developer are Copyright (C) 2003
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   Daniel Glazman (glazman@netscape.com) (Original author)
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include <math.h>
00039 
00040 #include "nsHTMLEditor.h"
00041 
00042 #include "nsIContent.h"
00043 #include "nsIDocument.h"
00044 #include "nsIEditor.h"
00045 #include "nsIPresShell.h"
00046 
00047 #include "nsISelection.h"
00048 
00049 #include "nsTextEditUtils.h"
00050 #include "nsEditorUtils.h"
00051 #include "nsHTMLEditUtils.h"
00052 #include "nsTextEditRules.h"
00053 #include "nsIHTMLEditRules.h"
00054 
00055 #include "nsIDOMHTMLElement.h"
00056 #include "nsIDOMNSHTMLElement.h"
00057 #include "nsIDOMNodeList.h"
00058 
00059 #include "nsIDOMEventTarget.h"
00060 #include "nsIDOMEventReceiver.h"
00061 
00062 #include "nsIPrefBranch.h"
00063 #include "nsIPrefService.h"
00064 #include "nsIServiceManager.h"
00065 
00066 #include "nsIDOMCSSValue.h"
00067 #include "nsIDOMCSSPrimitiveValue.h"
00068 #include "nsIDOMRGBColor.h"
00069 
00070 #define  BLACK_BG_RGB_TRIGGER 0xd0
00071 
00072 NS_IMETHODIMP
00073 nsHTMLEditor::AbsolutePositionSelection(PRBool aEnabled)
00074 {
00075   nsAutoEditBatch beginBatching(this);
00076   nsAutoRules beginRulesSniffing(this,
00077                                  aEnabled ? kOpSetAbsolutePosition :
00078                                             kOpRemoveAbsolutePosition,
00079                                  nsIEditor::eNext);
00080   
00081   // the line below does not match the code; should it be removed?
00082   // Find out if the selection is collapsed:
00083   nsCOMPtr<nsISelection> selection;
00084   nsresult res = GetSelection(getter_AddRefs(selection));
00085   if (NS_FAILED(res)) return res;
00086   if (!selection) return NS_ERROR_NULL_POINTER;
00087 
00088   nsTextRulesInfo ruleInfo(aEnabled ?
00089                            nsTextEditRules::kSetAbsolutePosition :
00090                            nsTextEditRules::kRemoveAbsolutePosition);
00091   PRBool cancel, handled;
00092   res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
00093   if (NS_FAILED(res) || cancel)
00094     return res;
00095   
00096   return mRules->DidDoAction(selection, &ruleInfo, res);
00097 }
00098 
00099 NS_IMETHODIMP
00100 nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
00101 {
00102   nsCOMPtr<nsIDOMElement> element;
00103   nsresult res = GetSelectionContainer(getter_AddRefs(element));
00104   if (NS_FAILED(res)) return res;
00105 
00106   nsAutoString positionStr;
00107   nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
00108   nsCOMPtr<nsIDOMNode> resultNode;
00109 
00110   do {
00111     res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
00112                                              positionStr);
00113     if (NS_FAILED(res)) return res;
00114     if (positionStr.EqualsLiteral("absolute"))
00115       resultNode = node;
00116     else {
00117       nsCOMPtr<nsIDOMNode> parentNode;
00118       res = node->GetParentNode(getter_AddRefs(parentNode));
00119       if (NS_FAILED(res)) return res;
00120       node.swap(parentNode);
00121     }
00122   } while (!resultNode &&
00123            !nsEditor::NodeIsType(node, nsEditProperty::html));
00124 
00125   element = do_QueryInterface(resultNode ); 
00126   *_retval = element;
00127   NS_IF_ADDREF(*_retval);
00128   return NS_OK;
00129 }
00130 
00131 NS_IMETHODIMP
00132 nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(PRBool *aIsSelectionContainerAbsolutelyPositioned)
00133 {
00134   *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nsnull);
00135   return NS_OK;
00136 }
00137 
00138 NS_IMETHODIMP
00139 nsHTMLEditor::GetAbsolutePositioningEnabled(PRBool * aIsEnabled)
00140 {
00141   *aIsEnabled = mIsAbsolutelyPositioningEnabled;
00142   return NS_OK;
00143 }
00144 
00145 NS_IMETHODIMP
00146 nsHTMLEditor::SetAbsolutePositioningEnabled(PRBool aIsEnabled)
00147 {
00148   mIsAbsolutelyPositioningEnabled = aIsEnabled;
00149   return NS_OK;
00150 }
00151 
00152 NS_IMETHODIMP
00153 nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement,
00154                                           PRInt32 aChange,
00155                                           PRInt32 * aReturn)
00156 {
00157   NS_ENSURE_ARG_POINTER(aElement);
00158   NS_ENSURE_ARG_POINTER(aReturn);
00159   if (!aChange) // early way out, no change
00160     return NS_OK;
00161 
00162   PRInt32 zIndex;
00163   nsresult res = GetElementZIndex(aElement, &zIndex);
00164   if (NS_FAILED(res)) return res;
00165 
00166   zIndex = PR_MAX(zIndex + aChange, 0);
00167   SetElementZIndex(aElement, zIndex);
00168   *aReturn = zIndex;
00169 
00170   return NS_OK;
00171 }
00172 
00173 NS_IMETHODIMP
00174 nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement,
00175                                PRInt32 aZindex)
00176 {
00177   NS_ENSURE_ARG_POINTER(aElement);
00178   
00179   nsAutoString zIndexStr;
00180   zIndexStr.AppendInt(aZindex);
00181 
00182   mHTMLCSSUtils->SetCSSProperty(aElement,
00183                                 nsEditProperty::cssZIndex,
00184                                 zIndexStr,
00185                                 PR_FALSE);
00186   return NS_OK;
00187 }
00188 
00189 NS_IMETHODIMP
00190 nsHTMLEditor::RelativeChangeZIndex(PRInt32 aChange)
00191 {
00192   nsAutoEditBatch beginBatching(this);
00193   nsAutoRules beginRulesSniffing(this,
00194                                  (aChange < 0) ? kOpDecreaseZIndex :
00195                                                  kOpIncreaseZIndex,
00196                                  nsIEditor::eNext);
00197   
00198   // brade: can we get rid of this comment?
00199   // Find out if the selection is collapsed:
00200   nsCOMPtr<nsISelection> selection;
00201   nsresult res = GetSelection(getter_AddRefs(selection));
00202   if (NS_FAILED(res)) return res;
00203   if (!selection) return NS_ERROR_NULL_POINTER;
00204   nsTextRulesInfo ruleInfo((aChange < 0) ? nsTextEditRules::kDecreaseZIndex:
00205                                            nsTextEditRules::kIncreaseZIndex);
00206   PRBool cancel, handled;
00207   res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
00208   if (cancel || NS_FAILED(res))
00209     return res;
00210   
00211   return mRules->DidDoAction(selection, &ruleInfo, res);
00212 }
00213 
00214 NS_IMETHODIMP
00215 nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
00216                                PRInt32 * aZindex)
00217 {
00218   nsAutoString zIndexStr;
00219   *aZindex = 0;
00220 
00221   nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement,
00222                                                      nsEditProperty::cssZIndex,
00223                                                      zIndexStr);
00224   if (NS_FAILED(res)) return res;
00225   if (zIndexStr.EqualsLiteral("auto")) {
00226     // we have to look at the positioned ancestors
00227     // cf. CSS 2 spec section 9.9.1
00228     nsCOMPtr<nsIDOMNode> parentNode;
00229     res = aElement->GetParentNode(getter_AddRefs(parentNode));
00230     if (NS_FAILED(res)) return res;
00231     nsCOMPtr<nsIDOMNode> node = parentNode;
00232     nsAutoString positionStr;
00233     while (node && 
00234            zIndexStr.EqualsLiteral("auto") &&
00235            !nsTextEditUtils::IsBody(node)) {
00236       res = mHTMLCSSUtils->GetComputedProperty(node,
00237                                                nsEditProperty::cssPosition,
00238                                                positionStr);
00239       if (NS_FAILED(res)) return res;
00240       if (positionStr.EqualsLiteral("absolute")) {
00241         // ah, we found one, what's its z-index ? If its z-index is auto,
00242         // we have to continue climbing the document's tree
00243         res = mHTMLCSSUtils->GetComputedProperty(node,
00244                                                  nsEditProperty::cssZIndex,
00245                                                  zIndexStr);
00246         if (NS_FAILED(res)) return res;
00247       }
00248       res = node->GetParentNode(getter_AddRefs(parentNode));
00249       if (NS_FAILED(res)) return res;
00250       node = parentNode;
00251     }
00252   }
00253 
00254   if (!zIndexStr.EqualsLiteral("auto")) {
00255     PRInt32 errorCode;
00256     *aZindex = zIndexStr.ToInteger(&errorCode);
00257   }
00258 
00259   return NS_OK;
00260 }
00261 
00262 nsresult
00263 nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn)
00264 {
00265   // let's create a grabber through the element factory
00266   nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
00267                                         aParentNode,
00268                                         NS_LITERAL_STRING("mozGrabber"),
00269                                         PR_FALSE,
00270                                         aReturn);
00271 
00272   if (!*aReturn)
00273     return NS_ERROR_FAILURE;
00274 
00275   // add the mouse listener so we can detect a click on a resizer
00276   nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
00277   evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"), mMouseListenerP, PR_FALSE);
00278 
00279   return res;
00280 }
00281 
00282 NS_IMETHODIMP
00283 nsHTMLEditor::RefreshGrabber()
00284 {
00285   NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER);
00286 
00287   nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject,
00288                                          mPositionedObjectX,
00289                                          mPositionedObjectY,
00290                                          mPositionedObjectWidth,
00291                                          mPositionedObjectHeight,
00292                                          mPositionedObjectBorderLeft,
00293                                          mPositionedObjectBorderTop,
00294                                          mPositionedObjectMarginLeft,
00295                                          mPositionedObjectMarginTop);
00296 
00297   if (NS_FAILED(res)) return res;
00298 
00299   SetAnonymousElementPosition(mPositionedObjectX+12,
00300                               mPositionedObjectY-14,
00301                               mGrabber);
00302   return NS_OK;
00303 }
00304 
00305 NS_IMETHODIMP
00306 nsHTMLEditor::HideGrabber()
00307 {
00308   nsresult res =
00309     mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos"));
00310   if (NS_FAILED(res)) return res;
00311 
00312   mAbsolutelyPositionedObject = nsnull;
00313   NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER);
00314 
00315   // get the presshell's document observer interface.
00316   nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
00317   if (!ps) return NS_ERROR_NOT_INITIALIZED;
00318 
00319   // get the root content node.
00320 
00321   nsIDOMElement *rootElement = GetRoot();
00322 
00323   nsCOMPtr<nsIContent> rootContent = do_QueryInterface(rootElement);
00324   if (!rootContent) return NS_ERROR_NULL_POINTER;
00325 
00326   DeleteRefToAnonymousNode(mGrabber, rootContent, ps);
00327   mGrabber = nsnull;
00328   DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps);
00329   mPositioningShadow = nsnull;
00330 
00331   return NS_OK;
00332 }
00333 
00334 NS_IMETHODIMP
00335 nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
00336 {
00337   NS_ENSURE_ARG_POINTER(aElement);
00338 
00339   nsAutoString classValue;
00340   nsresult res = CheckPositionedElementBGandFG(aElement, classValue);
00341   if (NS_FAILED(res)) return res;
00342 
00343   res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"),
00344                                classValue);
00345   if (NS_FAILED(res)) return res;
00346 
00347   // first, let's keep track of that element...
00348   mAbsolutelyPositionedObject = aElement;
00349 
00350   nsIDOMElement *rootElement = GetRoot();
00351   if (!rootElement)   return NS_ERROR_NULL_POINTER;
00352 
00353   res = CreateGrabber(rootElement, getter_AddRefs(mGrabber));
00354   if (NS_FAILED(res)) return res;
00355   // and set its position
00356   return RefreshGrabber();
00357 }
00358 
00359 nsresult
00360 nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
00361 {
00362   nsIDOMElement *rootElement = GetRoot();
00363   if (!rootElement)   return NS_ERROR_NULL_POINTER;
00364 
00365   // now, let's create the resizing shadow
00366   nsresult result = CreateShadow(getter_AddRefs(mPositioningShadow),
00367                                  rootElement, mAbsolutelyPositionedObject);
00368   if (NS_FAILED(result)) return result;
00369   result = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
00370                              mPositionedObjectX, mPositionedObjectY);
00371   if (NS_FAILED(result)) return result;
00372 
00373   // make the shadow appear
00374   mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
00375 
00376   // position it
00377   mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
00378                                       NS_LITERAL_STRING("width"),
00379                                       mPositionedObjectWidth);
00380   mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
00381                                       NS_LITERAL_STRING("height"),
00382                                       mPositionedObjectHeight);
00383 
00384   mIsMoving = PR_TRUE;
00385   return result;
00386 }
00387 
00388 void
00389 nsHTMLEditor::SnapToGrid(PRInt32 & newX, PRInt32 & newY)
00390 {
00391   if (mSnapToGridEnabled && mGridSize) {
00392     newX = (PRInt32) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize;
00393     newY = (PRInt32) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize;
00394   }
00395 }
00396 
00397 nsresult
00398 nsHTMLEditor::GrabberClicked()
00399 {
00400   // add a mouse move listener to the editor
00401   nsresult res = NS_OK;
00402   if (!mMouseMotionListenerP) {
00403     mMouseMotionListenerP = new ResizerMouseMotionListener(this);
00404     if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;}
00405 
00406     nsCOMPtr<nsIDOMEventReceiver> erP = GetDOMEventReceiver();
00407     NS_ENSURE_TRUE(erP, NS_ERROR_FAILURE);
00408 
00409     res = erP->AddEventListenerByIID(mMouseMotionListenerP,
00410                                      NS_GET_IID(nsIDOMMouseMotionListener));
00411     NS_ASSERTION(NS_SUCCEEDED(res),
00412                  "failed to register mouse motion listener");
00413   }
00414   mGrabberClicked = PR_TRUE;
00415   return res;
00416 }
00417 
00418 nsresult
00419 nsHTMLEditor::EndMoving()
00420 {
00421   if (mPositioningShadow) {
00422     nsCOMPtr<nsIPresShell> ps = do_QueryReferent(mPresShellWeak);
00423     if (!ps) return NS_ERROR_NOT_INITIALIZED;
00424 
00425     // get the root content node.
00426 
00427     nsIDOMElement *rootElement = GetRoot();
00428 
00429     nsCOMPtr<nsIContent> rootContent( do_QueryInterface(rootElement) );
00430     if (!rootContent) return NS_ERROR_FAILURE;
00431 
00432     DeleteRefToAnonymousNode(mPositioningShadow, rootContent, ps);
00433     mPositioningShadow = nsnull;
00434   }
00435   nsCOMPtr<nsIDOMEventReceiver> erP = GetDOMEventReceiver();
00436 
00437   if (erP && mMouseMotionListenerP) {
00438 #ifdef DEBUG
00439     nsresult res =
00440 #endif
00441     erP->RemoveEventListenerByIID(mMouseMotionListenerP, NS_GET_IID(nsIDOMMouseMotionListener));
00442     NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
00443   }
00444   mMouseMotionListenerP = nsnull;
00445 
00446   return NS_OK;
00447 }
00448 nsresult
00449 nsHTMLEditor::SetFinalPosition(PRInt32 aX, PRInt32 aY)
00450 {
00451   nsresult res = EndMoving();
00452   mGrabberClicked = PR_FALSE;
00453   mIsMoving = PR_FALSE;
00454   if (NS_FAILED(res)) return res;
00455 
00456   // we have now to set the new width and height of the resized object
00457   // we don't set the x and y position because we don't control that in
00458   // a normal HTML layout
00459   PRInt32 newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft);
00460   PRInt32 newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop);
00461 
00462   SnapToGrid(newX, newY);
00463 
00464   nsAutoString x, y;
00465   x.AppendInt(newX);
00466   y.AppendInt(newY);
00467 
00468   // we want one transaction only from a user's point of view
00469   nsAutoEditBatch batchIt(this);
00470 
00471   mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
00472                                       nsEditProperty::cssTop,
00473                                       newY,
00474                                       PR_FALSE);
00475   mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
00476                                       nsEditProperty::cssLeft,
00477                                       newX,
00478                                       PR_FALSE);
00479   // keep track of that size
00480   mPositionedObjectX  = newX;
00481   mPositionedObjectY  = newY;
00482 
00483   return RefreshResizers();
00484 }
00485 
00486 void
00487 nsHTMLEditor::AddPositioningOffet(PRInt32 & aX, PRInt32 & aY)
00488 {
00489   // Get the positioning offset
00490   nsresult res;
00491   nsCOMPtr<nsIPrefBranch> prefBranch =
00492     do_GetService(NS_PREFSERVICE_CONTRACTID, &res);
00493   PRInt32 positioningOffset = 0;
00494   if (NS_SUCCEEDED(res) && prefBranch) {
00495     res = prefBranch->GetIntPref("editor.positioning.offset", &positioningOffset);
00496     if (NS_FAILED(res)) // paranoia
00497       positioningOffset = 0;
00498   }
00499 
00500   aX += positioningOffset;
00501   aY += positioningOffset;
00502 }
00503 
00504 NS_IMETHODIMP
00505 nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
00506                                         PRBool aEnabled)
00507 {
00508   NS_ENSURE_ARG_POINTER(aElement);
00509 
00510   nsAutoString positionStr;
00511   mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition,
00512                                      positionStr);
00513   PRBool isPositioned = (positionStr.EqualsLiteral("absolute"));
00514 
00515   // nothing to do if the element is already in the state we want
00516   if (isPositioned == aEnabled)
00517     return NS_OK;
00518 
00519   nsAutoEditBatch batchIt(this);
00520   nsresult res;
00521 
00522   if (aEnabled) {
00523     PRInt32 x, y;
00524     GetElementOrigin(aElement, x, y);
00525 
00526     mHTMLCSSUtils->SetCSSProperty(aElement,
00527                                   nsEditProperty::cssPosition,
00528                                   NS_LITERAL_STRING("absolute"),
00529                                   PR_FALSE);
00530 
00531     AddPositioningOffet(x, y);
00532     SnapToGrid(x, y);
00533     SetElementPosition(aElement, x, y);
00534 
00535     // we may need to create a br if the positioned element is alone in its
00536     // container
00537     nsCOMPtr<nsIDOMNode> parentNode;
00538     res = aElement->GetParentNode(getter_AddRefs(parentNode));
00539     if (NS_FAILED(res)) return res;
00540 
00541     nsCOMPtr<nsIDOMNodeList> childNodes;
00542     res = parentNode->GetChildNodes(getter_AddRefs(childNodes));
00543     if (NS_FAILED(res)) return res;
00544     if (!childNodes) return NS_ERROR_NULL_POINTER;
00545     PRUint32 childCount;
00546     res = childNodes->GetLength(&childCount);
00547     if (NS_FAILED(res)) return res;
00548 
00549     if (childCount == 1) {
00550       nsCOMPtr<nsIDOMNode> brNode;
00551       res = CreateBR(parentNode, 0, address_of(brNode));
00552     }
00553   }
00554   else {
00555     nsAutoString emptyStr;
00556 
00557     mHTMLCSSUtils->RemoveCSSProperty(aElement,
00558                                      nsEditProperty::cssPosition,
00559                                      emptyStr, PR_FALSE);
00560     mHTMLCSSUtils->RemoveCSSProperty(aElement,
00561                                      nsEditProperty::cssTop,
00562                                      emptyStr, PR_FALSE);
00563     mHTMLCSSUtils->RemoveCSSProperty(aElement,
00564                                      nsEditProperty::cssLeft,
00565                                      emptyStr, PR_FALSE);
00566     mHTMLCSSUtils->RemoveCSSProperty(aElement,
00567                                      nsEditProperty::cssZIndex,
00568                                      emptyStr, PR_FALSE);
00569 
00570     if (!nsHTMLEditUtils::IsImage(aElement)) {
00571       mHTMLCSSUtils->RemoveCSSProperty(aElement,
00572                                        nsEditProperty::cssWidth,
00573                                        emptyStr, PR_FALSE);
00574       mHTMLCSSUtils->RemoveCSSProperty(aElement,
00575                                        nsEditProperty::cssHeight,
00576                                        emptyStr, PR_FALSE);
00577     }
00578 
00579     PRBool hasStyleOrIdOrClass;
00580     res = HasStyleOrIdOrClass(aElement, &hasStyleOrIdOrClass);
00581     if (NS_FAILED(res)) return res;
00582     if (!hasStyleOrIdOrClass && nsHTMLEditUtils::IsDiv(aElement)) {
00583       nsCOMPtr<nsIHTMLEditRules> htmlRules = do_QueryInterface(mRules);
00584       if (!htmlRules) return NS_ERROR_FAILURE;
00585       res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
00586       if (NS_FAILED(res)) return res;
00587       res = RemoveContainer(aElement);
00588     }
00589   }
00590   return res;
00591 }
00592 
00593 NS_IMETHODIMP
00594 nsHTMLEditor::SetSnapToGridEnabled(PRBool aEnabled)
00595 {
00596   mSnapToGridEnabled = aEnabled;
00597   return NS_OK;
00598 }
00599 
00600 NS_IMETHODIMP
00601 nsHTMLEditor::GetSnapToGridEnabled(PRBool * aIsEnabled)
00602 {
00603   *aIsEnabled = mSnapToGridEnabled;
00604   return NS_OK;
00605 }
00606 
00607 NS_IMETHODIMP
00608 nsHTMLEditor::SetGridSize(PRUint32 aSize)
00609 {
00610   mGridSize = aSize;
00611   return NS_OK;
00612 }
00613 
00614 NS_IMETHODIMP
00615 nsHTMLEditor::GetGridSize(PRUint32 * aSize)
00616 {
00617   *aSize = mGridSize;
00618   return NS_OK;
00619 }
00620 
00621 // self-explanatory
00622 NS_IMETHODIMP
00623 nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, PRInt32 aX, PRInt32 aY)
00624 {
00625   nsAutoEditBatch batchIt(this);
00626 
00627   mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
00628                                       nsEditProperty::cssLeft,
00629                                       aX,
00630                                       PR_FALSE);
00631   mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
00632                                       nsEditProperty::cssTop,
00633                                       aY,
00634                                       PR_FALSE);
00635   return NS_OK;
00636 }
00637 
00638 // self-explanatory
00639 NS_IMETHODIMP
00640 nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn)
00641 {
00642   *aReturn = mAbsolutelyPositionedObject;
00643   NS_IF_ADDREF(*aReturn);
00644   return NS_OK;
00645 }
00646 
00647 nsresult
00648 nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement,
00649                                             nsAString & aReturn)
00650 {
00651   // we are going to outline the positioned element and bring it to the
00652   // front to overlap any other element intersecting with it. But
00653   // first, let's see what's the background and foreground colors of the
00654   // positioned element.
00655   // if background-image computed value is 'none,
00656   //   If the background color is 'auto' and R G B values of the foreground are
00657   //       each above #d0, use a black background
00658   //   If the background color is 'auto' and at least one of R G B values of
00659   //       the foreground is below #d0, use a white background
00660   // Otherwise don't change background/foreground
00661 
00662   aReturn.Truncate();
00663   
00664   nsAutoString bgImageStr;
00665   nsresult res =
00666     mHTMLCSSUtils->GetComputedProperty(aElement,
00667                                        nsEditProperty::cssBackgroundImage,
00668                                        bgImageStr);
00669   if (NS_FAILED(res)) return res;
00670   if (bgImageStr.EqualsLiteral("none")) {
00671     nsAutoString bgColorStr;
00672     res =
00673       mHTMLCSSUtils->GetComputedProperty(aElement,
00674                                          nsEditProperty::cssBackgroundColor,
00675                                          bgColorStr);
00676     if (NS_FAILED(res)) return res;
00677     if (bgColorStr.EqualsLiteral("transparent")) {
00678 
00679       nsCOMPtr<nsIDOMViewCSS> viewCSS;
00680       res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(viewCSS));
00681       if (NS_FAILED(res)) return res;
00682       nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
00683       res = viewCSS->GetComputedStyle(aElement, EmptyString(), getter_AddRefs(cssDecl));
00684       if (NS_FAILED(res)) return res;
00685       // from these declarations, get the one we want and that one only
00686       nsCOMPtr<nsIDOMCSSValue> colorCssValue;
00687       res = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), getter_AddRefs(colorCssValue));
00688       if (NS_FAILED(res)) return res;
00689 
00690       PRUint16 type;
00691       res = colorCssValue->GetCssValueType(&type);
00692       if (NS_FAILED(res)) return res;
00693       if (nsIDOMCSSValue::CSS_PRIMITIVE_VALUE == type) {
00694         nsCOMPtr<nsIDOMCSSPrimitiveValue> val = do_QueryInterface(colorCssValue);
00695         res = val->GetPrimitiveType(&type);
00696         if (NS_FAILED(res)) return res;
00697         if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == type) {
00698           nsCOMPtr<nsIDOMRGBColor> rgbColor;
00699           res = val->GetRGBColorValue(getter_AddRefs(rgbColor));
00700           if (NS_FAILED(res)) return res;
00701           nsCOMPtr<nsIDOMCSSPrimitiveValue> red, green, blue;
00702           float r, g, b;
00703           res = rgbColor->GetRed(getter_AddRefs(red));
00704           if (NS_FAILED(res)) return res;
00705           res = rgbColor->GetGreen(getter_AddRefs(green));
00706           if (NS_FAILED(res)) return res;
00707           res = rgbColor->GetBlue(getter_AddRefs(blue));
00708           if (NS_FAILED(res)) return res;
00709           res = red->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &r);
00710           if (NS_FAILED(res)) return res;
00711           res = green->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &g);
00712           if (NS_FAILED(res)) return res;
00713           res = blue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &b);
00714           if (NS_FAILED(res)) return res;
00715           if (r >= BLACK_BG_RGB_TRIGGER &&
00716               g >= BLACK_BG_RGB_TRIGGER &&
00717               b >= BLACK_BG_RGB_TRIGGER)
00718             aReturn.AssignLiteral("black");
00719           else
00720             aReturn.AssignLiteral("white");
00721           return NS_OK;
00722         }
00723       }
00724     }
00725   }
00726 
00727   return NS_OK;
00728 }