layout/generic/Selection.h

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     5  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 #ifndef mozilla_Selection_h__
     8 #define mozilla_Selection_h__
    10 #include "nsIWeakReference.h"
    12 #include "nsISelection.h"
    13 #include "nsISelectionController.h"
    14 #include "nsISelectionPrivate.h"
    15 #include "nsRange.h"
    16 #include "nsThreadUtils.h"
    17 #include "mozilla/TextRange.h"
    18 #include "nsWrapperCache.h"
    20 struct CachedOffsetForFrame;
    21 class nsAutoScrollTimer;
    22 class nsIContentIterator;
    23 class nsIFrame;
    24 class nsFrameSelection;
    25 struct SelectionDetails;
    27 namespace mozilla {
    28 class ErrorResult;
    29 }
    31 struct RangeData
    32 {
    33   RangeData(nsRange* aRange)
    34     : mRange(aRange)
    35   {}
    37   nsRefPtr<nsRange> mRange;
    38   mozilla::TextRangeStyle mTextRangeStyle;
    39 };
    41 // Note, the ownership of mozilla::dom::Selection depends on which way the
    42 // object is created. When nsFrameSelection has created Selection,
    43 // addreffing/releasing the Selection object is aggregated to nsFrameSelection.
    44 // Otherwise normal addref/release is used.  This ensures that nsFrameSelection
    45 // is never deleted before its Selections.
    46 namespace mozilla {
    47 namespace dom {
    49 class Selection : public nsISelectionPrivate,
    50                   public nsWrapperCache,
    51                   public nsSupportsWeakReference
    52 {
    53 public:
    54   Selection();
    55   Selection(nsFrameSelection *aList);
    56   virtual ~Selection();
    58   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
    59   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Selection, nsISelectionPrivate)
    60   NS_DECL_NSISELECTION
    61   NS_DECL_NSISELECTIONPRIVATE
    63   nsIDocument* GetParentObject() const;
    65   // utility methods for scrolling the selection into view
    66   nsPresContext* GetPresContext() const;
    67   nsIPresShell* GetPresShell() const;
    68   nsFrameSelection* GetFrameSelection() const { return mFrameSelection; }
    69   // Returns a rect containing the selection region, and frame that that
    70   // position is relative to. For SELECTION_ANCHOR_REGION or
    71   // SELECTION_FOCUS_REGION the rect is a zero-width rectangle. For
    72   // SELECTION_WHOLE_SELECTION the rect contains both the anchor and focus
    73   // region rects.
    74   nsIFrame*     GetSelectionAnchorGeometry(SelectionRegion aRegion, nsRect *aRect);
    75   // Returns the position of the region (SELECTION_ANCHOR_REGION or
    76   // SELECTION_FOCUS_REGION only), and frame that that position is relative to.
    77   // The 'position' is a zero-width rectangle.
    78   nsIFrame*     GetSelectionEndPointGeometry(SelectionRegion aRegion, nsRect *aRect);
    80   nsresult      PostScrollSelectionIntoViewEvent(
    81                                         SelectionRegion aRegion,
    82                                         int32_t aFlags,
    83                                         nsIPresShell::ScrollAxis aVertical,
    84                                         nsIPresShell::ScrollAxis aHorizontal);
    85   enum {
    86     SCROLL_SYNCHRONOUS = 1<<1,
    87     SCROLL_FIRST_ANCESTOR_ONLY = 1<<2,
    88     SCROLL_DO_FLUSH = 1<<3,
    89     SCROLL_OVERFLOW_HIDDEN = 1<<5
    90   };
    91   // aDoFlush only matters if aIsSynchronous is true.  If not, we'll just flush
    92   // when the scroll event fires so we make sure to scroll to the right place.
    93   nsresult      ScrollIntoView(SelectionRegion aRegion,
    94                                nsIPresShell::ScrollAxis aVertical =
    95                                  nsIPresShell::ScrollAxis(),
    96                                nsIPresShell::ScrollAxis aHorizontal =
    97                                  nsIPresShell::ScrollAxis(),
    98                                int32_t aFlags = 0);
    99   nsresult      SubtractRange(RangeData* aRange, nsRange* aSubtract,
   100                               nsTArray<RangeData>* aOutput);
   101   nsresult      AddItem(nsRange *aRange, int32_t* aOutIndex);
   102   nsresult      RemoveItem(nsRange *aRange);
   103   nsresult      RemoveCollapsedRanges();
   104   nsresult      Clear(nsPresContext* aPresContext);
   105   nsresult      Collapse(nsINode* aParentNode, int32_t aOffset);
   106   nsresult      Extend(nsINode* aParentNode, int32_t aOffset);
   107   nsRange*      GetRangeAt(int32_t aIndex);
   108   int32_t GetRangeCount() { return mRanges.Length(); }
   110   // Get the anchor-to-focus range if we don't care which end is
   111   // anchor and which end is focus.
   112   const nsRange* GetAnchorFocusRange() const {
   113     return mAnchorFocusRange;
   114   }
   116   nsDirection  GetDirection(){return mDirection;}
   117   void         SetDirection(nsDirection aDir){mDirection = aDir;}
   118   nsresult     SetAnchorFocusToRange(nsRange *aRange);
   119   void         ReplaceAnchorFocusRange(nsRange *aRange);
   121   //  NS_IMETHOD   GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, int32_t aOffset, bool aIsEndNode, nsIFrame **aResultFrame);
   122   NS_IMETHOD   GetPrimaryFrameForAnchorNode(nsIFrame **aResultFrame);
   123   NS_IMETHOD   GetPrimaryFrameForFocusNode(nsIFrame **aResultFrame, int32_t *aOffset, bool aVisual);
   124   NS_IMETHOD   LookUpSelection(nsIContent *aContent, int32_t aContentOffset, int32_t aContentLength,
   125                              SelectionDetails **aReturnDetails, SelectionType aType, bool aSlowCheck);
   126   NS_IMETHOD   Repaint(nsPresContext* aPresContext);
   128   // Note: StartAutoScrollTimer might destroy arbitrary frames etc.
   129   nsresult     StartAutoScrollTimer(nsIFrame *aFrame,
   130                                     nsPoint& aPoint,
   131                                     uint32_t aDelay);
   133   nsresult     StopAutoScrollTimer();
   135   JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
   137   // WebIDL methods
   138   nsINode*     GetAnchorNode();
   139   uint32_t     AnchorOffset();
   140   nsINode*     GetFocusNode();
   141   uint32_t     FocusOffset();
   143   bool IsCollapsed();
   144   void Collapse(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
   145   void CollapseToStart(mozilla::ErrorResult& aRv);
   146   void CollapseToEnd(mozilla::ErrorResult& aRv);
   148   void Extend(nsINode& aNode, uint32_t aOffset, mozilla::ErrorResult& aRv);
   150   void SelectAllChildren(nsINode& aNode, mozilla::ErrorResult& aRv);
   151   void DeleteFromDocument(mozilla::ErrorResult& aRv);
   153   uint32_t RangeCount() const
   154   {
   155     return mRanges.Length();
   156   }
   157   nsRange* GetRangeAt(uint32_t aIndex, mozilla::ErrorResult& aRv);
   158   void AddRange(nsRange& aRange, mozilla::ErrorResult& aRv);
   159   void RemoveRange(nsRange& aRange, mozilla::ErrorResult& aRv);
   160   void RemoveAllRanges(mozilla::ErrorResult& aRv);
   162   void Stringify(nsAString& aResult);
   164   bool ContainsNode(nsINode* aNode, bool aPartlyContained, mozilla::ErrorResult& aRv);
   166   void Modify(const nsAString& aAlter, const nsAString& aDirection,
   167               const nsAString& aGranularity, mozilla::ErrorResult& aRv);
   169   bool GetInterlinePosition(mozilla::ErrorResult& aRv);
   170   void SetInterlinePosition(bool aValue, mozilla::ErrorResult& aRv);
   172   void ToStringWithFormat(const nsAString& aFormatType,
   173                           uint32_t aFlags,
   174                           int32_t aWrapColumn,
   175                           nsAString& aReturn,
   176                           mozilla::ErrorResult& aRv);
   177   void AddSelectionListener(nsISelectionListener* aListener,
   178                             mozilla::ErrorResult& aRv);
   179   void RemoveSelectionListener(nsISelectionListener* aListener,
   180                                mozilla::ErrorResult& aRv);
   182   int16_t Type() const { return mType; }
   184   void GetRangesForInterval(nsINode& aBeginNode, int32_t aBeginOffset,
   185                             nsINode& aEndNode, int32_t aEndOffset,
   186                             bool aAllowAdjacent,
   187                             nsTArray<nsRefPtr<nsRange>>& aReturn,
   188                             mozilla::ErrorResult& aRv);
   190   void ScrollIntoView(int16_t aRegion, bool aIsSynchronous,
   191                       int16_t aVPercent, int16_t aHPercent,
   192                       mozilla::ErrorResult& aRv);
   194 private:
   195   friend class ::nsAutoScrollTimer;
   197   // Note: DoAutoScroll might destroy arbitrary frames etc.
   198   nsresult DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint);
   200 public:
   201   SelectionType GetType(){return mType;}
   202   void          SetType(SelectionType aType){mType = aType;}
   204   nsresult     NotifySelectionListeners();
   206 private:
   208   class ScrollSelectionIntoViewEvent;
   209   friend class ScrollSelectionIntoViewEvent;
   211   class ScrollSelectionIntoViewEvent : public nsRunnable {
   212   public:
   213     NS_DECL_NSIRUNNABLE
   214     ScrollSelectionIntoViewEvent(Selection* aSelection,
   215                                  SelectionRegion aRegion,
   216                                  nsIPresShell::ScrollAxis aVertical,
   217                                  nsIPresShell::ScrollAxis aHorizontal,
   218                                  int32_t aFlags)
   219       : mSelection(aSelection),
   220         mRegion(aRegion),
   221         mVerticalScroll(aVertical),
   222         mHorizontalScroll(aHorizontal),
   223         mFlags(aFlags) {
   224       NS_ASSERTION(aSelection, "null parameter");
   225     }
   226     void Revoke() { mSelection = nullptr; }
   227   private:
   228     Selection *mSelection;
   229     SelectionRegion mRegion;
   230     nsIPresShell::ScrollAxis mVerticalScroll;
   231     nsIPresShell::ScrollAxis mHorizontalScroll;
   232     int32_t mFlags;
   233   };
   235   void setAnchorFocusRange(int32_t aIndex); // pass in index into mRanges;
   236                                             // negative value clears
   237                                             // mAnchorFocusRange
   238   nsresult     SelectAllFramesForContent(nsIContentIterator *aInnerIter,
   239                                nsIContent *aContent,
   240                                bool aSelected);
   241   nsresult     selectFrames(nsPresContext* aPresContext, nsRange *aRange, bool aSelect);
   242   nsresult     getTableCellLocationFromRange(nsRange *aRange, int32_t *aSelectionType, int32_t *aRow, int32_t *aCol);
   243   nsresult     addTableCellRange(nsRange *aRange, bool *aDidAddRange, int32_t *aOutIndex);
   245   nsresult FindInsertionPoint(
   246       nsTArray<RangeData>* aElementArray,
   247       nsINode* aPointNode, int32_t aPointOffset,
   248       nsresult (*aComparator)(nsINode*,int32_t,nsRange*,int32_t*),
   249       int32_t* aPoint);
   250   bool EqualsRangeAtPoint(nsINode* aBeginNode, int32_t aBeginOffset,
   251                             nsINode* aEndNode, int32_t aEndOffset,
   252                             int32_t aRangeIndex);
   253   nsresult GetIndicesForInterval(nsINode* aBeginNode, int32_t aBeginOffset,
   254                                  nsINode* aEndNode, int32_t aEndOffset,
   255                                  bool aAllowAdjacent,
   256                                  int32_t* aStartIndex, int32_t* aEndIndex);
   257   RangeData* FindRangeData(nsIDOMRange* aRange);
   259   // These are the ranges inside this selection. They are kept sorted in order
   260   // of DOM start position.
   261   //
   262   // This data structure is sorted by the range beginnings. As the ranges are
   263   // disjoint, it is also implicitly sorted by the range endings. This allows
   264   // us to perform binary searches when searching for existence of a range,
   265   // giving us O(log n) search time.
   266   //
   267   // Inserting a new range requires finding the overlapping interval, requiring
   268   // two binary searches plus up to an additional 6 DOM comparisons. If this
   269   // proves to be a performance concern, then an interval tree may be a
   270   // possible solution, allowing the calculation of the overlap interval in
   271   // O(log n) time, though this would require rebalancing and other overhead.
   272   nsTArray<RangeData> mRanges;
   274   nsRefPtr<nsRange> mAnchorFocusRange;
   275   nsRefPtr<nsFrameSelection> mFrameSelection;
   276   nsRefPtr<nsAutoScrollTimer> mAutoScrollTimer;
   277   nsCOMArray<nsISelectionListener> mSelectionListeners;
   278   nsRevocableEventPtr<ScrollSelectionIntoViewEvent> mScrollEvent;
   279   CachedOffsetForFrame *mCachedOffsetForFrame;
   280   nsDirection mDirection;
   281   SelectionType mType;
   282 };
   284 } // namespace dom
   285 } // namespace mozilla
   287 #endif // mozilla_Selection_h__

mercurial