diff options
Diffstat (limited to 'editor/libeditor/HTMLEditorNestedClasses.h')
-rw-r--r-- | editor/libeditor/HTMLEditorNestedClasses.h | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/editor/libeditor/HTMLEditorNestedClasses.h b/editor/libeditor/HTMLEditorNestedClasses.h new file mode 100644 index 0000000000..8a859899c3 --- /dev/null +++ b/editor/libeditor/HTMLEditorNestedClasses.h @@ -0,0 +1,176 @@ +/* -*- 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 HTMLEditorNestedClasses_h +#define HTMLEditorNestedClasses_h + +#include "EditorDOMPoint.h" +#include "EditorForwards.h" +#include "HTMLEditor.h" // for HTMLEditor +#include "HTMLEditHelpers.h" // for EditorInlineStyleAndValue + +#include "mozilla/Attributes.h" +#include "mozilla/Result.h" + +namespace mozilla { + +/***************************************************************************** + * AutoInlineStyleSetter is a temporary class to set an inline style to + * specific nodes. + ****************************************************************************/ + +class MOZ_STACK_CLASS HTMLEditor::AutoInlineStyleSetter final + : private EditorInlineStyleAndValue { + using Element = dom::Element; + using Text = dom::Text; + + public: + explicit AutoInlineStyleSetter( + const EditorInlineStyleAndValue& aStyleAndValue) + : EditorInlineStyleAndValue(aStyleAndValue) {} + + void Reset() { + mFirstHandledPoint.Clear(); + mLastHandledPoint.Clear(); + } + + const EditorDOMPoint& FirstHandledPointRef() const { + return mFirstHandledPoint; + } + const EditorDOMPoint& LastHandledPointRef() const { + return mLastHandledPoint; + } + + /** + * Split aText at aStartOffset and aEndOffset (except when they are start or + * end of its data) and wrap the middle text node in an element to apply the + * style. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult> + SplitTextNodeAndApplyStyleToMiddleNode(HTMLEditor& aHTMLEditor, Text& aText, + uint32_t aStartOffset, + uint32_t aEndOffset); + + /** + * Remove same style from children and apply the style entire (except + * non-editable nodes) aContent. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult> + ApplyStyleToNodeOrChildrenAndRemoveNestedSameStyle(HTMLEditor& aHTMLEditor, + nsIContent& aContent); + + /** + * Invert the style with creating new element or something. This should + * be called only when IsInvertibleWithCSS() returns true. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT nsresult + InvertStyleIfApplied(HTMLEditor& aHTMLEditor, Element& aElement); + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<SplitRangeOffFromNodeResult, nsresult> + InvertStyleIfApplied(HTMLEditor& aHTMLEditor, Text& aTextNode, + uint32_t aStartOffset, uint32_t aEndOffset); + + /** + * Extend or shrink aRange for applying the style to the range. + * See comments in the definition what this does. + */ + Result<EditorRawDOMRange, nsresult> ExtendOrShrinkRangeToApplyTheStyle( + const HTMLEditor& aHTMLEditor, const EditorDOMRange& aRange) const; + + /** + * Returns next/previous sibling of aContent or an ancestor of it if it's + * editable and does not cross block boundary. + */ + [[nodiscard]] static nsIContent* GetNextEditableInlineContent( + const nsIContent& aContent, const nsINode* aLimiter = nullptr); + [[nodiscard]] static nsIContent* GetPreviousEditableInlineContent( + const nsIContent& aContent, const nsINode* aLimiter = nullptr); + + private: + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult> ApplyStyle( + HTMLEditor& aHTMLEditor, nsIContent& aContent); + + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<CaretPoint, nsresult> + ApplyCSSTextDecoration(HTMLEditor& aHTMLEditor, nsIContent& aContent); + + /** + * Returns true if aStyledElement is a good element to set `style` attribute. + */ + [[nodiscard]] bool ElementIsGoodContainerToSetStyle( + nsStyledElement& aStyledElement) const; + + /** + * ElementIsGoodContainerForTheStyle() returns true if aElement is a + * good container for applying the style to a node. I.e., if this returns + * true, moving nodes into aElement is enough to apply the style to them. + * Otherwise, you need to create new element for the style. + */ + [[nodiscard]] MOZ_CAN_RUN_SCRIPT Result<bool, nsresult> + ElementIsGoodContainerForTheStyle(HTMLEditor& aHTMLEditor, + Element& aElement) const; + + /** + * Return true if the node is an element node and it represents the style or + * sets the style (including when setting different value) with `style` + * attribute. + */ + [[nodiscard]] bool ContentIsElementSettingTheStyle( + const HTMLEditor& aHTMLEditor, nsIContent& aContent) const; + + /** + * Helper methods to shrink range to apply the style. + */ + [[nodiscard]] EditorRawDOMPoint GetShrunkenRangeStart( + const HTMLEditor& aHTMLEditor, const EditorDOMRange& aRange, + const nsINode& aCommonAncestorOfRange, + const nsIContent* aFirstEntirelySelectedContentNodeInRange) const; + [[nodiscard]] EditorRawDOMPoint GetShrunkenRangeEnd( + const HTMLEditor& aHTMLEditor, const EditorDOMRange& aRange, + const nsINode& aCommonAncestorOfRange, + const nsIContent* aLastEntirelySelectedContentNodeInRange) const; + + /** + * Helper methods to extend the range to apply the style. + */ + [[nodiscard]] EditorRawDOMPoint + GetExtendedRangeStartToWrapAncestorApplyingSameStyle( + const HTMLEditor& aHTMLEditor, + const EditorRawDOMPoint& aStartPoint) const; + [[nodiscard]] EditorRawDOMPoint + GetExtendedRangeEndToWrapAncestorApplyingSameStyle( + const HTMLEditor& aHTMLEditor, const EditorRawDOMPoint& aEndPoint) const; + [[nodiscard]] EditorRawDOMRange + GetExtendedRangeToMinimizeTheNumberOfNewElements( + const HTMLEditor& aHTMLEditor, const nsINode& aCommonAncestor, + EditorRawDOMPoint&& aStartPoint, EditorRawDOMPoint&& aEndPoint) const; + + /** + * OnHandled() are called when this class creates new element to apply the + * style, applies new style to existing element or ignores to apply the style + * due to already set. + */ + void OnHandled(const EditorDOMPoint& aStartPoint, + const EditorDOMPoint& aEndPoint) { + if (!mFirstHandledPoint.IsSet()) { + mFirstHandledPoint = aStartPoint; + } + mLastHandledPoint = aEndPoint; + } + void OnHandled(nsIContent& aContent) { + if (!mFirstHandledPoint.IsSet()) { + mFirstHandledPoint.Set(&aContent, 0u); + } + mLastHandledPoint = EditorDOMPoint::AtEndOf(aContent); + } + + // mFirstHandledPoint and mLastHandledPoint store the first and last points + // which are newly created or apply the new style, or just ignored at trying + // to split a text node. + EditorDOMPoint mFirstHandledPoint; + EditorDOMPoint mLastHandledPoint; +}; + +} // namespace mozilla + +#endif // #ifndef HTMLEditorNestedClasses_h |