editor/libeditor/base/nsSelectionState.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/editor/libeditor/base/nsSelectionState.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,283 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef __selectionstate_h__
    1.10 +#define __selectionstate_h__
    1.11 +
    1.12 +#include "nsCOMPtr.h"
    1.13 +#include "nsIDOMNode.h"
    1.14 +#include "nsINode.h"
    1.15 +#include "nsTArray.h"
    1.16 +#include "nscore.h"
    1.17 +
    1.18 +class nsCycleCollectionTraversalCallback;
    1.19 +class nsIDOMCharacterData;
    1.20 +class nsIDOMRange;
    1.21 +class nsISelection;
    1.22 +class nsRange;
    1.23 +namespace mozilla {
    1.24 +namespace dom {
    1.25 +class Selection;
    1.26 +}
    1.27 +}
    1.28 +
    1.29 +/***************************************************************************
    1.30 + * class for recording selection info.  stores selection as collection of
    1.31 + * { {startnode, startoffset} , {endnode, endoffset} } tuples.  Can't store
    1.32 + * ranges since dom gravity will possibly change the ranges.
    1.33 + */
    1.34 +
    1.35 +// first a helper struct for saving/setting ranges
    1.36 +struct nsRangeStore MOZ_FINAL
    1.37 +{
    1.38 +  nsRangeStore();
    1.39 +
    1.40 +private:
    1.41 +  // Private destructor, to discourage deletion outside of Release():
    1.42 +  ~nsRangeStore();
    1.43 +
    1.44 +public:
    1.45 +  nsresult StoreRange(nsIDOMRange *aRange);
    1.46 +  nsresult GetRange(nsRange** outRange);
    1.47 +
    1.48 +  NS_INLINE_DECL_REFCOUNTING(nsRangeStore)
    1.49 +        
    1.50 +  nsCOMPtr<nsIDOMNode> startNode;
    1.51 +  int32_t              startOffset;
    1.52 +  nsCOMPtr<nsIDOMNode> endNode;
    1.53 +  int32_t              endOffset;
    1.54 +  // DEBUG:   static int32_t n;
    1.55 +};
    1.56 +
    1.57 +class nsSelectionState
    1.58 +{
    1.59 +  public:
    1.60 +      
    1.61 +    nsSelectionState();
    1.62 +    ~nsSelectionState();
    1.63 +
    1.64 +    void DoTraverse(nsCycleCollectionTraversalCallback &cb);
    1.65 +    void DoUnlink() { MakeEmpty(); }
    1.66 +  
    1.67 +    void     SaveSelection(mozilla::dom::Selection *aSel);
    1.68 +    nsresult RestoreSelection(nsISelection *aSel);
    1.69 +    bool     IsCollapsed();
    1.70 +    bool     IsEqual(nsSelectionState *aSelState);
    1.71 +    void     MakeEmpty();
    1.72 +    bool     IsEmpty();
    1.73 +  protected:    
    1.74 +    nsTArray<nsRefPtr<nsRangeStore> > mArray;
    1.75 +    
    1.76 +    friend class nsRangeUpdater;
    1.77 +};
    1.78 +
    1.79 +class nsRangeUpdater
    1.80 +{
    1.81 +  public:    
    1.82 +  
    1.83 +    nsRangeUpdater();
    1.84 +    ~nsRangeUpdater();
    1.85 +  
    1.86 +    void RegisterRangeItem(nsRangeStore *aRangeItem);
    1.87 +    void DropRangeItem(nsRangeStore *aRangeItem);
    1.88 +    nsresult RegisterSelectionState(nsSelectionState &aSelState);
    1.89 +    nsresult DropSelectionState(nsSelectionState &aSelState);
    1.90 +    
    1.91 +    // editor selection gravity routines.  Note that we can't always depend on
    1.92 +    // DOM Range gravity to do what we want to the "real" selection.  For instance,
    1.93 +    // if you move a node, that corresponds to deleting it and reinserting it.
    1.94 +    // DOM Range gravity will promote the selection out of the node on deletion,
    1.95 +    // which is not what you want if you know you are reinserting it.
    1.96 +    nsresult SelAdjCreateNode(nsIDOMNode *aParent, int32_t aPosition);
    1.97 +    nsresult SelAdjInsertNode(nsIDOMNode *aParent, int32_t aPosition);
    1.98 +    void     SelAdjDeleteNode(nsIDOMNode *aNode);
    1.99 +    nsresult SelAdjSplitNode(nsIDOMNode *aOldRightNode, int32_t aOffset, nsIDOMNode *aNewLeftNode);
   1.100 +    nsresult SelAdjJoinNodes(nsIDOMNode *aLeftNode, 
   1.101 +                             nsIDOMNode *aRightNode, 
   1.102 +                             nsIDOMNode *aParent, 
   1.103 +                             int32_t aOffset,
   1.104 +                             int32_t aOldLeftNodeLength);
   1.105 +    nsresult SelAdjInsertText(nsIDOMCharacterData *aTextNode, int32_t aOffset, const nsAString &aString);
   1.106 +    nsresult SelAdjDeleteText(nsIDOMCharacterData *aTextNode, int32_t aOffset, int32_t aLength);
   1.107 +    // the following gravity routines need will/did sandwiches, because the other gravity
   1.108 +    // routines will be called inside of these sandwiches, but should be ignored.
   1.109 +    nsresult WillReplaceContainer();
   1.110 +    nsresult DidReplaceContainer(nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode);
   1.111 +    nsresult WillRemoveContainer();
   1.112 +    nsresult DidRemoveContainer(nsIDOMNode *aNode, nsIDOMNode *aParent, int32_t aOffset, uint32_t aNodeOrigLen);
   1.113 +    nsresult WillInsertContainer();
   1.114 +    nsresult DidInsertContainer();
   1.115 +    void WillMoveNode();
   1.116 +    void DidMoveNode(nsINode* aOldParent, int32_t aOldOffset,
   1.117 +                     nsINode* aNewParent, int32_t aNewOffset);
   1.118 +  protected:    
   1.119 +    nsTArray<nsRefPtr<nsRangeStore> > mArray;
   1.120 +    bool mLock;
   1.121 +};
   1.122 +
   1.123 +
   1.124 +/***************************************************************************
   1.125 + * helper class for using nsSelectionState.  stack based class for doing
   1.126 + * preservation of dom points across editor actions
   1.127 + */
   1.128 +
   1.129 +class MOZ_STACK_CLASS nsAutoTrackDOMPoint
   1.130 +{
   1.131 +  private:
   1.132 +    nsRangeUpdater &mRU;
   1.133 +    nsCOMPtr<nsIDOMNode> *mNode;
   1.134 +    int32_t *mOffset;
   1.135 +    nsRefPtr<nsRangeStore> mRangeItem;
   1.136 +  public:
   1.137 +    nsAutoTrackDOMPoint(nsRangeUpdater &aRangeUpdater, nsCOMPtr<nsIDOMNode> *aNode, int32_t *aOffset) :
   1.138 +    mRU(aRangeUpdater)
   1.139 +    ,mNode(aNode)
   1.140 +    ,mOffset(aOffset)
   1.141 +    {
   1.142 +      mRangeItem = new nsRangeStore();
   1.143 +      mRangeItem->startNode = *mNode;
   1.144 +      mRangeItem->endNode = *mNode;
   1.145 +      mRangeItem->startOffset = *mOffset;
   1.146 +      mRangeItem->endOffset = *mOffset;
   1.147 +      mRU.RegisterRangeItem(mRangeItem);
   1.148 +    }
   1.149 +    
   1.150 +    ~nsAutoTrackDOMPoint()
   1.151 +    {
   1.152 +      mRU.DropRangeItem(mRangeItem);
   1.153 +      *mNode  = mRangeItem->startNode;
   1.154 +      *mOffset = mRangeItem->startOffset;
   1.155 +    }
   1.156 +};
   1.157 +
   1.158 +
   1.159 +
   1.160 +/***************************************************************************
   1.161 + * another helper class for nsSelectionState.  stack based class for doing
   1.162 + * Will/DidReplaceContainer()
   1.163 + */
   1.164 +
   1.165 +class MOZ_STACK_CLASS nsAutoReplaceContainerSelNotify
   1.166 +{
   1.167 +  private:
   1.168 +    nsRangeUpdater &mRU;
   1.169 +    nsIDOMNode *mOriginalNode;
   1.170 +    nsIDOMNode *mNewNode;
   1.171 +
   1.172 +  public:
   1.173 +    nsAutoReplaceContainerSelNotify(nsRangeUpdater &aRangeUpdater, nsIDOMNode *aOriginalNode, nsIDOMNode *aNewNode) :
   1.174 +    mRU(aRangeUpdater)
   1.175 +    ,mOriginalNode(aOriginalNode)
   1.176 +    ,mNewNode(aNewNode)
   1.177 +    {
   1.178 +      mRU.WillReplaceContainer();
   1.179 +    }
   1.180 +    
   1.181 +    ~nsAutoReplaceContainerSelNotify()
   1.182 +    {
   1.183 +      mRU.DidReplaceContainer(mOriginalNode, mNewNode);
   1.184 +    }
   1.185 +};
   1.186 +
   1.187 +
   1.188 +/***************************************************************************
   1.189 + * another helper class for nsSelectionState.  stack based class for doing
   1.190 + * Will/DidRemoveContainer()
   1.191 + */
   1.192 +
   1.193 +class MOZ_STACK_CLASS nsAutoRemoveContainerSelNotify
   1.194 +{
   1.195 +  private:
   1.196 +    nsRangeUpdater &mRU;
   1.197 +    nsIDOMNode *mNode;
   1.198 +    nsIDOMNode *mParent;
   1.199 +    int32_t    mOffset;
   1.200 +    uint32_t   mNodeOrigLen;
   1.201 +
   1.202 +  public:
   1.203 +    nsAutoRemoveContainerSelNotify(nsRangeUpdater& aRangeUpdater,
   1.204 +                                   nsINode* aNode,
   1.205 +                                   nsINode* aParent,
   1.206 +                                   int32_t aOffset,
   1.207 +                                   uint32_t aNodeOrigLen)
   1.208 +      : mRU(aRangeUpdater)
   1.209 +      , mNode(aNode->AsDOMNode())
   1.210 +      , mParent(aParent->AsDOMNode())
   1.211 +      , mOffset(aOffset)
   1.212 +      , mNodeOrigLen(aNodeOrigLen)
   1.213 +    {
   1.214 +      mRU.WillRemoveContainer();
   1.215 +    }
   1.216 +    
   1.217 +    ~nsAutoRemoveContainerSelNotify()
   1.218 +    {
   1.219 +      mRU.DidRemoveContainer(mNode, mParent, mOffset, mNodeOrigLen);
   1.220 +    }
   1.221 +};
   1.222 +
   1.223 +/***************************************************************************
   1.224 + * another helper class for nsSelectionState.  stack based class for doing
   1.225 + * Will/DidInsertContainer()
   1.226 + */
   1.227 +
   1.228 +class MOZ_STACK_CLASS nsAutoInsertContainerSelNotify
   1.229 +{
   1.230 +  private:
   1.231 +    nsRangeUpdater &mRU;
   1.232 +
   1.233 +  public:
   1.234 +    nsAutoInsertContainerSelNotify(nsRangeUpdater &aRangeUpdater) :
   1.235 +    mRU(aRangeUpdater)
   1.236 +    {
   1.237 +      mRU.WillInsertContainer();
   1.238 +    }
   1.239 +    
   1.240 +    ~nsAutoInsertContainerSelNotify()
   1.241 +    {
   1.242 +      mRU.DidInsertContainer();
   1.243 +    }
   1.244 +};
   1.245 +
   1.246 +
   1.247 +/***************************************************************************
   1.248 + * another helper class for nsSelectionState.  stack based class for doing
   1.249 + * Will/DidMoveNode()
   1.250 + */
   1.251 +
   1.252 +class MOZ_STACK_CLASS nsAutoMoveNodeSelNotify
   1.253 +{
   1.254 +  private:
   1.255 +    nsRangeUpdater &mRU;
   1.256 +    nsINode* mOldParent;
   1.257 +    nsINode* mNewParent;
   1.258 +    int32_t    mOldOffset;
   1.259 +    int32_t    mNewOffset;
   1.260 +
   1.261 +  public:
   1.262 +    nsAutoMoveNodeSelNotify(nsRangeUpdater &aRangeUpdater, 
   1.263 +                            nsINode* aOldParent,
   1.264 +                            int32_t aOldOffset, 
   1.265 +                            nsINode* aNewParent,
   1.266 +                            int32_t aNewOffset)
   1.267 +      : mRU(aRangeUpdater)
   1.268 +      , mOldParent(aOldParent)
   1.269 +      , mNewParent(aNewParent)
   1.270 +      , mOldOffset(aOldOffset)
   1.271 +      , mNewOffset(aNewOffset)
   1.272 +    {
   1.273 +      MOZ_ASSERT(aOldParent);
   1.274 +      MOZ_ASSERT(aNewParent);
   1.275 +      mRU.WillMoveNode();
   1.276 +    }
   1.277 +    
   1.278 +    ~nsAutoMoveNodeSelNotify()
   1.279 +    {
   1.280 +      mRU.DidMoveNode(mOldParent, mOldOffset, mNewParent, mNewOffset);
   1.281 +    }
   1.282 +};
   1.283 +
   1.284 +#endif
   1.285 +
   1.286 +

mercurial