mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1056166 part 5 - Clean up ChangeCSSInlineStyleTxn; r=ehsan
--HG-- rename : editor/libeditor/ChangeCSSInlineStyleTxn.cpp => editor/libeditor/ChangeStyleTxn.cpp rename : editor/libeditor/ChangeCSSInlineStyleTxn.h => editor/libeditor/ChangeStyleTxn.h
This commit is contained in:
parent
4ba29d6526
commit
7547add233
@ -1,315 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ChangeCSSInlineStyleTxn.h"
|
||||
#include "nsAString.h" // for nsAString_internal::Append, etc
|
||||
#include "nsCRT.h" // for nsCRT
|
||||
#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc
|
||||
#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc
|
||||
#include "nsGkAtoms.h" // for nsGkAtoms, etc
|
||||
#include "nsIAtom.h" // for nsIAtom
|
||||
#include "nsIDOMCSSStyleDeclaration.h" // for nsIDOMCSSStyleDeclaration
|
||||
#include "nsIDOMElement.h" // for nsIDOMElement
|
||||
#include "nsIDOMElementCSSInlineStyle.h"
|
||||
#include "nsISupportsImpl.h" // for EditTxn::QueryInterface, etc
|
||||
#include "nsISupportsUtils.h" // for NS_ADDREF
|
||||
#include "nsLiteralString.h" // for NS_LITERAL_STRING, etc
|
||||
#include "nsReadableUtils.h" // for ToNewUnicode
|
||||
#include "nsString.h" // for nsAutoString, nsString, etc
|
||||
#include "nsUnicharUtils.h"
|
||||
#include "nsXPCOM.h" // for NS_Free
|
||||
|
||||
class nsIEditor;
|
||||
|
||||
#define kNullCh (char16_t('\0'))
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeCSSInlineStyleTxn, EditTxn,
|
||||
mElement)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeCSSInlineStyleTxn)
|
||||
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
|
||||
|
||||
// answers true if aValue is in the string list of white-space separated values aValueList
|
||||
// a case-sensitive search is performed if aCaseSensitive is true
|
||||
bool
|
||||
ChangeCSSInlineStyleTxn::ValueIncludes(const nsAString &aValueList, const nsAString &aValue, bool aCaseSensitive)
|
||||
{
|
||||
nsAutoString valueList(aValueList);
|
||||
bool result = false;
|
||||
|
||||
valueList.Append(kNullCh); // put an extra null at the end
|
||||
|
||||
char16_t *value = ToNewUnicode(aValue);
|
||||
char16_t *start = valueList.BeginWriting();
|
||||
char16_t *end = start;
|
||||
|
||||
while (kNullCh != *start) {
|
||||
while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) { // skip leading space
|
||||
start++;
|
||||
}
|
||||
end = start;
|
||||
|
||||
while ((kNullCh != *end) && (false == nsCRT::IsAsciiSpace(*end))) { // look for space or end
|
||||
end++;
|
||||
}
|
||||
*end = kNullCh; // end string here
|
||||
|
||||
if (start < end) {
|
||||
if (aCaseSensitive) {
|
||||
if (!nsCRT::strcmp(value, start)) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (nsDependentString(value).Equals(nsDependentString(start),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
start = ++end;
|
||||
}
|
||||
NS_Free(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
// removes the value aRemoveValue from the string list of white-space separated values aValueList
|
||||
void
|
||||
ChangeCSSInlineStyleTxn::RemoveValueFromListOfValues(nsAString & aValues, const nsAString & aRemoveValue)
|
||||
{
|
||||
nsAutoString classStr(aValues); // copy to work buffer nsAutoString rv(aRemoveValue);
|
||||
nsAutoString outString;
|
||||
classStr.Append(kNullCh); // put an extra null at the end
|
||||
|
||||
char16_t *start = classStr.BeginWriting();
|
||||
char16_t *end = start;
|
||||
|
||||
while (kNullCh != *start) {
|
||||
while ((kNullCh != *start) && nsCRT::IsAsciiSpace(*start)) { // skip leading space
|
||||
start++;
|
||||
}
|
||||
end = start;
|
||||
|
||||
while ((kNullCh != *end) && (false == nsCRT::IsAsciiSpace(*end))) { // look for space or end
|
||||
end++;
|
||||
}
|
||||
*end = kNullCh; // end string here
|
||||
|
||||
if (start < end) {
|
||||
if (!aRemoveValue.Equals(start)) {
|
||||
outString.Append(start);
|
||||
outString.Append(char16_t(' '));
|
||||
}
|
||||
}
|
||||
|
||||
start = ++end;
|
||||
}
|
||||
aValues.Assign(outString);
|
||||
}
|
||||
|
||||
ChangeCSSInlineStyleTxn::ChangeCSSInlineStyleTxn()
|
||||
: EditTxn()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::Init(nsIEditor *aEditor,
|
||||
nsIDOMElement *aElement,
|
||||
nsIAtom *aProperty,
|
||||
const nsAString& aValue,
|
||||
bool aRemoveProperty)
|
||||
{
|
||||
NS_ASSERTION(aEditor && aElement, "bad arg");
|
||||
if (!aEditor || !aElement) { return NS_ERROR_NULL_POINTER; }
|
||||
|
||||
mEditor = aEditor;
|
||||
mElement = do_QueryInterface(aElement);
|
||||
mProperty = aProperty;
|
||||
NS_ADDREF(mProperty);
|
||||
mValue.Assign(aValue);
|
||||
mRemoveProperty = aRemoveProperty;
|
||||
mUndoAttributeWasSet = false;
|
||||
mRedoAttributeWasSet = false;
|
||||
mUndoValue.Truncate();
|
||||
mRedoValue.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::DoTransaction(void)
|
||||
{
|
||||
NS_ASSERTION(mEditor && mElement, "bad state");
|
||||
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
|
||||
NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||
nsresult result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsAutoString propertyNameString;
|
||||
mProperty->ToString(propertyNameString);
|
||||
|
||||
NS_NAMED_LITERAL_STRING(styleAttr, "style");
|
||||
result = mElement->HasAttribute(styleAttr, &mUndoAttributeWasSet);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
|
||||
nsAutoString values;
|
||||
result = cssDecl->GetPropertyValue(propertyNameString, values);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
mUndoValue.Assign(values);
|
||||
|
||||
// does this property accept more than 1 value ?
|
||||
// we need to know that because of bug 62682
|
||||
bool multiple = AcceptsMoreThanOneValue(mProperty);
|
||||
|
||||
if (mRemoveProperty) {
|
||||
nsAutoString returnString;
|
||||
if (multiple) {
|
||||
// the property can have more than one value, let's remove only
|
||||
// the value we have to remove and not the others
|
||||
|
||||
// the 2 lines below are a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
|
||||
// is not yet implemented (bug 62682)
|
||||
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
|
||||
RemoveValueFromListOfValues(values, mValue);
|
||||
if (values.IsEmpty()) {
|
||||
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
else {
|
||||
nsAutoString priority;
|
||||
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
result = cssDecl->SetProperty(propertyNameString, values,
|
||||
priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nsAutoString priority;
|
||||
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
if (multiple) {
|
||||
// the property can have more than one value, let's add
|
||||
// the value we have to add to the others
|
||||
|
||||
// the line below is a workaround because nsDOMCSSDeclaration::GetPropertyCSSValue
|
||||
// is not yet implemented (bug 62682)
|
||||
AddValueToMultivalueProperty(values, mValue);
|
||||
}
|
||||
else
|
||||
values.Assign(mValue);
|
||||
result = cssDecl->SetProperty(propertyNameString, values,
|
||||
priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
|
||||
// let's be sure we don't keep an empty style attribute
|
||||
uint32_t length;
|
||||
result = cssDecl->GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
if (!length) {
|
||||
result = mElement->RemoveAttribute(styleAttr);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
else
|
||||
mRedoAttributeWasSet = true;
|
||||
|
||||
return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
|
||||
}
|
||||
|
||||
nsresult ChangeCSSInlineStyleTxn::SetStyle(bool aAttributeWasSet,
|
||||
nsAString & aValue)
|
||||
{
|
||||
NS_ASSERTION(mEditor && mElement, "bad state");
|
||||
if (!mEditor || !mElement) { return NS_ERROR_NOT_INITIALIZED; }
|
||||
|
||||
nsresult result = NS_OK;
|
||||
if (aAttributeWasSet) {
|
||||
// the style attribute was set and not empty, let's recreate the declaration
|
||||
nsAutoString propertyNameString;
|
||||
mProperty->ToString(propertyNameString);
|
||||
|
||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles = do_QueryInterface(mElement);
|
||||
NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if (aValue.IsEmpty()) {
|
||||
// an empty value means we have to remove the property
|
||||
nsAutoString returnString;
|
||||
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||
}
|
||||
else {
|
||||
// let's recreate the declaration as it was
|
||||
nsAutoString priority;
|
||||
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
result = cssDecl->SetProperty(propertyNameString, aValue, priority);
|
||||
}
|
||||
}
|
||||
else
|
||||
result = mElement->RemoveAttribute(NS_LITERAL_STRING("style"));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::UndoTransaction(void)
|
||||
{
|
||||
return SetStyle(mUndoAttributeWasSet, mUndoValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::RedoTransaction(void)
|
||||
{
|
||||
return SetStyle(mRedoAttributeWasSet, mRedoValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP ChangeCSSInlineStyleTxn::GetTxnDescription(nsAString& aString)
|
||||
{
|
||||
aString.AssignLiteral("ChangeCSSInlineStyleTxn: [mRemoveProperty == ");
|
||||
|
||||
if (!mRemoveProperty)
|
||||
aString.AppendLiteral("false] ");
|
||||
else
|
||||
aString.AppendLiteral("true] ");
|
||||
nsAutoString tempString;
|
||||
mProperty->ToString(tempString);
|
||||
aString += tempString;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// answers true if the CSS property accepts more than one value
|
||||
bool
|
||||
ChangeCSSInlineStyleTxn::AcceptsMoreThanOneValue(nsIAtom *aCSSProperty)
|
||||
{
|
||||
return aCSSProperty == nsGkAtoms::text_decoration;
|
||||
}
|
||||
|
||||
// adds the value aNewValue to the list of white-space separated values aValues
|
||||
NS_IMETHODIMP
|
||||
ChangeCSSInlineStyleTxn::AddValueToMultivalueProperty(nsAString & aValues, const nsAString & aNewValue)
|
||||
{
|
||||
if (aValues.IsEmpty()
|
||||
|| aValues.LowerCaseEqualsLiteral("none")) {
|
||||
// the list of values is empty of the value is 'none'
|
||||
aValues.Assign(aNewValue);
|
||||
}
|
||||
else if (!ValueIncludes(aValues, aNewValue, false)) {
|
||||
// we already have another value but not this one; add it
|
||||
aValues.Append(char16_t(' '));
|
||||
aValues.Append(aNewValue);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
@ -1,114 +0,0 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ChangeCSSInlineStyleTxn_h__
|
||||
#define ChangeCSSInlineStyleTxn_h__
|
||||
|
||||
#include "EditTxn.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsID.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsString.h"
|
||||
#include "nscore.h"
|
||||
|
||||
class nsIAtom;
|
||||
class nsIEditor;
|
||||
|
||||
/**
|
||||
* A transaction that changes the value of a CSS inline style of a content node.
|
||||
* This transaction covers add, remove, and change a property's value.
|
||||
*/
|
||||
class ChangeCSSInlineStyleTxn : public EditTxn
|
||||
{
|
||||
public:
|
||||
/** Initialize the transaction.
|
||||
* @param aEditor [IN] the object providing core editing operations
|
||||
* @param aNode [IN] the node whose style attribute will be changed
|
||||
* @param aProperty [IN] the name of the property to change
|
||||
* @param aValue [IN] the new value for aProperty, if aRemoveProperty is false
|
||||
* @param aRemoveProperty [IN] if true, remove aProperty from style attribute
|
||||
*/
|
||||
NS_IMETHOD Init(nsIEditor * aEditor,
|
||||
nsIDOMElement * aElement,
|
||||
nsIAtom * aProperty,
|
||||
const nsAString & aValue,
|
||||
bool aRemoveProperty);
|
||||
|
||||
/** returns true if the list of white-space separated values contains aValue
|
||||
*
|
||||
* @return true if the value is in the list of values
|
||||
* @param aValueList [IN] a list of white-space separated values
|
||||
* @param aValue [IN] the value to look for in the list
|
||||
* @param aCaseSensitive [IN] a boolean being true if a case-sensitive search is needed
|
||||
*/
|
||||
static bool ValueIncludes(const nsAString & aValueList, const nsAString & aValue, bool aCaseSensitive);
|
||||
|
||||
/** adds the value aNewValue to the list of white-space separated values aValues
|
||||
*
|
||||
* @param aValues [IN/OUT] a list of wite-space separated values
|
||||
* @param aNewValue [IN] a value this code adds to aValues if it is not already in
|
||||
*/
|
||||
NS_IMETHOD AddValueToMultivalueProperty(nsAString & aValues, const nsAString & aNewValue);
|
||||
|
||||
ChangeCSSInlineStyleTxn();
|
||||
|
||||
private:
|
||||
/** returns true if the property accepts more than one value
|
||||
*
|
||||
* @return true if the property accepts more than one value
|
||||
* @param aCSSProperty [IN] the CSS property
|
||||
*/
|
||||
bool AcceptsMoreThanOneValue(nsIAtom * aCSSProperty);
|
||||
|
||||
/** remove a value from a list of white-space separated values
|
||||
* @param aValues [IN] a list of white-space separated values
|
||||
* @param aRemoveValue [IN] the value to remove from the list
|
||||
*/
|
||||
void RemoveValueFromListOfValues(nsAString & aValues, const nsAString & aRemoveValue);
|
||||
|
||||
/** If the boolean is true and if the value is not the empty string,
|
||||
* set the property in the transaction to that value; if the value
|
||||
* is empty, remove the property from element's styles. If the boolean
|
||||
* is false, just remove the style attribute.
|
||||
*/
|
||||
nsresult SetStyle(bool aAttributeWasSet, nsAString & aValue);
|
||||
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeCSSInlineStyleTxn, EditTxn)
|
||||
NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr);
|
||||
|
||||
NS_DECL_EDITTXN
|
||||
|
||||
NS_IMETHOD RedoTransaction();
|
||||
|
||||
protected:
|
||||
|
||||
/** the editor that created this transaction */
|
||||
nsIEditor *mEditor;
|
||||
|
||||
/** the element to operate upon */
|
||||
nsCOMPtr<nsIDOMElement> mElement;
|
||||
|
||||
/** the CSS property to change */
|
||||
nsIAtom *mProperty;
|
||||
|
||||
/** the value to set the property to (ignored if mRemoveProperty==true) */
|
||||
nsString mValue;
|
||||
|
||||
/** the value to set the property to for undo */
|
||||
nsString mUndoValue;
|
||||
/** the value to set the property to for redo */
|
||||
nsString mRedoValue;
|
||||
/** true if the style attribute was present and not empty before DoTransaction */
|
||||
bool mUndoAttributeWasSet;
|
||||
/** true if the style attribute is present and not empty after DoTransaction */
|
||||
bool mRedoAttributeWasSet;
|
||||
|
||||
/** true if the operation is to remove mProperty from mElement */
|
||||
bool mRemoveProperty;
|
||||
};
|
||||
|
||||
#endif
|
299
editor/libeditor/ChangeStyleTxn.cpp
Normal file
299
editor/libeditor/ChangeStyleTxn.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ChangeStyleTxn.h"
|
||||
|
||||
#include "mozilla/dom/Element.h" // for Element
|
||||
#include "nsAString.h" // for nsAString_internal::Append, etc
|
||||
#include "nsCRT.h" // for nsCRT::IsAsciiSpace
|
||||
#include "nsDebug.h" // for NS_ENSURE_SUCCESS, etc
|
||||
#include "nsError.h" // for NS_ERROR_NULL_POINTER, etc
|
||||
#include "nsGkAtoms.h" // for nsGkAtoms, etc
|
||||
#include "nsIDOMCSSStyleDeclaration.h" // for nsIDOMCSSStyleDeclaration
|
||||
#include "nsIDOMElementCSSInlineStyle.h" // for nsIDOMElementCSSInlineStyle
|
||||
#include "nsLiteralString.h" // for NS_LITERAL_STRING, etc
|
||||
#include "nsReadableUtils.h" // for ToNewUnicode
|
||||
#include "nsString.h" // for nsAutoString, nsString, etc
|
||||
#include "nsUnicharUtils.h" // for nsCaseInsensitiveStringComparator
|
||||
#include "nsXPCOM.h" // for NS_Free
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
#define kNullCh (char16_t('\0'))
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_INHERITED(ChangeStyleTxn, EditTxn, mElement)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(ChangeStyleTxn)
|
||||
NS_INTERFACE_MAP_END_INHERITING(EditTxn)
|
||||
|
||||
NS_IMPL_ADDREF_INHERITED(ChangeStyleTxn, EditTxn)
|
||||
NS_IMPL_RELEASE_INHERITED(ChangeStyleTxn, EditTxn)
|
||||
|
||||
ChangeStyleTxn::~ChangeStyleTxn()
|
||||
{
|
||||
}
|
||||
|
||||
// Answers true if aValue is in the string list of white-space separated values
|
||||
// aValueList.
|
||||
bool
|
||||
ChangeStyleTxn::ValueIncludes(const nsAString &aValueList,
|
||||
const nsAString &aValue)
|
||||
{
|
||||
nsAutoString valueList(aValueList);
|
||||
bool result = false;
|
||||
|
||||
// put an extra null at the end
|
||||
valueList.Append(kNullCh);
|
||||
|
||||
char16_t* value = ToNewUnicode(aValue);
|
||||
char16_t* start = valueList.BeginWriting();
|
||||
char16_t* end = start;
|
||||
|
||||
while (kNullCh != *start) {
|
||||
while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) {
|
||||
// skip leading space
|
||||
start++;
|
||||
}
|
||||
end = start;
|
||||
|
||||
while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) {
|
||||
// look for space or end
|
||||
end++;
|
||||
}
|
||||
// end string here
|
||||
*end = kNullCh;
|
||||
|
||||
if (start < end) {
|
||||
if (nsDependentString(value).Equals(nsDependentString(start),
|
||||
nsCaseInsensitiveStringComparator())) {
|
||||
result = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
start = ++end;
|
||||
}
|
||||
NS_Free(value);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Removes the value aRemoveValue from the string list of white-space separated
|
||||
// values aValueList
|
||||
void
|
||||
ChangeStyleTxn::RemoveValueFromListOfValues(nsAString& aValues,
|
||||
const nsAString& aRemoveValue)
|
||||
{
|
||||
nsAutoString classStr(aValues);
|
||||
nsAutoString outString;
|
||||
// put an extra null at the end
|
||||
classStr.Append(kNullCh);
|
||||
|
||||
char16_t* start = classStr.BeginWriting();
|
||||
char16_t* end = start;
|
||||
|
||||
while (kNullCh != *start) {
|
||||
while (kNullCh != *start && nsCRT::IsAsciiSpace(*start)) {
|
||||
// skip leading space
|
||||
start++;
|
||||
}
|
||||
end = start;
|
||||
|
||||
while (kNullCh != *end && !nsCRT::IsAsciiSpace(*end)) {
|
||||
// look for space or end
|
||||
end++;
|
||||
}
|
||||
// end string here
|
||||
*end = kNullCh;
|
||||
|
||||
if (start < end && !aRemoveValue.Equals(start)) {
|
||||
outString.Append(start);
|
||||
outString.Append(char16_t(' '));
|
||||
}
|
||||
|
||||
start = ++end;
|
||||
}
|
||||
aValues.Assign(outString);
|
||||
}
|
||||
|
||||
ChangeStyleTxn::ChangeStyleTxn(Element& aElement, nsIAtom& aProperty,
|
||||
const nsAString& aValue,
|
||||
EChangeType aChangeType)
|
||||
: EditTxn()
|
||||
, mElement(&aElement)
|
||||
, mProperty(&aProperty)
|
||||
, mValue(aValue)
|
||||
, mRemoveProperty(aChangeType == eRemove)
|
||||
, mUndoValue()
|
||||
, mRedoValue()
|
||||
, mUndoAttributeWasSet(false)
|
||||
, mRedoAttributeWasSet(false)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChangeStyleTxn::DoTransaction()
|
||||
{
|
||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles =
|
||||
do_QueryInterface(mElement);
|
||||
NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||
nsresult result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
|
||||
|
||||
nsAutoString propertyNameString;
|
||||
mProperty->ToString(propertyNameString);
|
||||
|
||||
mUndoAttributeWasSet = mElement->HasAttr(kNameSpaceID_None,
|
||||
nsGkAtoms::style);
|
||||
|
||||
nsAutoString values;
|
||||
result = cssDecl->GetPropertyValue(propertyNameString, values);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
mUndoValue.Assign(values);
|
||||
|
||||
// Does this property accept more than one value? (bug 62682)
|
||||
bool multiple = AcceptsMoreThanOneValue(*mProperty);
|
||||
|
||||
if (mRemoveProperty) {
|
||||
nsAutoString returnString;
|
||||
if (multiple) {
|
||||
// Let's remove only the value we have to remove and not the others
|
||||
|
||||
// The two lines below are a workaround because
|
||||
// nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug
|
||||
// 62682)
|
||||
RemoveValueFromListOfValues(values, NS_LITERAL_STRING("none"));
|
||||
RemoveValueFromListOfValues(values, mValue);
|
||||
if (values.IsEmpty()) {
|
||||
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
} else {
|
||||
nsAutoString priority;
|
||||
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
result = cssDecl->SetProperty(propertyNameString, values,
|
||||
priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
} else {
|
||||
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
} else {
|
||||
nsAutoString priority;
|
||||
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
if (multiple) {
|
||||
// Let's add the value we have to add to the others
|
||||
|
||||
// The line below is a workaround because
|
||||
// nsDOMCSSDeclaration::GetPropertyCSSValue is not yet implemented (bug
|
||||
// 62682)
|
||||
AddValueToMultivalueProperty(values, mValue);
|
||||
} else {
|
||||
values.Assign(mValue);
|
||||
}
|
||||
result = cssDecl->SetProperty(propertyNameString, values,
|
||||
priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
}
|
||||
|
||||
// Let's be sure we don't keep an empty style attribute
|
||||
uint32_t length;
|
||||
result = cssDecl->GetLength(&length);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
if (!length) {
|
||||
result = mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
} else {
|
||||
mRedoAttributeWasSet = true;
|
||||
}
|
||||
|
||||
return cssDecl->GetPropertyValue(propertyNameString, mRedoValue);
|
||||
}
|
||||
|
||||
nsresult
|
||||
ChangeStyleTxn::SetStyle(bool aAttributeWasSet, nsAString& aValue)
|
||||
{
|
||||
nsresult result = NS_OK;
|
||||
if (aAttributeWasSet) {
|
||||
// The style attribute was not empty, let's recreate the declaration
|
||||
nsAutoString propertyNameString;
|
||||
mProperty->ToString(propertyNameString);
|
||||
|
||||
nsCOMPtr<nsIDOMElementCSSInlineStyle> inlineStyles =
|
||||
do_QueryInterface(mElement);
|
||||
NS_ENSURE_TRUE(inlineStyles, NS_ERROR_NULL_POINTER);
|
||||
nsCOMPtr<nsIDOMCSSStyleDeclaration> cssDecl;
|
||||
result = inlineStyles->GetStyle(getter_AddRefs(cssDecl));
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
NS_ENSURE_TRUE(cssDecl, NS_ERROR_NULL_POINTER);
|
||||
|
||||
if (aValue.IsEmpty()) {
|
||||
// An empty value means we have to remove the property
|
||||
nsAutoString returnString;
|
||||
result = cssDecl->RemoveProperty(propertyNameString, returnString);
|
||||
} else {
|
||||
// Let's recreate the declaration as it was
|
||||
nsAutoString priority;
|
||||
result = cssDecl->GetPropertyPriority(propertyNameString, priority);
|
||||
NS_ENSURE_SUCCESS(result, result);
|
||||
result = cssDecl->SetProperty(propertyNameString, aValue, priority);
|
||||
}
|
||||
} else {
|
||||
result = mElement->UnsetAttr(kNameSpaceID_None, nsGkAtoms::style, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChangeStyleTxn::UndoTransaction()
|
||||
{
|
||||
return SetStyle(mUndoAttributeWasSet, mUndoValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChangeStyleTxn::RedoTransaction()
|
||||
{
|
||||
return SetStyle(mRedoAttributeWasSet, mRedoValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
ChangeStyleTxn::GetTxnDescription(nsAString& aString)
|
||||
{
|
||||
aString.AssignLiteral("ChangeStyleTxn: [mRemoveProperty == ");
|
||||
|
||||
if (mRemoveProperty) {
|
||||
aString.AppendLiteral("true] ");
|
||||
} else {
|
||||
aString.AppendLiteral("false] ");
|
||||
}
|
||||
aString += nsDependentAtomString(mProperty);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// True if the CSS property accepts more than one value
|
||||
bool
|
||||
ChangeStyleTxn::AcceptsMoreThanOneValue(nsIAtom& aCSSProperty)
|
||||
{
|
||||
return &aCSSProperty == nsGkAtoms::text_decoration;
|
||||
}
|
||||
|
||||
// Adds the value aNewValue to the list of white-space separated values aValues
|
||||
void
|
||||
ChangeStyleTxn::AddValueToMultivalueProperty(nsAString& aValues,
|
||||
const nsAString& aNewValue)
|
||||
{
|
||||
if (aValues.IsEmpty() || aValues.LowerCaseEqualsLiteral("none")) {
|
||||
aValues.Assign(aNewValue);
|
||||
} else if (!ValueIncludes(aValues, aNewValue)) {
|
||||
// We already have another value but not this one; add it
|
||||
aValues.Append(char16_t(' '));
|
||||
aValues.Append(aNewValue);
|
||||
}
|
||||
}
|
112
editor/libeditor/ChangeStyleTxn.h
Normal file
112
editor/libeditor/ChangeStyleTxn.h
Normal file
@ -0,0 +1,112 @@
|
||||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef ChangeStyleTxn_h__
|
||||
#define ChangeStyleTxn_h__
|
||||
|
||||
#include "EditTxn.h" // base class
|
||||
#include "nsCOMPtr.h" // nsCOMPtr members
|
||||
#include "nsCycleCollectionParticipant.h" // various macros
|
||||
#include "nsString.h" // nsString members
|
||||
|
||||
class nsAString;
|
||||
class nsIAtom;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
class Element;
|
||||
|
||||
/**
|
||||
* A transaction that changes the value of a CSS inline style of a content
|
||||
* node. This transaction covers add, remove, and change a property's value.
|
||||
*/
|
||||
class ChangeStyleTxn : public EditTxn
|
||||
{
|
||||
public:
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ChangeStyleTxn, EditTxn)
|
||||
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
||||
NS_DECL_EDITTXN
|
||||
|
||||
NS_IMETHOD RedoTransaction() MOZ_OVERRIDE;
|
||||
|
||||
enum EChangeType { eSet, eRemove };
|
||||
|
||||
/** @param aNode [IN] the node whose style attribute will be changed
|
||||
* @param aProperty [IN] the name of the property to change
|
||||
* @param aValue [IN] new value for aProperty, or value to remove
|
||||
* @param aChangeType [IN] whether to set or remove
|
||||
*/
|
||||
ChangeStyleTxn(Element& aElement, nsIAtom& aProperty,
|
||||
const nsAString& aValue, EChangeType aChangeType);
|
||||
|
||||
/** Returns true if the list of white-space separated values contains aValue
|
||||
*
|
||||
* @return true if the value is in the list of values
|
||||
* @param aValueList [IN] a list of white-space separated values
|
||||
* @param aValue [IN] the value to look for in the list
|
||||
*/
|
||||
static bool ValueIncludes(const nsAString& aValueList,
|
||||
const nsAString& aValue);
|
||||
|
||||
private:
|
||||
~ChangeStyleTxn();
|
||||
|
||||
/** Adds the value aNewValue to list of white-space separated values aValues
|
||||
*
|
||||
* @param aValues [IN/OUT] a list of wite-space separated values
|
||||
* @param aNewValue [IN] a value this code adds to aValues if it is not already in
|
||||
*/
|
||||
void AddValueToMultivalueProperty(nsAString& aValues,
|
||||
const nsAString& aNewValue);
|
||||
|
||||
/** Returns true if the property accepts more than one value
|
||||
*
|
||||
* @return true if the property accepts more than one value
|
||||
* @param aCSSProperty [IN] the CSS property
|
||||
*/
|
||||
bool AcceptsMoreThanOneValue(nsIAtom& aCSSProperty);
|
||||
|
||||
/** Remove a value from a list of white-space separated values
|
||||
* @param aValues [IN] a list of white-space separated values
|
||||
* @param aRemoveValue [IN] the value to remove from the list
|
||||
*/
|
||||
void RemoveValueFromListOfValues(nsAString& aValues,
|
||||
const nsAString& aRemoveValue);
|
||||
|
||||
/** If the boolean is true and if the value is not the empty string,
|
||||
* set the property in the transaction to that value; if the value
|
||||
* is empty, remove the property from element's styles. If the boolean
|
||||
* is false, just remove the style attribute.
|
||||
*/
|
||||
nsresult SetStyle(bool aAttributeWasSet, nsAString& aValue);
|
||||
|
||||
/** The element to operate upon */
|
||||
nsCOMPtr<Element> mElement;
|
||||
|
||||
/** The CSS property to change */
|
||||
nsCOMPtr<nsIAtom> mProperty;
|
||||
|
||||
/** The value to set the property to (ignored if mRemoveProperty==true) */
|
||||
nsString mValue;
|
||||
|
||||
/** true if the operation is to remove mProperty from mElement */
|
||||
bool mRemoveProperty;
|
||||
|
||||
/** The value to set the property to for undo */
|
||||
nsString mUndoValue;
|
||||
/** The value to set the property to for redo */
|
||||
nsString mRedoValue;
|
||||
/** True if the style attribute was present and not empty before DoTransaction */
|
||||
bool mUndoAttributeWasSet;
|
||||
/** True if the style attribute is present and not empty after DoTransaction */
|
||||
bool mRedoAttributeWasSet;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -8,7 +8,7 @@ TEST_DIRS += ['tests']
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'ChangeAttributeTxn.cpp',
|
||||
'ChangeCSSInlineStyleTxn.cpp',
|
||||
'ChangeStyleTxn.cpp',
|
||||
'CreateElementTxn.cpp',
|
||||
'DeleteNodeTxn.cpp',
|
||||
'DeleteRangeTxn.cpp',
|
||||
|
@ -155,16 +155,15 @@ nsHTMLEditor::RelativeChangeElementZIndex(nsIDOMElement * aElement,
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetElementZIndex(nsIDOMElement * aElement,
|
||||
int32_t aZindex)
|
||||
nsHTMLEditor::SetElementZIndex(nsIDOMElement* aElement, int32_t aZindex)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aElement);
|
||||
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
NS_ENSURE_ARG_POINTER(element);
|
||||
|
||||
nsAutoString zIndexStr;
|
||||
zIndexStr.AppendInt(aZindex);
|
||||
|
||||
mHTMLCSSUtils->SetCSSProperty(aElement, nsGkAtoms::z_index, zIndexStr,
|
||||
false);
|
||||
mHTMLCSSUtils->SetCSSProperty(*element, *nsGkAtoms::z_index, zIndexStr);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
@ -467,10 +466,13 @@ nsHTMLEditor::SetFinalPosition(int32_t aX, int32_t aY)
|
||||
// we want one transaction only from a user's point of view
|
||||
nsAutoEditBatch batchIt(this);
|
||||
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
|
||||
nsGkAtoms::top, newY, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mAbsolutelyPositionedObject,
|
||||
nsGkAtoms::left, newX, false);
|
||||
nsCOMPtr<Element> absolutelyPositionedObject =
|
||||
do_QueryInterface(mAbsolutelyPositionedObject);
|
||||
NS_ENSURE_STATE(absolutelyPositionedObject);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
|
||||
*nsGkAtoms::top, newY);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*absolutelyPositionedObject,
|
||||
*nsGkAtoms::left, newX);
|
||||
// keep track of that size
|
||||
mPositionedObjectX = newX;
|
||||
mPositionedObjectY = newY;
|
||||
@ -490,10 +492,11 @@ nsHTMLEditor::AddPositioningOffset(int32_t & aX, int32_t & aY)
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
|
||||
nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement* aElement,
|
||||
bool aEnabled)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aElement);
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
NS_ENSURE_ARG_POINTER(element);
|
||||
|
||||
nsAutoString positionStr;
|
||||
mHTMLCSSUtils->GetComputedProperty(aElement, nsGkAtoms::position,
|
||||
@ -510,9 +513,8 @@ nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
|
||||
int32_t x, y;
|
||||
GetElementOrigin(aElement, x, y);
|
||||
|
||||
mHTMLCSSUtils->SetCSSProperty(aElement, nsGkAtoms::position,
|
||||
NS_LITERAL_STRING("absolute"),
|
||||
false);
|
||||
mHTMLCSSUtils->SetCSSProperty(*element, *nsGkAtoms::position,
|
||||
NS_LITERAL_STRING("absolute"));
|
||||
|
||||
AddPositioningOffset(x, y);
|
||||
SnapToGrid(x, y);
|
||||
@ -531,20 +533,20 @@ nsHTMLEditor::AbsolutelyPositionElement(nsIDOMElement * aElement,
|
||||
}
|
||||
}
|
||||
else {
|
||||
mHTMLCSSUtils->RemoveCSSProperty(aElement, nsGkAtoms::position,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(aElement, nsGkAtoms::top,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(aElement, nsGkAtoms::left,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(aElement, nsGkAtoms::z_index,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::position,
|
||||
EmptyString());
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::top,
|
||||
EmptyString());
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::left,
|
||||
EmptyString());
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::z_index,
|
||||
EmptyString());
|
||||
|
||||
if (!nsHTMLEditUtils::IsImage(aElement)) {
|
||||
mHTMLCSSUtils->RemoveCSSProperty(aElement, nsGkAtoms::width,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(aElement, nsGkAtoms::height,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::width,
|
||||
EmptyString());
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*element, *nsGkAtoms::height,
|
||||
EmptyString());
|
||||
}
|
||||
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aElement);
|
||||
@ -592,10 +594,12 @@ nsHTMLEditor::GetGridSize(uint32_t * aSize)
|
||||
NS_IMETHODIMP
|
||||
nsHTMLEditor::SetElementPosition(nsIDOMElement *aElement, int32_t aX, int32_t aY)
|
||||
{
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aElement);
|
||||
NS_ENSURE_STATE(element);
|
||||
nsAutoEditBatch batchIt(this);
|
||||
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(aElement, nsGkAtoms::left, aX, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(aElement, nsGkAtoms::top, aY, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*element, *nsGkAtoms::left, aX);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*element, *nsGkAtoms::top, aY);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ChangeCSSInlineStyleTxn.h"
|
||||
#include "ChangeStyleTxn.h"
|
||||
#include "EditTxn.h"
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
@ -44,6 +44,7 @@
|
||||
#include "nsUnicharUtils.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
static
|
||||
void ProcessBValue(const nsAString * aInputString, nsAString & aOutputString,
|
||||
@ -441,72 +442,53 @@ nsHTMLCSSUtils::IsCSSEditableProperty(nsIContent* aNode,
|
||||
return false;
|
||||
}
|
||||
|
||||
// the lowest level above the transaction; adds the css declaration "aProperty : aValue" to
|
||||
// the inline styles carried by aElement
|
||||
// The lowest level above the transaction; adds the CSS declaration
|
||||
// "aProperty : aValue" to the inline styles carried by aElement
|
||||
nsresult
|
||||
nsHTMLCSSUtils::SetCSSProperty(nsIDOMElement *aElement, nsIAtom * aProperty, const nsAString & aValue,
|
||||
bool aSuppressTransaction)
|
||||
nsHTMLCSSUtils::SetCSSProperty(Element& aElement, nsIAtom& aProperty,
|
||||
const nsAString& aValue, bool aSuppressTxn)
|
||||
{
|
||||
nsRefPtr<ChangeCSSInlineStyleTxn> txn;
|
||||
nsresult result = CreateCSSPropertyTxn(aElement, aProperty, aValue,
|
||||
getter_AddRefs(txn), false);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (aSuppressTransaction) {
|
||||
result = txn->DoTransaction();
|
||||
}
|
||||
else {
|
||||
result = mHTMLEditor->DoTransaction(txn);
|
||||
}
|
||||
nsRefPtr<ChangeStyleTxn> txn =
|
||||
CreateCSSPropertyTxn(aElement, aProperty, aValue, ChangeStyleTxn::eSet);
|
||||
if (aSuppressTxn) {
|
||||
return txn->DoTransaction();
|
||||
}
|
||||
return result;
|
||||
return mHTMLEditor->DoTransaction(txn);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLCSSUtils::SetCSSPropertyPixels(nsIDOMElement *aElement,
|
||||
nsIAtom *aProperty,
|
||||
int32_t aIntValue,
|
||||
bool aSuppressTransaction)
|
||||
nsHTMLCSSUtils::SetCSSPropertyPixels(Element& aElement, nsIAtom& aProperty,
|
||||
int32_t aIntValue)
|
||||
{
|
||||
nsAutoString s;
|
||||
s.AppendInt(aIntValue);
|
||||
return SetCSSProperty(aElement, aProperty, s + NS_LITERAL_STRING("px"),
|
||||
aSuppressTransaction);
|
||||
/* suppress txn */ false);
|
||||
}
|
||||
|
||||
// the lowest level above the transaction; removes the value aValue from the list of values
|
||||
// specified for the CSS property aProperty, or totally remove the declaration if this
|
||||
// property accepts only one value
|
||||
// The lowest level above the transaction; removes the value aValue from the
|
||||
// list of values specified for the CSS property aProperty, or totally remove
|
||||
// the declaration if this property accepts only one value
|
||||
nsresult
|
||||
nsHTMLCSSUtils::RemoveCSSProperty(nsIDOMElement *aElement, nsIAtom * aProperty, const nsAString & aValue,
|
||||
bool aSuppressTransaction)
|
||||
nsHTMLCSSUtils::RemoveCSSProperty(Element& aElement, nsIAtom& aProperty,
|
||||
const nsAString& aValue, bool aSuppressTxn)
|
||||
{
|
||||
nsRefPtr<ChangeCSSInlineStyleTxn> txn;
|
||||
nsresult result = CreateCSSPropertyTxn(aElement, aProperty, aValue,
|
||||
getter_AddRefs(txn), true);
|
||||
if (NS_SUCCEEDED(result)) {
|
||||
if (aSuppressTransaction) {
|
||||
result = txn->DoTransaction();
|
||||
}
|
||||
else {
|
||||
result = mHTMLEditor->DoTransaction(txn);
|
||||
}
|
||||
nsRefPtr<ChangeStyleTxn> txn =
|
||||
CreateCSSPropertyTxn(aElement, aProperty, aValue, ChangeStyleTxn::eRemove);
|
||||
if (aSuppressTxn) {
|
||||
return txn->DoTransaction();
|
||||
}
|
||||
return result;
|
||||
return mHTMLEditor->DoTransaction(txn);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsHTMLCSSUtils::CreateCSSPropertyTxn(nsIDOMElement *aElement,
|
||||
nsIAtom * aAttribute,
|
||||
already_AddRefed<ChangeStyleTxn>
|
||||
nsHTMLCSSUtils::CreateCSSPropertyTxn(Element& aElement, nsIAtom& aAttribute,
|
||||
const nsAString& aValue,
|
||||
ChangeCSSInlineStyleTxn ** aTxn,
|
||||
bool aRemoveProperty)
|
||||
ChangeStyleTxn::EChangeType aChangeType)
|
||||
{
|
||||
NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
|
||||
|
||||
*aTxn = new ChangeCSSInlineStyleTxn();
|
||||
NS_ENSURE_TRUE(*aTxn, NS_ERROR_OUT_OF_MEMORY);
|
||||
NS_ADDREF(*aTxn);
|
||||
return (*aTxn)->Init(mHTMLEditor, aElement, aAttribute, aValue, aRemoveProperty);
|
||||
nsRefPtr<ChangeStyleTxn> txn =
|
||||
new ChangeStyleTxn(aElement, aAttribute, aValue, aChangeType);
|
||||
return txn.forget();
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -598,14 +580,14 @@ nsHTMLCSSUtils::GetComputedStyle(dom::Element* aElement)
|
||||
nsresult
|
||||
nsHTMLCSSUtils::RemoveCSSInlineStyle(nsIDOMNode *aNode, nsIAtom *aProperty, const nsAString & aPropertyValue)
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> elem = do_QueryInterface(aNode);
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aNode);
|
||||
NS_ENSURE_STATE(element);
|
||||
|
||||
// remove the property from the style attribute
|
||||
nsresult res = RemoveCSSProperty(elem, aProperty, aPropertyValue, false);
|
||||
nsresult res = RemoveCSSProperty(*element, *aProperty, aPropertyValue);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
nsCOMPtr<dom::Element> element = do_QueryInterface(aNode);
|
||||
if (!element || !element->IsHTML(nsGkAtoms::span) ||
|
||||
if (!element->IsHTML(nsGkAtoms::span) ||
|
||||
nsHTMLEditor::HasAttributes(element)) {
|
||||
return NS_OK;
|
||||
}
|
||||
@ -939,11 +921,10 @@ nsHTMLCSSUtils::SetCSSEquivalentToHTMLStyle(nsIDOMNode * aNode,
|
||||
aValue, cssPropertyArray, cssValueArray,
|
||||
false);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(element);
|
||||
// set the individual CSS inline styles
|
||||
*aCount = cssPropertyArray.Length();
|
||||
for (int32_t index = 0; index < *aCount; index++) {
|
||||
nsresult res = SetCSSProperty(domElement, cssPropertyArray[index],
|
||||
nsresult res = SetCSSProperty(*element, *cssPropertyArray[index],
|
||||
cssValueArray[index], aSuppressTransaction);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
}
|
||||
@ -988,12 +969,11 @@ nsHTMLCSSUtils::RemoveCSSEquivalentToHTMLStyle(dom::Element* aElement,
|
||||
aValue, cssPropertyArray, cssValueArray,
|
||||
true);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> domElement = do_QueryInterface(aElement);
|
||||
// remove the individual CSS inline styles
|
||||
int32_t count = cssPropertyArray.Length();
|
||||
for (int32_t index = 0; index < count; index++) {
|
||||
nsresult res = RemoveCSSProperty(domElement,
|
||||
cssPropertyArray[index],
|
||||
nsresult res = RemoveCSSProperty(*aElement,
|
||||
*cssPropertyArray[index],
|
||||
cssValueArray[index],
|
||||
aSuppressTransaction);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
@ -1122,11 +1102,11 @@ nsHTMLCSSUtils::IsCSSEquivalentToHTMLInlineStyleSet(nsIDOMNode *aNode,
|
||||
} else if (nsGkAtoms::u == aHTMLProperty) {
|
||||
nsAutoString val;
|
||||
val.AssignLiteral("underline");
|
||||
aIsSet = bool(ChangeCSSInlineStyleTxn::ValueIncludes(valueString, val, false));
|
||||
aIsSet = ChangeStyleTxn::ValueIncludes(valueString, val);
|
||||
} else if (nsGkAtoms::strike == aHTMLProperty) {
|
||||
nsAutoString val;
|
||||
val.AssignLiteral("line-through");
|
||||
aIsSet = bool(ChangeCSSInlineStyleTxn::ValueIncludes(valueString, val, false));
|
||||
aIsSet = ChangeStyleTxn::ValueIncludes(valueString, val);
|
||||
} else if (aHTMLAttribute &&
|
||||
((nsGkAtoms::font == aHTMLProperty &&
|
||||
aHTMLAttribute->EqualsLiteral("color")) ||
|
||||
|
@ -6,11 +6,11 @@
|
||||
#ifndef nsHTMLCSSUtils_h__
|
||||
#define nsHTMLCSSUtils_h__
|
||||
|
||||
#include "ChangeStyleTxn.h" // for ChangeStyleTxn::EChangeType
|
||||
#include "nsCOMPtr.h" // for already_AddRefed
|
||||
#include "nsTArray.h" // for nsTArray
|
||||
#include "nscore.h" // for nsAString, nsresult, nullptr
|
||||
|
||||
class ChangeCSSInlineStyleTxn;
|
||||
class nsComputedDOMStyle;
|
||||
class nsIAtom;
|
||||
class nsIContent;
|
||||
@ -94,13 +94,14 @@ public:
|
||||
* @param aSuppressTransaction [IN] a boolean indicating, when true,
|
||||
* that no transaction should be recorded
|
||||
*/
|
||||
nsresult SetCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
|
||||
const nsAString & aValue,
|
||||
bool aSuppressTransaction);
|
||||
nsresult SetCSSPropertyPixels(nsIDOMElement *aElement, nsIAtom *aProperty,
|
||||
int32_t aIntValue, bool aSuppressTxn);
|
||||
nsresult RemoveCSSProperty(nsIDOMElement * aElement, nsIAtom * aProperty,
|
||||
const nsAString & aPropertyValue, bool aSuppressTransaction);
|
||||
nsresult SetCSSProperty(mozilla::dom::Element& aElement, nsIAtom& aProperty,
|
||||
const nsAString& aValue, bool aSuppressTxn = false);
|
||||
nsresult SetCSSPropertyPixels(mozilla::dom::Element& aElement,
|
||||
nsIAtom& aProperty, int32_t aIntValue);
|
||||
nsresult RemoveCSSProperty(mozilla::dom::Element& aElement,
|
||||
nsIAtom& aProperty,
|
||||
const nsAString& aPropertyValue,
|
||||
bool aSuppressTxn = false);
|
||||
|
||||
/** directly adds/remove a CSS declaration to the STYLE atrribute carried by
|
||||
* a given element without going through the txn manager
|
||||
@ -374,19 +375,18 @@ private:
|
||||
nsTArray<nsString>& aValueArray,
|
||||
bool aGetOrRemoveRequest);
|
||||
|
||||
/** creates a Transaction for setting or removing a css property
|
||||
/** Creates a Transaction for setting or removing a CSS property. Never
|
||||
* returns null.
|
||||
*
|
||||
* @param aElement [IN] a DOM element
|
||||
* @param aProperty [IN] a CSS property
|
||||
* @param aValue [IN] the value to remove for this CSS property or the empty string if irrelevant
|
||||
* @param aTxn [OUT] the created transaction
|
||||
* @param aRemoveProperty [IN] true if we create a "remove" transaction, false for a "set"
|
||||
* @param aValue [IN] the value to set for this CSS property
|
||||
* @param aChangeType [IN] eSet to set, eRemove to remove
|
||||
*/
|
||||
nsresult CreateCSSPropertyTxn(nsIDOMElement * aElement,
|
||||
nsIAtom * aProperty,
|
||||
const nsAString & aValue,
|
||||
ChangeCSSInlineStyleTxn ** aTxn,
|
||||
bool aRemoveProperty);
|
||||
already_AddRefed<mozilla::dom::ChangeStyleTxn>
|
||||
CreateCSSPropertyTxn(mozilla::dom::Element& aElement,
|
||||
nsIAtom& aProperty, const nsAString& aValue,
|
||||
mozilla::dom::ChangeStyleTxn::EChangeType aChangeType);
|
||||
|
||||
/** back-end for GetSpecifiedProperty and GetComputedProperty
|
||||
*
|
||||
|
@ -9074,13 +9074,15 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element = do_QueryInterface(aNode);
|
||||
nsCOMPtr<Element> element = do_QueryInterface(aNode);
|
||||
if (!element) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
nsIAtom* marginProperty = MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils, element);
|
||||
nsIAtom* marginProperty =
|
||||
MarginPropertyAtomForIndent(mHTMLEditor->mHTMLCSSUtils,
|
||||
GetAsDOMNode(element));
|
||||
nsAutoString value;
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
mHTMLEditor->mHTMLCSSUtils->GetSpecifiedProperty(aNode, marginProperty, value);
|
||||
@ -9119,12 +9121,14 @@ nsHTMLEditRules::RelativeChangeIndentationOfElementNode(nsIDOMNode *aNode, int8_
|
||||
newValue.AppendFloat(f);
|
||||
newValue.Append(nsDependentAtomString(unit));
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(element, marginProperty, newValue, false);
|
||||
mHTMLEditor->mHTMLCSSUtils->SetCSSProperty(*element, *marginProperty,
|
||||
newValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(mHTMLEditor);
|
||||
mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(element, marginProperty, value, false);
|
||||
mHTMLEditor->mHTMLCSSUtils->RemoveCSSProperty(*element, *marginProperty,
|
||||
value);
|
||||
|
||||
// remove unnecessary DIV blocks:
|
||||
// we could skip this section but that would cause a FAIL in
|
||||
|
@ -48,6 +48,7 @@
|
||||
class nsISelection;
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
||||
class nsHTMLEditUtils;
|
||||
|
||||
@ -932,13 +933,13 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
|
||||
NS_NAMED_LITERAL_STRING(heightStr, "height");
|
||||
|
||||
bool hasAttr = false;
|
||||
nsCOMPtr<Element> resizedObject = do_QueryInterface(mResizedObject);
|
||||
NS_ENSURE_TRUE(resizedObject, );
|
||||
if (mResizedObjectIsAbsolutelyPositioned) {
|
||||
if (setHeight)
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject, nsGkAtoms::top, y,
|
||||
false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::top, y);
|
||||
if (setWidth)
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject, nsGkAtoms::left, x,
|
||||
false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::left, x);
|
||||
}
|
||||
if (IsCSSEnabled() || mResizedObjectIsAbsolutelyPositioned) {
|
||||
if (setWidth && NS_SUCCEEDED(mResizedObject->HasAttribute(widthStr, &hasAttr)) && hasAttr)
|
||||
@ -949,11 +950,11 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
|
||||
RemoveAttribute(mResizedObject, heightStr);
|
||||
|
||||
if (setWidth)
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject, nsGkAtoms::width,
|
||||
width, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
|
||||
width);
|
||||
if (setHeight)
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject, nsGkAtoms::height,
|
||||
height, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
|
||||
height);
|
||||
}
|
||||
else {
|
||||
// we use HTML size and remove all equivalent CSS properties
|
||||
@ -962,11 +963,11 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
|
||||
// triggering an immediate reflow; otherwise, we have problems
|
||||
// with asynchronous reflow
|
||||
if (setWidth)
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject, nsGkAtoms::width,
|
||||
width, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::width,
|
||||
width);
|
||||
if (setHeight)
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(mResizedObject, nsGkAtoms::height,
|
||||
height, false);
|
||||
mHTMLCSSUtils->SetCSSPropertyPixels(*resizedObject, *nsGkAtoms::height,
|
||||
height);
|
||||
|
||||
if (setWidth) {
|
||||
nsAutoString w;
|
||||
@ -980,11 +981,11 @@ nsHTMLEditor::SetFinalSize(int32_t aX, int32_t aY)
|
||||
}
|
||||
|
||||
if (setWidth)
|
||||
mHTMLCSSUtils->RemoveCSSProperty(mResizedObject, nsGkAtoms::width,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::width,
|
||||
EmptyString());
|
||||
if (setHeight)
|
||||
mHTMLCSSUtils->RemoveCSSProperty(mResizedObject, nsGkAtoms::height,
|
||||
EmptyString(), false);
|
||||
mHTMLCSSUtils->RemoveCSSProperty(*resizedObject, *nsGkAtoms::height,
|
||||
EmptyString());
|
||||
}
|
||||
// finally notify the listeners if any
|
||||
int32_t listenersCount = objectResizeEventListeners.Count();
|
||||
|
Loading…
Reference in New Issue
Block a user