tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

MoveNodeTransaction.h (9286B)


      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 MoveNodeTransaction_h
      7 #define MoveNodeTransaction_h
      8 
      9 #include "EditTransactionBase.h"  // for EditTransactionBase, etc.
     10 
     11 #include "EditorDOMPoint.h"
     12 #include "EditorForwards.h"
     13 #include "SelectionState.h"
     14 
     15 #include "nsCOMPtr.h"  // for nsCOMPtr
     16 #include "nsCycleCollectionParticipant.h"
     17 #include "nsIContent.h"       // for nsIContent
     18 #include "nsISupportsImpl.h"  // for NS_DECL_ISUPPORTS_INHERITED
     19 
     20 namespace mozilla {
     21 
     22 class MoveNodeTransactionBase : public EditTransactionBase {
     23 public:
     24  NS_DECL_ISUPPORTS_INHERITED
     25  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MoveNodeTransactionBase,
     26                                           EditTransactionBase)
     27  NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(MoveNodeTransactionBase)
     28 
     29  virtual EditorRawDOMPoint SuggestPointToPutCaret() const = 0;
     30  virtual EditorRawDOMPoint SuggestNextInsertionPoint() const = 0;
     31 
     32 protected:
     33  MoveNodeTransactionBase(HTMLEditor& aHTMLEditor,
     34                          nsIContent& aLastContentToMove,
     35                          const EditorRawDOMPoint& aPointToInsert);
     36 
     37  virtual ~MoveNodeTransactionBase() = default;
     38 
     39  [[nodiscard]] EditorRawDOMPoint SuggestPointToPutCaret(
     40      nsIContent* aLastMoveContent) const {
     41    if (MOZ_UNLIKELY(!mContainer || !aLastMoveContent)) {
     42      return EditorRawDOMPoint();
     43    }
     44    return EditorRawDOMPoint::After(*aLastMoveContent);
     45  }
     46 
     47  [[nodiscard]] EditorRawDOMPoint SuggestNextInsertionPoint(
     48      nsIContent* aLastMoveContent) const {
     49    if (MOZ_UNLIKELY(!mContainer)) {
     50      return EditorRawDOMPoint();
     51    }
     52    if (!mReference) {
     53      return EditorRawDOMPoint::AtEndOf(*aLastMoveContent);
     54    }
     55    if (MOZ_UNLIKELY(mReference->GetParentNode() != mContainer)) {
     56      if (MOZ_LIKELY(aLastMoveContent->GetParentNode() == mContainer)) {
     57        return EditorRawDOMPoint(aLastMoveContent).NextPoint();
     58      }
     59      return EditorRawDOMPoint::AtEndOf(mContainer);
     60    }
     61    return EditorRawDOMPoint(mReference);
     62  }
     63 
     64  // mContainer is new container of mContentToInsert after (re-)doing the
     65  // transaction.
     66  nsCOMPtr<nsINode> mContainer;
     67 
     68  // mReference is the child content where mContentToMove should be or was
     69  // inserted into the mContainer.  This is typically the next sibling of
     70  // mContentToMove after moving.
     71  nsCOMPtr<nsIContent> mReference;
     72 
     73  // mOldContainer is the original container of mContentToMove before moving.
     74  nsCOMPtr<nsINode> mOldContainer;
     75 
     76  // mOldNextSibling is the next sibling of mCOntentToMove before moving.
     77  nsCOMPtr<nsIContent> mOldNextSibling;
     78 
     79  // The editor for this transaction.
     80  RefPtr<HTMLEditor> mHTMLEditor;
     81 };
     82 
     83 /**
     84 * A transaction that moves a content node to a specified point.
     85 */
     86 class MoveNodeTransaction final : public MoveNodeTransactionBase {
     87 protected:
     88  template <typename PT, typename CT>
     89  MoveNodeTransaction(HTMLEditor& aHTMLEditor, nsIContent& aContentToMove,
     90                      const EditorDOMPointBase<PT, CT>& aPointToInsert);
     91 
     92 public:
     93  /**
     94   * Create a transaction for moving aContentToMove before the child at
     95   * aPointToInsert.
     96   *
     97   * @param aHTMLEditor         The editor which manages the transaction.
     98   * @param aContentToMove      The node to be moved.
     99   * @param aPointToInsert      The insertion point of aContentToMove.
    100   * @return                    A MoveNodeTransaction which was initialized
    101   *                            with the arguments.
    102   */
    103  template <typename PT, typename CT>
    104  static already_AddRefed<MoveNodeTransaction> MaybeCreate(
    105      HTMLEditor& aHTMLEditor, nsIContent& aContentToMove,
    106      const EditorDOMPointBase<PT, CT>& aPointToInsert);
    107 
    108  NS_DECL_ISUPPORTS_INHERITED
    109  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MoveNodeTransaction,
    110                                           MoveNodeTransactionBase)
    111 
    112  NS_DECL_EDITTRANSACTIONBASE
    113  NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(MoveNodeTransaction)
    114 
    115  MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() final;
    116 
    117  /**
    118   * SuggestPointToPutCaret() suggests a point after doing or redoing the
    119   * transaction.
    120   */
    121  EditorRawDOMPoint SuggestPointToPutCaret() const final {
    122    return MoveNodeTransactionBase::SuggestPointToPutCaret(mContentToMove);
    123  }
    124 
    125  /**
    126   * Suggest next insertion point if the caller wants to move another content
    127   * node around the insertion point.
    128   */
    129  EditorRawDOMPoint SuggestNextInsertionPoint() const final {
    130    return MoveNodeTransactionBase::SuggestNextInsertionPoint(mContentToMove);
    131  }
    132 
    133  friend std::ostream& operator<<(std::ostream& aStream,
    134                                  const MoveNodeTransaction& aTransaction);
    135 
    136 protected:
    137  virtual ~MoveNodeTransaction() = default;
    138 
    139  MOZ_CAN_RUN_SCRIPT nsresult DoTransactionInternal();
    140 
    141  // The content which will be or was moved from mOldContainer to mContainer.
    142  nsCOMPtr<nsIContent> mContentToMove;
    143 };
    144 
    145 /**
    146 * A transaction that moves multiple siblings once.
    147 */
    148 class MoveSiblingsTransaction final : public MoveNodeTransactionBase {
    149 protected:
    150  template <typename PT, typename CT>
    151  MoveSiblingsTransaction(HTMLEditor& aHTMLEditor,
    152                          nsIContent& aFirstContentToMove,
    153                          nsIContent& aLastContentToMove,
    154                          uint32_t aNumberOfSiblings,
    155                          const EditorDOMPointBase<PT, CT>& aPointToInsert);
    156 
    157 public:
    158  /**
    159   * Create a transaction for moving aContentToMove before the child at
    160   * aPointToInsert.
    161   *
    162   * @param aHTMLEditor         The editor which manages the transaction.
    163   * @param aFirstContentToMove The first node to be moved.
    164   * @param aLastContentToMove  The last node to be moved.  Its parent node
    165   *                            should be the parent of aFirstContentToMove and
    166   *                            a following sibling of aFirstContentToMove.
    167   * @param aNumberOfSiblings   The number of siblings to move.
    168   * @param aPointToInsert      The insertion point of aContentToMove.
    169   * @return                    A MoveSiblingsTransaction which was initialized
    170   *                            with the arguments.
    171   */
    172  template <typename PT, typename CT>
    173  static already_AddRefed<MoveSiblingsTransaction> MaybeCreate(
    174      HTMLEditor& aHTMLEditor, nsIContent& aFirstContentToMove,
    175      nsIContent& aLastContentToMove,
    176      const EditorDOMPointBase<PT, CT>& aPointToInsert);
    177 
    178  NS_DECL_ISUPPORTS_INHERITED
    179  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MoveSiblingsTransaction,
    180                                           MoveNodeTransactionBase)
    181 
    182  NS_DECL_EDITTRANSACTIONBASE
    183  NS_DECL_EDITTRANSACTIONBASE_GETASMETHODS_OVERRIDE(MoveSiblingsTransaction)
    184 
    185  MOZ_CAN_RUN_SCRIPT NS_IMETHOD RedoTransaction() override;
    186 
    187  /**
    188   * SuggestPointToPutCaret() suggests a point after doing or redoing the
    189   * transaction.
    190   */
    191  EditorRawDOMPoint SuggestPointToPutCaret() const final {
    192    return MoveNodeTransactionBase::SuggestPointToPutCaret(
    193        GetLastMovedContent());
    194  }
    195 
    196  /**
    197   * Suggest next insertion point if the caller wants to move another content
    198   * node around the insertion point.
    199   */
    200  EditorRawDOMPoint SuggestNextInsertionPoint() const final {
    201    return MoveNodeTransactionBase::SuggestNextInsertionPoint(
    202        GetLastMovedContent());
    203  }
    204 
    205  const nsTArray<OwningNonNull<nsIContent>>& TargetSiblings() const {
    206    return mSiblingsToMove;
    207  }
    208 
    209  [[nodiscard]] nsIContent* GetFirstMovedContent() const;
    210  [[nodiscard]] nsIContent* GetLastMovedContent() const;
    211 
    212  friend std::ostream& operator<<(std::ostream& aStream,
    213                                  const MoveSiblingsTransaction& aTransaction);
    214 
    215 protected:
    216  virtual ~MoveSiblingsTransaction() = default;
    217 
    218  MOZ_CAN_RUN_SCRIPT nsresult DoTransactionInternal();
    219 
    220  [[nodiscard]] bool IsSiblingsToMoveValid() const {
    221    for (const auto& content : mSiblingsToMove) {
    222      if (MOZ_UNLIKELY(!content.isInitialized())) {
    223        return false;
    224      }
    225    }
    226    return true;
    227  }
    228 
    229  /**
    230   * Remove all aClonedSiblingsToMove from the DOM.  aClonedSiblingsToMove must
    231   * be a clone of mSiblingsToMove in the stack.
    232   */
    233  MOZ_CAN_RUN_SCRIPT void RemoveAllSiblingsToMove(
    234      HTMLEditor& aHTMLEditor,
    235      const nsTArray<OwningNonNull<nsIContent>>& aClonedSiblingsToMove,
    236      AutoMoveNodeSelNotify& aNotifier) const;
    237 
    238  /**
    239   * Insert all disconnected aClonedSiblingsToMove to before aReferenceNode or
    240   * end of aParentNode.  Before calling this, RemoveAllSiblingsToMove()
    241   * should've already been called.
    242   */
    243  MOZ_CAN_RUN_SCRIPT nsresult InsertAllSiblingsToMove(
    244      HTMLEditor& aHTMLEditor,
    245      const nsTArray<OwningNonNull<nsIContent>>& aClonedSiblingsToMove,
    246      nsINode& aParentNode, nsIContent* aReferenceNode,
    247      AutoMoveNodeSelNotify& aNotifier) const;
    248 
    249  // The content which will be or was moved from mOldContainer to mContainer.
    250  AutoTArray<OwningNonNull<nsIContent>, 2> mSiblingsToMove;
    251 
    252  // At undoing, this is set to true and at redoing, this is set to false.
    253  bool mDone = false;
    254 };
    255 
    256 }  // namespace mozilla
    257 
    258 #endif  // #ifndef MoveNodeTransaction_h