Bumping manifests a=b2g-bump
[gecko.git] / layout / generic / Selection.h
blob12d63624a90de0ebb0f1213d07c87d9c465c47cc
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;
31 struct RangeData
33 explicit RangeData(nsRange* aRange)
34 : mRange(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.
46 namespace mozilla {
47 namespace dom {
49 class Selection MOZ_FINAL : public nsISelectionPrivate,
50 public nsWrapperCache,
51 public nsSupportsWeakReference
53 protected:
54 virtual ~Selection();
56 public:
57 Selection();
58 explicit Selection(nsFrameSelection *aList);
60 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
61 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(Selection, nsISelectionPrivate)
62 NS_DECL_NSISELECTION
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
75 // region rects.
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,
84 int32_t aFlags,
85 nsIPresShell::ScrollAxis aVertical,
86 nsIPresShell::ScrollAxis aHorizontal);
87 enum {
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(),
100 int32_t aFlags = 0);
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,
132 nsPoint& aPoint,
133 uint32_t aDelay);
135 nsresult StopAutoScrollTimer();
137 JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE;
139 // WebIDL methods
140 nsINode* GetAnchorNode();
141 uint32_t AnchorOffset();
142 nsINode* GetFocusNode();
143 uint32_t FocusOffset();
145 bool IsCollapsed();
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,
175 uint32_t aFlags,
176 int32_t aWrapColumn,
177 nsAString& aReturn,
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,
188 bool aAllowAdjacent,
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);
196 private:
197 friend class ::nsAutoScrollTimer;
199 // Note: DoAutoScroll might destroy arbitrary frames etc.
200 nsresult DoAutoScroll(nsIFrame *aFrame, nsPoint& aPoint);
202 public:
203 SelectionType GetType(){return mType;}
204 void SetType(SelectionType aType){mType = aType;}
206 nsresult NotifySelectionListeners();
208 private:
210 class ScrollSelectionIntoViewEvent;
211 friend class ScrollSelectionIntoViewEvent;
213 class ScrollSelectionIntoViewEvent : public nsRunnable {
214 public:
215 NS_DECL_NSIRUNNABLE
216 ScrollSelectionIntoViewEvent(Selection* aSelection,
217 SelectionRegion aRegion,
218 nsIPresShell::ScrollAxis aVertical,
219 nsIPresShell::ScrollAxis aHorizontal,
220 int32_t aFlags)
221 : mSelection(aSelection),
222 mRegion(aRegion),
223 mVerticalScroll(aVertical),
224 mHorizontalScroll(aHorizontal),
225 mFlags(aFlags) {
226 NS_ASSERTION(aSelection, "null parameter");
228 void Revoke() { mSelection = nullptr; }
229 private:
230 Selection *mSelection;
231 SelectionRegion mRegion;
232 nsIPresShell::ScrollAxis mVerticalScroll;
233 nsIPresShell::ScrollAxis mHorizontalScroll;
234 int32_t mFlags;
237 void setAnchorFocusRange(int32_t aIndex); // pass in index into mRanges;
238 // negative value clears
239 // mAnchorFocusRange
240 nsresult SelectAllFramesForContent(nsIContentIterator *aInnerIter,
241 nsIContent *aContent,
242 bool aSelected);
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*),
251 int32_t* aPoint);
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,
257 bool aAllowAdjacent,
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;
283 SelectionType mType;
286 } // namespace dom
287 } // namespace mozilla
289 #endif // mozilla_Selection_h__