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"
16 #include "nsThreadUtils.h"
17 #include "mozilla/TextRange.h"
18 #include "nsWrapperCache.h"
20 struct CachedOffsetForFrame
;
21 class nsAutoScrollTimer
;
22 class nsIContentIterator
;
24 class nsFrameSelection
;
25 struct SelectionDetails
;
33 explicit RangeData(nsRange
* aRange
)
37 nsRefPtr
<nsRange
> mRange
;
38 mozilla::TextRangeStyle mTextRangeStyle
;
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.
49 class Selection MOZ_FINAL
: public nsISelectionPrivate
,
50 public nsWrapperCache
,
51 public nsSupportsWeakReference
58 explicit Selection(nsFrameSelection
*aList
);
60 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
61 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Selection
, nsISelectionPrivate
)
63 NS_DECL_NSISELECTIONPRIVATE
65 nsIDocument
* GetParentObject() const;
67 // utility methods for scrolling the selection into view
68 nsPresContext
* GetPresContext() const;
69 nsIPresShell
* GetPresShell() const;
70 nsFrameSelection
* GetFrameSelection() const { return mFrameSelection
; }
71 // Returns a rect containing the selection region, and frame that that
72 // position is relative to. For SELECTION_ANCHOR_REGION or
73 // SELECTION_FOCUS_REGION the rect is a zero-width rectangle. For
74 // SELECTION_WHOLE_SELECTION the rect contains both the anchor and focus
76 nsIFrame
* GetSelectionAnchorGeometry(SelectionRegion aRegion
, nsRect
*aRect
);
77 // Returns the position of the region (SELECTION_ANCHOR_REGION or
78 // SELECTION_FOCUS_REGION only), and frame that that position is relative to.
79 // The 'position' is a zero-width rectangle.
80 nsIFrame
* GetSelectionEndPointGeometry(SelectionRegion aRegion
, nsRect
*aRect
);
82 nsresult
PostScrollSelectionIntoViewEvent(
83 SelectionRegion aRegion
,
85 nsIPresShell::ScrollAxis aVertical
,
86 nsIPresShell::ScrollAxis aHorizontal
);
88 SCROLL_SYNCHRONOUS
= 1<<1,
89 SCROLL_FIRST_ANCESTOR_ONLY
= 1<<2,
90 SCROLL_DO_FLUSH
= 1<<3,
91 SCROLL_OVERFLOW_HIDDEN
= 1<<5
93 // aDoFlush only matters if aIsSynchronous is true. If not, we'll just flush
94 // when the scroll event fires so we make sure to scroll to the right place.
95 nsresult
ScrollIntoView(SelectionRegion aRegion
,
96 nsIPresShell::ScrollAxis aVertical
=
97 nsIPresShell::ScrollAxis(),
98 nsIPresShell::ScrollAxis aHorizontal
=
99 nsIPresShell::ScrollAxis(),
101 nsresult
SubtractRange(RangeData
* aRange
, nsRange
* aSubtract
,
102 nsTArray
<RangeData
>* aOutput
);
103 nsresult
AddItem(nsRange
*aRange
, int32_t* aOutIndex
);
104 nsresult
RemoveItem(nsRange
*aRange
);
105 nsresult
RemoveCollapsedRanges();
106 nsresult
Clear(nsPresContext
* aPresContext
);
107 nsresult
Collapse(nsINode
* aParentNode
, int32_t aOffset
);
108 nsresult
Extend(nsINode
* aParentNode
, int32_t aOffset
);
109 nsRange
* GetRangeAt(int32_t aIndex
);
110 int32_t GetRangeCount() { return mRanges
.Length(); }
112 // Get the anchor-to-focus range if we don't care which end is
113 // anchor and which end is focus.
114 const nsRange
* GetAnchorFocusRange() const {
115 return mAnchorFocusRange
;
118 nsDirection
GetDirection(){return mDirection
;}
119 void SetDirection(nsDirection aDir
){mDirection
= aDir
;}
120 nsresult
SetAnchorFocusToRange(nsRange
*aRange
);
121 void ReplaceAnchorFocusRange(nsRange
*aRange
);
123 // NS_IMETHOD GetPrimaryFrameForRangeEndpoint(nsIDOMNode *aNode, int32_t aOffset, bool aIsEndNode, nsIFrame **aResultFrame);
124 NS_IMETHOD
GetPrimaryFrameForAnchorNode(nsIFrame
**aResultFrame
);
125 NS_IMETHOD
GetPrimaryFrameForFocusNode(nsIFrame
**aResultFrame
, int32_t *aOffset
, bool aVisual
);
126 NS_IMETHOD
LookUpSelection(nsIContent
*aContent
, int32_t aContentOffset
, int32_t aContentLength
,
127 SelectionDetails
**aReturnDetails
, SelectionType aType
, bool aSlowCheck
);
128 NS_IMETHOD
Repaint(nsPresContext
* aPresContext
);
130 // Note: StartAutoScrollTimer might destroy arbitrary frames etc.
131 nsresult
StartAutoScrollTimer(nsIFrame
*aFrame
,
135 nsresult
StopAutoScrollTimer();
137 JSObject
* WrapObject(JSContext
* aCx
) MOZ_OVERRIDE
;
140 nsINode
* GetAnchorNode();
141 uint32_t AnchorOffset();
142 nsINode
* GetFocusNode();
143 uint32_t FocusOffset();
146 void Collapse(nsINode
& aNode
, uint32_t aOffset
, mozilla::ErrorResult
& aRv
);
147 void CollapseToStart(mozilla::ErrorResult
& aRv
);
148 void CollapseToEnd(mozilla::ErrorResult
& aRv
);
150 void Extend(nsINode
& aNode
, uint32_t aOffset
, mozilla::ErrorResult
& aRv
);
152 void SelectAllChildren(nsINode
& aNode
, mozilla::ErrorResult
& aRv
);
153 void DeleteFromDocument(mozilla::ErrorResult
& aRv
);
155 uint32_t RangeCount() const
157 return mRanges
.Length();
159 nsRange
* GetRangeAt(uint32_t aIndex
, mozilla::ErrorResult
& aRv
);
160 void AddRange(nsRange
& aRange
, mozilla::ErrorResult
& aRv
);
161 void RemoveRange(nsRange
& aRange
, mozilla::ErrorResult
& aRv
);
162 void RemoveAllRanges(mozilla::ErrorResult
& aRv
);
164 void Stringify(nsAString
& aResult
);
166 bool ContainsNode(nsINode
* aNode
, bool aPartlyContained
, mozilla::ErrorResult
& aRv
);
168 void Modify(const nsAString
& aAlter
, const nsAString
& aDirection
,
169 const nsAString
& aGranularity
, mozilla::ErrorResult
& aRv
);
171 bool GetInterlinePosition(mozilla::ErrorResult
& aRv
);
172 void SetInterlinePosition(bool aValue
, mozilla::ErrorResult
& aRv
);
174 void ToStringWithFormat(const nsAString
& aFormatType
,
178 mozilla::ErrorResult
& aRv
);
179 void AddSelectionListener(nsISelectionListener
* aListener
,
180 mozilla::ErrorResult
& aRv
);
181 void RemoveSelectionListener(nsISelectionListener
* aListener
,
182 mozilla::ErrorResult
& aRv
);
184 int16_t Type() const { return mType
; }
186 void GetRangesForInterval(nsINode
& aBeginNode
, int32_t aBeginOffset
,
187 nsINode
& aEndNode
, int32_t aEndOffset
,
189 nsTArray
<nsRefPtr
<nsRange
>>& aReturn
,
190 mozilla::ErrorResult
& aRv
);
192 void ScrollIntoView(int16_t aRegion
, bool aIsSynchronous
,
193 int16_t aVPercent
, int16_t aHPercent
,
194 mozilla::ErrorResult
& aRv
);
197 friend class ::nsAutoScrollTimer
;
199 // Note: DoAutoScroll might destroy arbitrary frames etc.
200 nsresult
DoAutoScroll(nsIFrame
*aFrame
, nsPoint
& aPoint
);
203 SelectionType
GetType(){return mType
;}
204 void SetType(SelectionType aType
){mType
= aType
;}
206 nsresult
NotifySelectionListeners();
210 class ScrollSelectionIntoViewEvent
;
211 friend class ScrollSelectionIntoViewEvent
;
213 class ScrollSelectionIntoViewEvent
: public nsRunnable
{
216 ScrollSelectionIntoViewEvent(Selection
* aSelection
,
217 SelectionRegion aRegion
,
218 nsIPresShell::ScrollAxis aVertical
,
219 nsIPresShell::ScrollAxis aHorizontal
,
221 : mSelection(aSelection
),
223 mVerticalScroll(aVertical
),
224 mHorizontalScroll(aHorizontal
),
226 NS_ASSERTION(aSelection
, "null parameter");
228 void Revoke() { mSelection
= nullptr; }
230 Selection
*mSelection
;
231 SelectionRegion mRegion
;
232 nsIPresShell::ScrollAxis mVerticalScroll
;
233 nsIPresShell::ScrollAxis mHorizontalScroll
;
237 void setAnchorFocusRange(int32_t aIndex
); // pass in index into mRanges;
238 // negative value clears
240 nsresult
SelectAllFramesForContent(nsIContentIterator
*aInnerIter
,
241 nsIContent
*aContent
,
243 nsresult
selectFrames(nsPresContext
* aPresContext
, nsRange
*aRange
, bool aSelect
);
244 nsresult
getTableCellLocationFromRange(nsRange
*aRange
, int32_t *aSelectionType
, int32_t *aRow
, int32_t *aCol
);
245 nsresult
addTableCellRange(nsRange
*aRange
, bool *aDidAddRange
, int32_t *aOutIndex
);
247 nsresult
FindInsertionPoint(
248 nsTArray
<RangeData
>* aElementArray
,
249 nsINode
* aPointNode
, int32_t aPointOffset
,
250 nsresult (*aComparator
)(nsINode
*,int32_t,nsRange
*,int32_t*),
252 bool EqualsRangeAtPoint(nsINode
* aBeginNode
, int32_t aBeginOffset
,
253 nsINode
* aEndNode
, int32_t aEndOffset
,
254 int32_t aRangeIndex
);
255 nsresult
GetIndicesForInterval(nsINode
* aBeginNode
, int32_t aBeginOffset
,
256 nsINode
* aEndNode
, int32_t aEndOffset
,
258 int32_t* aStartIndex
, int32_t* aEndIndex
);
259 RangeData
* FindRangeData(nsIDOMRange
* aRange
);
261 // These are the ranges inside this selection. They are kept sorted in order
262 // of DOM start position.
264 // This data structure is sorted by the range beginnings. As the ranges are
265 // disjoint, it is also implicitly sorted by the range endings. This allows
266 // us to perform binary searches when searching for existence of a range,
267 // giving us O(log n) search time.
269 // Inserting a new range requires finding the overlapping interval, requiring
270 // two binary searches plus up to an additional 6 DOM comparisons. If this
271 // proves to be a performance concern, then an interval tree may be a
272 // possible solution, allowing the calculation of the overlap interval in
273 // O(log n) time, though this would require rebalancing and other overhead.
274 nsTArray
<RangeData
> mRanges
;
276 nsRefPtr
<nsRange
> mAnchorFocusRange
;
277 nsRefPtr
<nsFrameSelection
> mFrameSelection
;
278 nsRefPtr
<nsAutoScrollTimer
> mAutoScrollTimer
;
279 nsCOMArray
<nsISelectionListener
> mSelectionListeners
;
280 nsRevocableEventPtr
<ScrollSelectionIntoViewEvent
> mScrollEvent
;
281 CachedOffsetForFrame
*mCachedOffsetForFrame
;
282 nsDirection mDirection
;
287 } // namespace mozilla
289 #endif // mozilla_Selection_h__