1 : /* ***** BEGIN LICENSE BLOCK *****
2 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
3 : *
4 : * The contents of this file are subject to the Mozilla Public License Version
5 : * 1.1 (the "License"); you may not use this file except in compliance with
6 : * the License. You may obtain a copy of the License at
7 : * http://www.mozilla.org/MPL/
8 : *
9 : * Software distributed under the License is distributed on an "AS IS" basis,
10 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 : * for the specific language governing rights and limitations under the
12 : * License.
13 : *
14 : * The Original Code is Mozilla.org.
15 : *
16 : * The Initial Developer of the Original Code is
17 : * Netscape Communications Corp.
18 : * Portions created by the Initial Developer are Copyright (C) 2003
19 : * the Initial Developer. All Rights Reserved.
20 : *
21 : * Contributor(s):
22 : * Daniel Glazman (glazman@netscape.com) (Original author)
23 : *
24 : * Alternatively, the contents of this file may be used under the terms of
25 : * either the GNU General Public License Version 2 or later (the "GPL"), or
26 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 : * in which case the provisions of the GPL or the LGPL are applicable instead
28 : * of those above. If you wish to allow use of your version of this file only
29 : * under the terms of either the GPL or the LGPL, and not to allow others to
30 : * use your version of this file under the terms of the MPL, indicate your
31 : * decision by deleting the provisions above and replace them with the notice
32 : * and other provisions required by the GPL or the LGPL. If you do not delete
33 : * the provisions above, a recipient may use your version of this file under
34 : * the terms of any one of the MPL, the GPL or the LGPL.
35 : *
36 : * ***** END LICENSE BLOCK ***** */
37 :
38 : #include <math.h>
39 :
40 : #include "nsHTMLEditor.h"
41 :
42 : #include "nsIContent.h"
43 : #include "nsIDocument.h"
44 : #include "nsIEditor.h"
45 : #include "nsIPresShell.h"
46 :
47 : #include "nsISelection.h"
48 :
49 : #include "nsTextEditUtils.h"
50 : #include "nsEditorUtils.h"
51 : #include "nsHTMLEditUtils.h"
52 : #include "nsTextEditRules.h"
53 : #include "nsHTMLEditRules.h"
54 :
55 : #include "nsIDOMHTMLElement.h"
56 : #include "nsIDOMNodeList.h"
57 :
58 : #include "nsIDOMEventTarget.h"
59 :
60 : #include "nsIDOMCSSValue.h"
61 : #include "nsIDOMCSSPrimitiveValue.h"
62 : #include "nsIDOMRGBColor.h"
63 :
64 : #include "mozilla/Preferences.h"
65 : #include "mozilla/dom/Element.h"
66 :
67 : using namespace mozilla;
68 :
69 : #define BLACK_BG_RGB_TRIGGER 0xd0
70 :
71 : NS_IMETHODIMP
72 0 : nsHTMLEditor::AbsolutePositionSelection(bool aEnabled)
73 : {
74 0 : nsAutoEditBatch beginBatching(this);
75 : nsAutoRules beginRulesSniffing(this,
76 : aEnabled ? kOpSetAbsolutePosition :
77 : kOpRemoveAbsolutePosition,
78 0 : nsIEditor::eNext);
79 :
80 : // the line below does not match the code; should it be removed?
81 : // Find out if the selection is collapsed:
82 0 : nsCOMPtr<nsISelection> selection;
83 0 : nsresult res = GetSelection(getter_AddRefs(selection));
84 0 : NS_ENSURE_SUCCESS(res, res);
85 0 : NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
86 :
87 : nsTextRulesInfo ruleInfo(aEnabled ?
88 : nsTextEditRules::kSetAbsolutePosition :
89 0 : nsTextEditRules::kRemoveAbsolutePosition);
90 : bool cancel, handled;
91 0 : res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
92 0 : if (NS_FAILED(res) || cancel)
93 0 : return res;
94 :
95 0 : return mRules->DidDoAction(selection, &ruleInfo, res);
96 : }
97 :
98 : NS_IMETHODIMP
99 0 : nsHTMLEditor::GetAbsolutelyPositionedSelectionContainer(nsIDOMElement **_retval)
100 : {
101 0 : nsCOMPtr<nsIDOMElement> element;
102 0 : nsresult res = GetSelectionContainer(getter_AddRefs(element));
103 0 : NS_ENSURE_SUCCESS(res, res);
104 :
105 0 : nsAutoString positionStr;
106 0 : nsCOMPtr<nsIDOMNode> node = do_QueryInterface(element);
107 0 : nsCOMPtr<nsIDOMNode> resultNode;
108 :
109 0 : while (!resultNode && node && !nsEditor::NodeIsType(node, nsEditProperty::html)) {
110 : res = mHTMLCSSUtils->GetComputedProperty(node, nsEditProperty::cssPosition,
111 0 : positionStr);
112 0 : NS_ENSURE_SUCCESS(res, res);
113 0 : if (positionStr.EqualsLiteral("absolute"))
114 0 : resultNode = node;
115 : else {
116 0 : nsCOMPtr<nsIDOMNode> parentNode;
117 0 : res = node->GetParentNode(getter_AddRefs(parentNode));
118 0 : NS_ENSURE_SUCCESS(res, res);
119 0 : node.swap(parentNode);
120 : }
121 : }
122 :
123 0 : element = do_QueryInterface(resultNode );
124 0 : *_retval = element;
125 0 : NS_IF_ADDREF(*_retval);
126 0 : return NS_OK;
127 : }
128 :
129 : NS_IMETHODIMP
130 0 : nsHTMLEditor::GetSelectionContainerAbsolutelyPositioned(bool *aIsSelectionContainerAbsolutelyPositioned)
131 : {
132 0 : *aIsSelectionContainerAbsolutelyPositioned = (mAbsolutelyPositionedObject != nsnull);
133 0 : return NS_OK;
134 : }
135 :
136 : NS_IMETHODIMP
137 0 : nsHTMLEditor::GetAbsolutePositioningEnabled(bool * aIsEnabled)
138 : {
139 0 : *aIsEnabled = mIsAbsolutelyPositioningEnabled;
140 0 : return NS_OK;
141 : }
142 :
143 : NS_IMETHODIMP
144 0 : nsHTMLEditor::SetAbsolutePositioningEnabled(bool aIsEnabled)
145 : {
146 0 : mIsAbsolutelyPositioningEnabled = aIsEnabled;
147 0 : return NS_OK;
148 : }
149 :
150 : NS_IMETHODIMP
151 0 : nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement,
152 : PRInt32 aChange,
153 : PRInt32 * aReturn)
154 : {
155 0 : NS_ENSURE_ARG_POINTER(aElement);
156 0 : NS_ENSURE_ARG_POINTER(aReturn);
157 0 : if (!aChange) // early way out, no change
158 0 : return NS_OK;
159 :
160 : PRInt32 zIndex;
161 0 : nsresult res = GetElementZIndex(aElement, &zIndex);
162 0 : NS_ENSURE_SUCCESS(res, res);
163 :
164 0 : zIndex = NS_MAX(zIndex + aChange, 0);
165 0 : SetElementZIndex(aElement, zIndex);
166 0 : *aReturn = zIndex;
167 :
168 0 : return NS_OK;
169 : }
170 :
171 : NS_IMETHODIMP
172 0 : nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement,
173 : PRInt32 aZindex)
174 : {
175 0 : NS_ENSURE_ARG_POINTER(aElement);
176 :
177 0 : nsAutoString zIndexStr;
178 0 : zIndexStr.AppendInt(aZindex);
179 :
180 : mHTMLCSSUtils->SetCSSProperty(aElement,
181 : nsEditProperty::cssZIndex,
182 : zIndexStr,
183 0 : false);
184 0 : return NS_OK;
185 : }
186 :
187 : NS_IMETHODIMP
188 0 : nsHTMLEditor::RelativeChangeZIndex(PRInt32 aChange)
189 : {
190 0 : nsAutoEditBatch beginBatching(this);
191 : nsAutoRules beginRulesSniffing(this,
192 : (aChange < 0) ? kOpDecreaseZIndex :
193 : kOpIncreaseZIndex,
194 0 : nsIEditor::eNext);
195 :
196 : // brade: can we get rid of this comment?
197 : // Find out if the selection is collapsed:
198 0 : nsCOMPtr<nsISelection> selection;
199 0 : nsresult res = GetSelection(getter_AddRefs(selection));
200 0 : NS_ENSURE_SUCCESS(res, res);
201 0 : NS_ENSURE_TRUE(selection, NS_ERROR_NULL_POINTER);
202 : nsTextRulesInfo ruleInfo((aChange < 0) ? nsTextEditRules::kDecreaseZIndex:
203 0 : nsTextEditRules::kIncreaseZIndex);
204 : bool cancel, handled;
205 0 : res = mRules->WillDoAction(selection, &ruleInfo, &cancel, &handled);
206 0 : if (cancel || NS_FAILED(res))
207 0 : return res;
208 :
209 0 : return mRules->DidDoAction(selection, &ruleInfo, res);
210 : }
211 :
212 : NS_IMETHODIMP
213 0 : nsHTMLEditor::GetElementZIndex(nsIDOMElement * aElement,
214 : PRInt32 * aZindex)
215 : {
216 0 : nsAutoString zIndexStr;
217 0 : *aZindex = 0;
218 :
219 : nsresult res = mHTMLCSSUtils->GetSpecifiedProperty(aElement,
220 : nsEditProperty::cssZIndex,
221 0 : zIndexStr);
222 0 : NS_ENSURE_SUCCESS(res, res);
223 0 : if (zIndexStr.EqualsLiteral("auto")) {
224 : // we have to look at the positioned ancestors
225 : // cf. CSS 2 spec section 9.9.1
226 0 : nsCOMPtr<nsIDOMNode> parentNode;
227 0 : res = aElement->GetParentNode(getter_AddRefs(parentNode));
228 0 : NS_ENSURE_SUCCESS(res, res);
229 0 : nsCOMPtr<nsIDOMNode> node = parentNode;
230 0 : nsAutoString positionStr;
231 0 : while (node &&
232 0 : zIndexStr.EqualsLiteral("auto") &&
233 0 : !nsTextEditUtils::IsBody(node)) {
234 : res = mHTMLCSSUtils->GetComputedProperty(node,
235 : nsEditProperty::cssPosition,
236 0 : positionStr);
237 0 : NS_ENSURE_SUCCESS(res, res);
238 0 : if (positionStr.EqualsLiteral("absolute")) {
239 : // ah, we found one, what's its z-index ? If its z-index is auto,
240 : // we have to continue climbing the document's tree
241 : res = mHTMLCSSUtils->GetComputedProperty(node,
242 : nsEditProperty::cssZIndex,
243 0 : zIndexStr);
244 0 : NS_ENSURE_SUCCESS(res, res);
245 : }
246 0 : res = node->GetParentNode(getter_AddRefs(parentNode));
247 0 : NS_ENSURE_SUCCESS(res, res);
248 0 : node = parentNode;
249 : }
250 : }
251 :
252 0 : if (!zIndexStr.EqualsLiteral("auto")) {
253 : PRInt32 errorCode;
254 0 : *aZindex = zIndexStr.ToInteger(&errorCode);
255 : }
256 :
257 0 : return NS_OK;
258 : }
259 :
260 : nsresult
261 0 : nsHTMLEditor::CreateGrabber(nsIDOMNode * aParentNode, nsIDOMElement ** aReturn)
262 : {
263 : // let's create a grabber through the element factory
264 0 : nsresult res = CreateAnonymousElement(NS_LITERAL_STRING("span"),
265 : aParentNode,
266 0 : NS_LITERAL_STRING("mozGrabber"),
267 : false,
268 0 : aReturn);
269 :
270 0 : NS_ENSURE_TRUE(*aReturn, NS_ERROR_FAILURE);
271 :
272 : // add the mouse listener so we can detect a click on a resizer
273 0 : nsCOMPtr<nsIDOMEventTarget> evtTarget(do_QueryInterface(*aReturn));
274 0 : evtTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
275 0 : mEventListener, false);
276 :
277 0 : return res;
278 : }
279 :
280 : NS_IMETHODIMP
281 0 : nsHTMLEditor::RefreshGrabber()
282 : {
283 0 : NS_ENSURE_TRUE(mAbsolutelyPositionedObject, NS_ERROR_NULL_POINTER);
284 :
285 : nsresult res = GetPositionAndDimensions(mAbsolutelyPositionedObject,
286 : mPositionedObjectX,
287 : mPositionedObjectY,
288 : mPositionedObjectWidth,
289 : mPositionedObjectHeight,
290 : mPositionedObjectBorderLeft,
291 : mPositionedObjectBorderTop,
292 : mPositionedObjectMarginLeft,
293 0 : mPositionedObjectMarginTop);
294 :
295 0 : NS_ENSURE_SUCCESS(res, res);
296 :
297 : SetAnonymousElementPosition(mPositionedObjectX+12,
298 : mPositionedObjectY-14,
299 0 : mGrabber);
300 0 : return NS_OK;
301 : }
302 :
303 : NS_IMETHODIMP
304 0 : nsHTMLEditor::HideGrabber()
305 : {
306 : nsresult res =
307 0 : mAbsolutelyPositionedObject->RemoveAttribute(NS_LITERAL_STRING("_moz_abspos"));
308 0 : NS_ENSURE_SUCCESS(res, res);
309 :
310 0 : mAbsolutelyPositionedObject = nsnull;
311 0 : NS_ENSURE_TRUE(mGrabber, NS_ERROR_NULL_POINTER);
312 :
313 : // get the presshell's document observer interface.
314 0 : nsCOMPtr<nsIPresShell> ps = GetPresShell();
315 : // We allow the pres shell to be null; when it is, we presume there
316 : // are no document observers to notify, but we still want to
317 : // UnbindFromTree.
318 :
319 0 : nsCOMPtr<nsIDOMNode> parentNode;
320 0 : res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
321 0 : NS_ENSURE_SUCCESS(res, res);
322 :
323 0 : nsCOMPtr<nsIContent> parentContent = do_QueryInterface(parentNode);
324 0 : NS_ENSURE_TRUE(parentContent, NS_ERROR_NULL_POINTER);
325 :
326 0 : DeleteRefToAnonymousNode(mGrabber, parentContent, ps);
327 0 : mGrabber = nsnull;
328 0 : DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
329 0 : mPositioningShadow = nsnull;
330 :
331 0 : return NS_OK;
332 : }
333 :
334 : NS_IMETHODIMP
335 0 : nsHTMLEditor::ShowGrabberOnElement(nsIDOMElement * aElement)
336 : {
337 0 : NS_ENSURE_ARG_POINTER(aElement);
338 :
339 0 : if (mGrabber) {
340 0 : NS_ERROR("call HideGrabber first");
341 0 : return NS_ERROR_UNEXPECTED;
342 : }
343 :
344 0 : nsAutoString classValue;
345 0 : nsresult res = CheckPositionedElementBGandFG(aElement, classValue);
346 0 : NS_ENSURE_SUCCESS(res, res);
347 :
348 0 : res = aElement->SetAttribute(NS_LITERAL_STRING("_moz_abspos"),
349 0 : classValue);
350 0 : NS_ENSURE_SUCCESS(res, res);
351 :
352 : // first, let's keep track of that element...
353 0 : mAbsolutelyPositionedObject = aElement;
354 :
355 0 : nsCOMPtr<nsIDOMNode> parentNode;
356 0 : res = aElement->GetParentNode(getter_AddRefs(parentNode));
357 0 : NS_ENSURE_SUCCESS(res, res);
358 :
359 0 : res = CreateGrabber(parentNode, getter_AddRefs(mGrabber));
360 0 : NS_ENSURE_SUCCESS(res, res);
361 :
362 : // and set its position
363 0 : return RefreshGrabber();
364 : }
365 :
366 : nsresult
367 0 : nsHTMLEditor::StartMoving(nsIDOMElement *aHandle)
368 : {
369 0 : nsCOMPtr<nsIDOMNode> parentNode;
370 0 : nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
371 0 : NS_ENSURE_SUCCESS(res, res);
372 :
373 : // now, let's create the resizing shadow
374 0 : res = CreateShadow(getter_AddRefs(mPositioningShadow),
375 0 : parentNode, mAbsolutelyPositionedObject);
376 0 : NS_ENSURE_SUCCESS(res,res);
377 : res = SetShadowPosition(mPositioningShadow, mAbsolutelyPositionedObject,
378 0 : mPositionedObjectX, mPositionedObjectY);
379 0 : NS_ENSURE_SUCCESS(res,res);
380 :
381 : // make the shadow appear
382 0 : mPositioningShadow->RemoveAttribute(NS_LITERAL_STRING("class"));
383 :
384 : // position it
385 : mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
386 0 : NS_LITERAL_STRING("width"),
387 0 : mPositionedObjectWidth);
388 : mHTMLCSSUtils->SetCSSPropertyPixels(mPositioningShadow,
389 0 : NS_LITERAL_STRING("height"),
390 0 : mPositionedObjectHeight);
391 :
392 0 : mIsMoving = true;
393 0 : return res;
394 : }
395 :
396 : void
397 0 : nsHTMLEditor::SnapToGrid(PRInt32 & newX, PRInt32 & newY)
398 : {
399 0 : if (mSnapToGridEnabled && mGridSize) {
400 0 : newX = (PRInt32) floor( ((float)newX / (float)mGridSize) + 0.5f ) * mGridSize;
401 0 : newY = (PRInt32) floor( ((float)newY / (float)mGridSize) + 0.5f ) * mGridSize;
402 : }
403 0 : }
404 :
405 : nsresult
406 0 : nsHTMLEditor::GrabberClicked()
407 : {
408 : // add a mouse move listener to the editor
409 0 : nsresult res = NS_OK;
410 0 : if (!mMouseMotionListenerP) {
411 0 : mMouseMotionListenerP = new ResizerMouseMotionListener(this);
412 0 : if (!mMouseMotionListenerP) {return NS_ERROR_NULL_POINTER;}
413 :
414 0 : nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
415 0 : NS_ENSURE_TRUE(piTarget, NS_ERROR_FAILURE);
416 :
417 0 : res = piTarget->AddEventListener(NS_LITERAL_STRING("mousemove"),
418 : mMouseMotionListenerP,
419 0 : false, false);
420 0 : NS_ASSERTION(NS_SUCCEEDED(res),
421 : "failed to register mouse motion listener");
422 : }
423 0 : mGrabberClicked = true;
424 0 : return res;
425 : }
426 :
427 : nsresult
428 0 : nsHTMLEditor::EndMoving()
429 : {
430 0 : if (mPositioningShadow) {
431 0 : nsCOMPtr<nsIPresShell> ps = GetPresShell();
432 0 : NS_ENSURE_TRUE(ps, NS_ERROR_NOT_INITIALIZED);
433 :
434 0 : nsCOMPtr<nsIDOMNode> parentNode;
435 0 : nsresult res = mGrabber->GetParentNode(getter_AddRefs(parentNode));
436 0 : NS_ENSURE_SUCCESS(res, res);
437 :
438 0 : nsCOMPtr<nsIContent> parentContent( do_QueryInterface(parentNode) );
439 0 : NS_ENSURE_TRUE(parentContent, NS_ERROR_FAILURE);
440 :
441 0 : DeleteRefToAnonymousNode(mPositioningShadow, parentContent, ps);
442 :
443 0 : mPositioningShadow = nsnull;
444 : }
445 0 : nsCOMPtr<nsIDOMEventTarget> piTarget = GetDOMEventTarget();
446 :
447 0 : if (piTarget && mMouseMotionListenerP) {
448 : #ifdef DEBUG
449 : nsresult res =
450 : #endif
451 0 : piTarget->RemoveEventListener(NS_LITERAL_STRING("mousemove"),
452 : mMouseMotionListenerP,
453 0 : false);
454 0 : NS_ASSERTION(NS_SUCCEEDED(res), "failed to remove mouse motion listener");
455 : }
456 0 : mMouseMotionListenerP = nsnull;
457 :
458 0 : mGrabberClicked = false;
459 0 : mIsMoving = false;
460 0 : nsCOMPtr<nsISelection> selection;
461 0 : GetSelection(getter_AddRefs(selection));
462 0 : if (!selection) {
463 0 : return NS_ERROR_NOT_INITIALIZED;
464 : }
465 0 : return CheckSelectionStateForAnonymousButtons(selection);
466 : }
467 : nsresult
468 0 : nsHTMLEditor::SetFinalPosition(PRInt32 aX, PRInt32 aY)
469 : {
470 0 : nsresult res = EndMoving();
471 0 : NS_ENSURE_SUCCESS(res, res);
472 :
473 : // we have now to set the new width and height of the resized object
474 : // we don't set the x and y position because we don't control that in
475 : // a normal HTML layout
476 0 : PRInt32 newX = mPositionedObjectX + aX - mOriginalX - (mPositionedObjectBorderLeft+mPositionedObjectMarginLeft);
477 0 : PRInt32 newY = mPositionedObjectY + aY - mOriginalY - (mPositionedObjectBorderTop+mPositionedObjectMarginTop);
478 :
479 0 : SnapToGrid(newX, newY);
480 :
481 0 : nsAutoString x, y;
482 0 : x.AppendInt(newX);
483 0 : y.AppendInt(newY);
484 :
485 : // we want one transaction only from a user's point of view
486 0 : nsAutoEditBatch batchIt(this);
487 :
488 : mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
489 : nsEditProperty::cssTop,
490 : newY,
491 0 : false);
492 : mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
493 : nsEditProperty::cssLeft,
494 : newX,
495 0 : false);
496 : // keep track of that size
497 0 : mPositionedObjectX = newX;
498 0 : mPositionedObjectY = newY;
499 :
500 0 : return RefreshResizers();
501 : }
502 :
503 : void
504 0 : nsHTMLEditor::AddPositioningOffset(PRInt32 & aX, PRInt32 & aY)
505 : {
506 : // Get the positioning offset
507 : PRInt32 positioningOffset =
508 0 : Preferences::GetInt("editor.positioning.offset", 0);
509 :
510 0 : aX += positioningOffset;
511 0 : aY += positioningOffset;
512 0 : }
513 :
514 : NS_IMETHODIMP
515 0 : nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
516 : bool aEnabled)
517 : {
518 0 : NS_ENSURE_ARG_POINTER(aElement);
519 :
520 0 : nsAutoString positionStr;
521 : mHTMLCSSUtils->GetComputedProperty(aElement, nsEditProperty::cssPosition,
522 0 : positionStr);
523 0 : bool isPositioned = (positionStr.EqualsLiteral("absolute"));
524 :
525 : // nothing to do if the element is already in the state we want
526 0 : if (isPositioned == aEnabled)
527 0 : return NS_OK;
528 :
529 0 : nsAutoEditBatch batchIt(this);
530 : nsresult res;
531 :
532 0 : if (aEnabled) {
533 : PRInt32 x, y;
534 0 : GetElementOrigin(aElement, x, y);
535 :
536 : mHTMLCSSUtils->SetCSSProperty(aElement,
537 : nsEditProperty::cssPosition,
538 0 : NS_LITERAL_STRING("absolute"),
539 0 : false);
540 :
541 0 : AddPositioningOffset(x, y);
542 0 : SnapToGrid(x, y);
543 0 : SetElementPosition(aElement, x, y);
544 :
545 : // we may need to create a br if the positioned element is alone in its
546 : // container
547 0 : nsCOMPtr<nsIDOMNode> parentNode;
548 0 : res = aElement->GetParentNode(getter_AddRefs(parentNode));
549 0 : NS_ENSURE_SUCCESS(res, res);
550 :
551 0 : nsCOMPtr<nsIDOMNodeList> childNodes;
552 0 : res = parentNode->GetChildNodes(getter_AddRefs(childNodes));
553 0 : NS_ENSURE_SUCCESS(res, res);
554 0 : NS_ENSURE_TRUE(childNodes, NS_ERROR_NULL_POINTER);
555 : PRUint32 childCount;
556 0 : res = childNodes->GetLength(&childCount);
557 0 : NS_ENSURE_SUCCESS(res, res);
558 :
559 0 : if (childCount == 1) {
560 0 : nsCOMPtr<nsIDOMNode> brNode;
561 0 : res = CreateBR(parentNode, 0, address_of(brNode));
562 : }
563 : }
564 : else {
565 0 : res = NS_OK;
566 : mHTMLCSSUtils->RemoveCSSProperty(aElement,
567 : nsEditProperty::cssPosition,
568 0 : EmptyString(), false);
569 : mHTMLCSSUtils->RemoveCSSProperty(aElement,
570 : nsEditProperty::cssTop,
571 0 : EmptyString(), false);
572 : mHTMLCSSUtils->RemoveCSSProperty(aElement,
573 : nsEditProperty::cssLeft,
574 0 : EmptyString(), false);
575 : mHTMLCSSUtils->RemoveCSSProperty(aElement,
576 : nsEditProperty::cssZIndex,
577 0 : EmptyString(), false);
578 :
579 0 : if (!nsHTMLEditUtils::IsImage(aElement)) {
580 : mHTMLCSSUtils->RemoveCSSProperty(aElement,
581 : nsEditProperty::cssWidth,
582 0 : EmptyString(), false);
583 : mHTMLCSSUtils->RemoveCSSProperty(aElement,
584 : nsEditProperty::cssHeight,
585 0 : EmptyString(), false);
586 : }
587 :
588 0 : nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
589 0 : if (element && element->IsHTML(nsGkAtoms::div) && !HasStyleOrIdOrClass(element)) {
590 0 : nsHTMLEditRules* htmlRules = static_cast<nsHTMLEditRules*>(mRules.get());
591 0 : NS_ENSURE_TRUE(htmlRules, NS_ERROR_FAILURE);
592 0 : res = htmlRules->MakeSureElemStartsOrEndsOnCR(aElement);
593 0 : NS_ENSURE_SUCCESS(res, res);
594 0 : res = RemoveContainer(aElement);
595 : }
596 : }
597 0 : return res;
598 : }
599 :
600 : NS_IMETHODIMP
601 0 : nsHTMLEditor::SetSnapToGridEnabled(bool aEnabled)
602 : {
603 0 : mSnapToGridEnabled = aEnabled;
604 0 : return NS_OK;
605 : }
606 :
607 : NS_IMETHODIMP
608 0 : nsHTMLEditor::GetSnapToGridEnabled(bool * aIsEnabled)
609 : {
610 0 : *aIsEnabled = mSnapToGridEnabled;
611 0 : return NS_OK;
612 : }
613 :
614 : NS_IMETHODIMP
615 0 : nsHTMLEditor::SetGridSize(PRUint32 aSize)
616 : {
617 0 : mGridSize = aSize;
618 0 : return NS_OK;
619 : }
620 :
621 : NS_IMETHODIMP
622 0 : nsHTMLEditor::GetGridSize(PRUint32 * aSize)
623 : {
624 0 : *aSize = mGridSize;
625 0 : return NS_OK;
626 : }
627 :
628 : // self-explanatory
629 : NS_IMETHODIMP
630 0 : nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, PRInt32 aX, PRInt32 aY)
631 : {
632 0 : nsAutoEditBatch batchIt(this);
633 :
634 : mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
635 : nsEditProperty::cssLeft,
636 : aX,
637 0 : false);
638 : mHTMLCSSUtils->SetCSSPropertyPixels(aElement,
639 : nsEditProperty::cssTop,
640 : aY,
641 0 : false);
642 0 : return NS_OK;
643 : }
644 :
645 : // self-explanatory
646 : NS_IMETHODIMP
647 0 : nsHTMLEditor::GetPositionedElement(nsIDOMElement ** aReturn)
648 : {
649 0 : *aReturn = mAbsolutelyPositionedObject;
650 0 : NS_IF_ADDREF(*aReturn);
651 0 : return NS_OK;
652 : }
653 :
654 : nsresult
655 0 : nsHTMLEditor::CheckPositionedElementBGandFG(nsIDOMElement * aElement,
656 : nsAString & aReturn)
657 : {
658 : // we are going to outline the positioned element and bring it to the
659 : // front to overlap any other element intersecting with it. But
660 : // first, let's see what's the background and foreground colors of the
661 : // positioned element.
662 : // if background-image computed value is 'none,
663 : // If the background color is 'auto' and R G B values of the foreground are
664 : // each above #d0, use a black background
665 : // If the background color is 'auto' and at least one of R G B values of
666 : // the foreground is below #d0, use a white background
667 : // Otherwise don't change background/foreground
668 :
669 0 : aReturn.Truncate();
670 :
671 0 : nsAutoString bgImageStr;
672 : nsresult res =
673 : mHTMLCSSUtils->GetComputedProperty(aElement,
674 : nsEditProperty::cssBackgroundImage,
675 0 : bgImageStr);
676 0 : NS_ENSURE_SUCCESS(res, res);
677 0 : if (bgImageStr.EqualsLiteral("none")) {
678 0 : nsAutoString bgColorStr;
679 : res =
680 : mHTMLCSSUtils->GetComputedProperty(aElement,
681 : nsEditProperty::cssBackgroundColor,
682 0 : bgColorStr);
683 0 : NS_ENSURE_SUCCESS(res, res);
684 0 : if (bgColorStr.EqualsLiteral("transparent")) {
685 0 : nsCOMPtr<nsIDOMWindow> window;
686 0 : res = mHTMLCSSUtils->GetDefaultViewCSS(aElement, getter_AddRefs(window));
687 0 : NS_ENSURE_SUCCESS(res, res);
688 :
689 0 : nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
690 0 : res = window->GetComputedStyle(aElement, EmptyString(), getter_AddRefs(cssDecl));
691 0 : NS_ENSURE_SUCCESS(res, res);
692 :
693 : // from these declarations, get the one we want and that one only
694 0 : nsCOMPtr<nsIDOMCSSValue> colorCssValue;
695 0 : res = cssDecl->GetPropertyCSSValue(NS_LITERAL_STRING("color"), getter_AddRefs(colorCssValue));
696 0 : NS_ENSURE_SUCCESS(res, res);
697 :
698 : PRUint16 type;
699 0 : res = colorCssValue->GetCssValueType(&type);
700 0 : NS_ENSURE_SUCCESS(res, res);
701 0 : if (nsIDOMCSSValue::CSS_PRIMITIVE_VALUE == type) {
702 0 : nsCOMPtr<nsIDOMCSSPrimitiveValue> val = do_QueryInterface(colorCssValue);
703 0 : res = val->GetPrimitiveType(&type);
704 0 : NS_ENSURE_SUCCESS(res, res);
705 0 : if (nsIDOMCSSPrimitiveValue::CSS_RGBCOLOR == type) {
706 0 : nsCOMPtr<nsIDOMRGBColor> rgbColor;
707 0 : res = val->GetRGBColorValue(getter_AddRefs(rgbColor));
708 0 : NS_ENSURE_SUCCESS(res, res);
709 0 : nsCOMPtr<nsIDOMCSSPrimitiveValue> red, green, blue;
710 : float r, g, b;
711 0 : res = rgbColor->GetRed(getter_AddRefs(red));
712 0 : NS_ENSURE_SUCCESS(res, res);
713 0 : res = rgbColor->GetGreen(getter_AddRefs(green));
714 0 : NS_ENSURE_SUCCESS(res, res);
715 0 : res = rgbColor->GetBlue(getter_AddRefs(blue));
716 0 : NS_ENSURE_SUCCESS(res, res);
717 0 : res = red->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &r);
718 0 : NS_ENSURE_SUCCESS(res, res);
719 0 : res = green->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &g);
720 0 : NS_ENSURE_SUCCESS(res, res);
721 0 : res = blue->GetFloatValue(nsIDOMCSSPrimitiveValue::CSS_NUMBER, &b);
722 0 : NS_ENSURE_SUCCESS(res, res);
723 0 : if (r >= BLACK_BG_RGB_TRIGGER &&
724 : g >= BLACK_BG_RGB_TRIGGER &&
725 : b >= BLACK_BG_RGB_TRIGGER)
726 0 : aReturn.AssignLiteral("black");
727 : else
728 0 : aReturn.AssignLiteral("white");
729 0 : return NS_OK;
730 : }
731 : }
732 : }
733 : }
734 :
735 0 : return NS_OK;
736 : }
|