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

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

mercurial