CSSEditUtils.h (17086B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5 6 #ifndef CSSEditUtils_h 7 #define CSSEditUtils_h 8 9 #include "ChangeStyleTransaction.h" // for ChangeStyleTransaction 10 #include "EditorForwards.h" 11 #include "nsCOMPtr.h" // for already_AddRefed 12 #include "nsStringFwd.h" 13 #include "nsTArray.h" // for nsTArray 14 #include "nscore.h" // for nsAString, nsresult, nullptr 15 16 class nsComputedDOMStyle; 17 class nsAtom; 18 class nsIContent; 19 class nsINode; 20 class nsStaticAtom; 21 class nsStyledElement; 22 23 namespace mozilla { 24 namespace dom { 25 class Element; 26 } // namespace dom 27 28 using nsProcessValueFunc = void (*)(const nsAString* aInputString, 29 nsAString& aOutputString, 30 const char* aDefaultValueString, 31 const char* aPrependString, 32 const char* aAppendString); 33 34 class CSSEditUtils final { 35 public: 36 // To prevent the class being instantiated 37 CSSEditUtils() = delete; 38 39 enum nsCSSEditableProperty { 40 eCSSEditableProperty_NONE = 0, 41 eCSSEditableProperty_background_color, 42 eCSSEditableProperty_background_image, 43 eCSSEditableProperty_border, 44 eCSSEditableProperty_caption_side, 45 eCSSEditableProperty_color, 46 eCSSEditableProperty_float, 47 eCSSEditableProperty_font_family, 48 eCSSEditableProperty_font_size, 49 eCSSEditableProperty_font_style, 50 eCSSEditableProperty_font_weight, 51 eCSSEditableProperty_height, 52 eCSSEditableProperty_list_style_type, 53 eCSSEditableProperty_margin_left, 54 eCSSEditableProperty_margin_right, 55 eCSSEditableProperty_text_align, 56 eCSSEditableProperty_text_decoration, 57 eCSSEditableProperty_vertical_align, 58 eCSSEditableProperty_whitespace, 59 eCSSEditableProperty_width 60 }; 61 62 // Nb: keep these fields in an order that minimizes padding. 63 struct CSSEquivTable { 64 nsCSSEditableProperty cssProperty; 65 bool gettable; 66 bool caseSensitiveValue; 67 nsProcessValueFunc processValueFunctor; 68 const char* defaultValue; 69 const char* prependValue; 70 const char* appendValue; 71 }; 72 73 /** 74 * Adds/remove a CSS declaration to the STYLE attribute carried by a given 75 * element. 76 * 77 * @param aHTMLEditor [IN] An HTMLEditor instance 78 * @param aStyledElement [IN] A DOM styled element. 79 * @param aProperty [IN] An atom containing the CSS property to set. 80 * @param aValue [IN] A string containing the value of the CSS 81 * property. 82 */ 83 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult 84 SetCSSPropertyWithTransaction(HTMLEditor& aHTMLEditor, 85 nsStyledElement& aStyledElement, 86 nsAtom& aProperty, const nsAString& aValue) { 87 return SetCSSPropertyInternal(aHTMLEditor, aStyledElement, aProperty, 88 aValue, false); 89 } 90 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult 91 SetCSSPropertyPixelsWithTransaction(HTMLEditor& aHTMLEditor, 92 nsStyledElement& aStyledElement, 93 nsAtom& aProperty, int32_t aIntValue); 94 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult 95 SetCSSPropertyPixelsWithoutTransaction(HTMLEditor& aHTMLEditor, 96 nsStyledElement& aStyledElement, 97 const nsAtom& aProperty, 98 int32_t aIntValue); 99 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult 100 RemoveCSSPropertyWithTransaction(HTMLEditor& aHTMLEditor, 101 nsStyledElement& aStyledElement, 102 nsAtom& aProperty, 103 const nsAString& aPropertyValue) { 104 return RemoveCSSPropertyInternal(aHTMLEditor, aStyledElement, aProperty, 105 aPropertyValue, false); 106 } 107 108 /** 109 * Gets the specified/computed style value of a CSS property for a given 110 * node (or its element ancestor if it is not an element). 111 * 112 * @param aContent [IN] A DOM node. 113 * @param aProperty [IN] An atom containing the CSS property to get. 114 * @param aPropertyValue [OUT] The retrieved value of the property. 115 */ 116 static nsresult GetSpecifiedProperty(nsIContent& aContent, 117 nsAtom& aCSSProperty, nsAString& aValue); 118 MOZ_CAN_RUN_SCRIPT static nsresult GetComputedProperty(nsIContent& aContent, 119 nsAtom& aCSSProperty, 120 nsAString& aValue); 121 122 /** 123 * Removes a CSS property from the specified declarations in STYLE attribute 124 * and removes the node if it is an useless span. 125 * 126 * @param aHTMLEditor [IN] An HTMLEditor instance 127 * @param aStyledElement [IN] The styled element we want to remove a style 128 * from. 129 * @param aProperty [IN] The CSS property atom to remove. 130 * @param aPropertyValue [IN] The value of the property we have to remove 131 * if the property accepts more than one value. 132 * @return A candidate point to put caret. 133 */ 134 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<EditorDOMPoint, nsresult> 135 RemoveCSSInlineStyleWithTransaction(HTMLEditor& aHTMLEditor, 136 nsStyledElement& aStyledElement, 137 nsAtom* aProperty, 138 const nsAString& aPropertyValue); 139 140 /** 141 * Get the default browser background color if we need it for 142 * GetCSSBackgroundColorState(). 143 * 144 * @param aColor [OUT] The default color as it is defined in prefs. 145 */ 146 static void GetDefaultBackgroundColor(nsAString& aColor); 147 148 /** 149 * Returns the list of values for the CSS equivalences to 150 * the passed HTML style for the passed node. 151 * 152 * @param aElement [IN] A DOM node. 153 * @param aStyle [IN] The style to get the values. 154 * @param aValueString [OUT] The list of CSS values. 155 */ 156 MOZ_CAN_RUN_SCRIPT static nsresult GetComputedCSSEquivalentTo( 157 dom::Element& aElement, const EditorElementStyle& aStyle, 158 nsAString& aOutValue); 159 160 /** 161 * Does the node aNode (or his parent if it is not an element node) carries 162 * the CSS equivalent styles to the HTML style for this node ? 163 * 164 * @param aHTMLEditor [IN] An HTMLEditor instance 165 * @param aContent [IN] A DOM node. 166 * @param aStyle [IN] The style to check. 167 * @param aInOutValue [IN/OUT] Input value is used for initial value of the 168 * result, out value is the list of CSS values. 169 * @return A boolean being true if the css properties are 170 * not same as initial value. 171 */ 172 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<bool, nsresult> 173 IsComputedCSSEquivalentTo(const HTMLEditor& aHTMLEditor, nsIContent& aContent, 174 const EditorInlineStyle& aStyle, 175 nsAString& aInOutValue); 176 [[nodiscard]] MOZ_CAN_RUN_SCRIPT_BOUNDARY static Result<bool, nsresult> 177 IsSpecifiedCSSEquivalentTo(const HTMLEditor& aHTMLEditor, 178 nsIContent& aContent, 179 const EditorInlineStyle& aStyle, 180 nsAString& aInOutValue); 181 182 /** 183 * This is a kind of Is*CSSEquivalentTo. 184 * Is*CSSEquivalentTo returns whether the properties aren't same as initial 185 * value. But this method returns whether the properties aren't set. 186 * If node is <span style="font-weight: normal"/>, 187 * - Is(Computed|Specified)CSSEquivalentTo returns false. 188 * - Have(Computed|Specified)CSSEquivalentStyles returns true. 189 * 190 * @param aHTMLEditor [IN] An HTMLEditor instance 191 * @param aContent [IN] A DOM node. 192 * @param aStyle [IN] The style to check. 193 * @return A boolean being true if the css properties are 194 * not set. 195 */ 196 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<bool, nsresult> 197 HaveComputedCSSEquivalentStyles(const HTMLEditor& aHTMLEditor, 198 nsIContent& aContent, 199 const EditorInlineStyle& aStyle); 200 [[nodiscard]] MOZ_CAN_RUN_SCRIPT_BOUNDARY static Result<bool, nsresult> 201 HaveSpecifiedCSSEquivalentStyles(const HTMLEditor& aHTMLEditor, 202 nsIContent& aContent, 203 const EditorInlineStyle& aStyle); 204 205 /** 206 * Adds to the node the CSS inline styles equivalent to the HTML style 207 * and return the number of CSS properties set by the call. 208 * 209 * @param aHTMLEditor [IN} An HTMLEditor instance 210 * @param aNode [IN] A DOM node. 211 * @param aStyleToSet [IN] The style to set. Can be EditorInlineStyle. 212 * @param aValue [IN] The attribute or style value of aStyleToSet. 213 * 214 * @return The number of CSS properties set by the call. 215 */ 216 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<size_t, nsresult> 217 SetCSSEquivalentToStyle(WithTransaction aWithTransaction, 218 HTMLEditor& aHTMLEditor, 219 nsStyledElement& aStyledElement, 220 const EditorElementStyle& aStyleToSet, 221 const nsAString* aValue); 222 223 /** 224 * Removes from the node the CSS inline styles equivalent to the HTML style. 225 * 226 * @param aHTMLEditor [IN} An HTMLEditor instance 227 * @param aStyledElement [IN] A DOM Element (must not be null). 228 * @param aStyleToRemove [IN] The style to remove. Can be EditorInlineStyle. 229 * @param aAttribute [IN] An atom to an attribute name or nullptr if 230 * irrelevant. 231 * @param aValue [IN] The attribute value. 232 */ 233 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult RemoveCSSEquivalentToStyle( 234 WithTransaction aWithTransaction, HTMLEditor& aHTMLEditor, 235 nsStyledElement& aStyledElement, const EditorElementStyle& aStyleToRemove, 236 const nsAString* aValue); 237 238 /** 239 * Parses a "xxxx.xxxxxuuu" string where x is a digit and u an alpha char. 240 * 241 * @param aString [IN] Input string to parse. 242 * @param aValue [OUT] Numeric part. 243 * @param aUnit [OUT] Unit part. 244 */ 245 static void ParseLength(const nsAString& aString, float* aValue, 246 nsAtom** aUnit); 247 248 /** 249 * DoStyledElementsHaveSameStyle compares two elements and checks if they have 250 * the same specified CSS declarations in the STYLE attribute. The answer is 251 * always false if at least one of them carries an ID or a class. 252 * 253 * @param aStyledElement [IN] A styled element. 254 * @param aOtherStyledElement [IN] The other styled element. 255 * @return true if the two elements are considered to 256 * have same styles. 257 */ 258 static bool DoStyledElementsHaveSameStyle( 259 nsStyledElement& aStyledElement, nsStyledElement& aOtherStyledElement); 260 261 /** 262 * Gets the computed style for a given element. Can return null. 263 */ 264 static already_AddRefed<nsComputedDOMStyle> GetComputedStyle( 265 dom::Element* aElement); 266 267 private: 268 enum class StyleType { Specified, Computed }; 269 270 /** 271 * Retrieves the CSS property atom from an enum. 272 * 273 * @param aProperty The enum value for the property. 274 * @return The corresponding atom. 275 */ 276 static nsStaticAtom* GetCSSPropertyAtom(nsCSSEditableProperty aProperty); 277 278 struct CSSDeclaration { 279 nsStaticAtom& mProperty; 280 nsString const mValue; 281 }; 282 283 /** 284 * Retrieves the CSS declarations for aEquivTable. 285 * 286 * @param aEquivTable The equivalence table. 287 * @param aValue Optional. If specified, may return only 288 * matching declarations to this value (depends on 289 * the style, check how is aInputString of 290 * nsProcessValueFunc for the details). 291 * @param aHandlingFor What's the purpose of calling this. 292 * @param aOutCSSDeclarations [OUT] The array of CSS declarations. 293 */ 294 enum class HandlingFor { GettingStyle, SettingStyle, RemovingStyle }; 295 static void GetCSSDeclarations(const CSSEquivTable* aEquivTable, 296 const nsAString* aValue, 297 HandlingFor aHandlingFor, 298 nsTArray<CSSDeclaration>& aOutCSSDeclarations); 299 300 /** 301 * Retrieves the CSS declarations equivalent to the given aStyle/aValue on 302 * aElement. 303 * 304 * @param aElement The DOM node. 305 * @param aStyle The style to get equivelent CSS properties and 306 * values. 307 * @param aValue Optional. If specified, may return only 308 * matching declarations to this value (depends on 309 * the style, check how is aInputString of 310 * nsProcessValueFunc for the details). 311 * @param aHandlingFor What's the purpose of calling this. 312 * @param aOutCSSDeclarations [OUT] The array of CSS declarations. 313 */ 314 static void GetCSSDeclarations(dom::Element& aElement, 315 const EditorElementStyle& aStyle, 316 const nsAString* aValue, 317 HandlingFor aHandlingFor, 318 nsTArray<CSSDeclaration>& aOutCSSDeclarations); 319 320 /** 321 * Back-end for GetSpecifiedProperty and GetComputedProperty. 322 * 323 * @param aNode [IN] A DOM node. 324 * @param aProperty [IN] A CSS property. 325 * @param aValue [OUT] The retrieved value for this property. 326 */ 327 MOZ_CAN_RUN_SCRIPT static nsresult GetComputedCSSInlinePropertyBase( 328 nsIContent& aContent, nsAtom& aCSSProperty, nsAString& aValue); 329 static nsresult GetSpecifiedCSSInlinePropertyBase(nsIContent& aContent, 330 nsAtom& aCSSProperty, 331 nsAString& aValue); 332 333 /** 334 * Those methods are wrapped with corresponding methods which do not have 335 * "Internal" in their names. Don't use these methods directly even if 336 * you want to use one of them in this class. 337 * Note that these methods may run scrip only when StyleType is Computed. 338 */ 339 MOZ_CAN_RUN_SCRIPT static nsresult GetCSSEquivalentTo( 340 dom::Element& aElement, const EditorElementStyle& aStyle, 341 nsAString& aOutValue, StyleType aStyleType); 342 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<bool, nsresult> 343 IsCSSEquivalentTo(const HTMLEditor& aHTMLEditor, nsIContent& aContent, 344 const EditorInlineStyle& aStyle, nsAString& aInOutValue, 345 StyleType aStyleType); 346 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static Result<bool, nsresult> 347 HaveCSSEquivalentStyles(const HTMLEditor& aHTMLEditor, nsIContent& aContent, 348 const EditorInlineStyle& aStyle, 349 StyleType aStyleType); 350 351 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult RemoveCSSPropertyInternal( 352 HTMLEditor& aHTMLEditor, nsStyledElement& aStyledElement, 353 nsAtom& aProperty, const nsAString& aPropertyValue, 354 bool aSuppressTxn = false); 355 [[nodiscard]] MOZ_CAN_RUN_SCRIPT static nsresult SetCSSPropertyInternal( 356 HTMLEditor& aHTMLEditor, nsStyledElement& aStyledElement, 357 nsAtom& aProperty, const nsAString& aValue, bool aSuppressTxn = false); 358 359 /** 360 * Answers true if the given aStyle on aElement or an element whose name is 361 * aTagName has a CSS equivalence in this implementation. 362 * 363 * @param aTagName [IN] Tag name of an element. 364 * @param aElement [IN] An element. 365 * @param aStyle [IN] The style you want to check. 366 * @return A boolean saying if the tag/attribute has a CSS 367 * equiv. 368 */ 369 [[nodiscard]] static bool IsCSSEditableStyle( 370 const nsAtom& aTagName, const EditorElementStyle& aStyle); 371 [[nodiscard]] static bool IsCSSEditableStyle( 372 const dom::Element& aElement, const EditorElementStyle& aStyle); 373 374 friend class EditorElementStyle; // for IsCSSEditableStyle 375 }; 376 377 #define NS_EDITOR_INDENT_INCREMENT_IN 0.4134f 378 #define NS_EDITOR_INDENT_INCREMENT_CM 1.05f 379 #define NS_EDITOR_INDENT_INCREMENT_MM 10.5f 380 #define NS_EDITOR_INDENT_INCREMENT_PT 29.76f 381 #define NS_EDITOR_INDENT_INCREMENT_PC 2.48f 382 #define NS_EDITOR_INDENT_INCREMENT_EM 3 383 #define NS_EDITOR_INDENT_INCREMENT_EX 6 384 #define NS_EDITOR_INDENT_INCREMENT_PX 40 385 #define NS_EDITOR_INDENT_INCREMENT_PERCENT 4 386 387 } // namespace mozilla 388 389 #endif // #ifndef CSSEditUtils_h