2010-09-09 Darin Adler <darin@apple.com>
[WebKit-https.git] / WebCore / editing / SelectionController.h
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef SelectionController_h
27 #define SelectionController_h
28
29 #include "CSSMutableStyleDeclaration.h"
30 #include "IntRect.h"
31 #include "Range.h"
32 #include "ScrollBehavior.h"
33 #include "Timer.h"
34 #include "VisibleSelection.h"
35 #include <wtf/Noncopyable.h>
36
37 namespace WebCore {
38
39 class Frame;
40 class GraphicsContext;
41 class HTMLFormElement;
42 class RenderObject;
43 class RenderView;
44 class Settings;
45 class VisiblePosition;
46
47 enum DirectionalityPolicy { MakeNonDirectionalSelection, MakeDirectionalSelection };
48
49 class SelectionController : public Noncopyable {
50 public:
51     enum EAlteration { AlterationMove, AlterationExtend };
52     enum EDirection { DirectionForward, DirectionBackward, DirectionRight, DirectionLeft };
53     enum CursorAlignOnScroll { AlignCursorOnScrollIfNeeded,
54                                AlignCursorOnScrollAlways };
55
56     SelectionController(Frame* = 0, bool isDragCaretController = false);
57
58     Element* rootEditableElement() const { return m_selection.rootEditableElement(); }
59     bool isContentEditable() const { return m_selection.isContentEditable(); }
60     bool isContentRichlyEditable() const { return m_selection.isContentRichlyEditable(); }
61     Node* shadowTreeRootNode() const { return m_selection.shadowTreeRootNode(); }
62      
63     void moveTo(const Range*, EAffinity, bool userTriggered = false);
64     void moveTo(const VisiblePosition&, bool userTriggered = false, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded);
65     void moveTo(const VisiblePosition&, const VisiblePosition&, bool userTriggered = false);
66     void moveTo(const Position&, EAffinity, bool userTriggered = false);
67     void moveTo(const Position&, const Position&, EAffinity, bool userTriggered = false);
68
69     const VisibleSelection& selection() const { return m_selection; }
70     void setSelection(const VisibleSelection&, bool closeTyping = true, bool clearTypingStyle = true, bool userTriggered = false, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded, TextGranularity = CharacterGranularity, DirectionalityPolicy = MakeDirectionalSelection);
71     void setSelection(const VisibleSelection& selection, TextGranularity granularity, DirectionalityPolicy directionality = MakeDirectionalSelection) { setSelection(selection, true, true, false, AlignCursorOnScrollIfNeeded, granularity, directionality); }
72     bool setSelectedRange(Range*, EAffinity, bool closeTyping);
73     void selectAll();
74     void clear();
75     
76     // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
77     void selectFrameElementInParentIfFullySelected();
78
79     bool contains(const IntPoint&);
80
81     VisibleSelection::SelectionType selectionType() const { return m_selection.selectionType(); }
82
83     EAffinity affinity() const { return m_selection.affinity(); }
84
85     bool modify(EAlteration, EDirection, TextGranularity, bool userTriggered = false);
86     bool modify(EAlteration, int verticalDistance, bool userTriggered = false, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded);
87     TextGranularity granularity() const { return m_granularity; }
88
89     void setStart(const VisiblePosition &, bool userTriggered = false);
90     void setEnd(const VisiblePosition &, bool userTriggered = false);
91     
92     void setBase(const VisiblePosition&, bool userTriggered = false);
93     void setBase(const Position&, EAffinity, bool userTriggered = false);
94     void setExtent(const VisiblePosition&, bool userTriggered = false);
95     void setExtent(const Position&, EAffinity, bool userTriggered = false);
96
97     Position base() const { return m_selection.base(); }
98     Position extent() const { return m_selection.extent(); }
99     Position start() const { return m_selection.start(); }
100     Position end() const { return m_selection.end(); }
101
102     // Return the renderer that is responsible for painting the caret (in the selection start node)
103     RenderObject* caretRenderer() const;
104
105     // Caret rect local to the caret's renderer
106     IntRect localCaretRect();
107     IntRect localCaretRectForPainting() const { return m_caretRect; }
108
109     // Bounds of (possibly transformed) caret in absolute coords
110     IntRect absoluteCaretBounds();
111     void setCaretRectNeedsUpdate(bool flag = true);
112
113     void setIsDirectional(bool);
114     void willBeModified(EAlteration, EDirection);
115     
116     bool isNone() const { return m_selection.isNone(); }
117     bool isCaret() const { return m_selection.isCaret(); }
118     bool isRange() const { return m_selection.isRange(); }
119     bool isCaretOrRange() const { return m_selection.isCaretOrRange(); }
120     bool isInPasswordField() const;
121     bool isAll(StayInEditableContent stayInEditableContent = MustStayInEditableContent) const { return m_selection.isAll(stayInEditableContent); }
122     
123     PassRefPtr<Range> toNormalizedRange() const { return m_selection.toNormalizedRange(); }
124
125     void debugRenderer(RenderObject*, bool selected) const;
126     
127     void nodeWillBeRemoved(Node*);
128
129     void setCaretVisible(bool = true);
130     void clearCaretRectIfNeeded();
131     bool recomputeCaretRect(); // returns true if caret rect moved
132     void invalidateCaretRect();
133     void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect);
134
135     // Used to suspend caret blinking while the mouse is down.
136     void setCaretBlinkingSuspended(bool suspended) { m_isCaretBlinkingSuspended = suspended; }
137     bool isCaretBlinkingSuspended() const { return m_isCaretBlinkingSuspended; }
138
139     // Focus
140     void setFocused(bool);
141     bool isFocused() const { return m_focused; }
142     bool isFocusedAndActive() const;
143     void pageActivationChanged();
144
145     // Painting.
146     void updateAppearance();
147
148     void updateSecureKeyboardEntryIfActive();
149
150 #ifndef NDEBUG
151     void formatForDebugger(char* buffer, unsigned length) const;
152     void showTreeForThis() const;
153 #endif
154
155     bool shouldChangeSelection(const VisibleSelection&) const;
156     bool shouldDeleteSelection(const VisibleSelection&) const;
157     void setFocusedNodeIfNeeded();
158     void notifyRendererOfSelectionChange(bool userTriggered);
159
160     void paintDragCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
161
162     CSSMutableStyleDeclaration* typingStyle() const;
163     void setTypingStyle(PassRefPtr<CSSMutableStyleDeclaration>);
164     void clearTypingStyle();
165
166     FloatRect bounds(bool clipToVisibleContent = true) const;
167
168     void getClippedVisibleTextRectangles(Vector<FloatRect>&) const;
169
170     HTMLFormElement* currentForm() const;
171
172     void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, bool revealExtent = false);
173     void setSelectionFromNone();
174
175 private:
176     enum EPositionType { START, END, BASE, EXTENT };
177
178     TextDirection directionOfEnclosingBlock();
179
180     VisiblePosition positionForPlatform(bool isGetStart) const;
181     VisiblePosition startForPlatform() const;
182     VisiblePosition endForPlatform() const;
183
184     bool modify(EAlteration, EDirection, TextGranularity, bool userTriggered, Settings*);
185
186     VisiblePosition modifyExtendingRight(TextGranularity);
187     VisiblePosition modifyExtendingForward(TextGranularity);
188     VisiblePosition modifyMovingRight(TextGranularity);
189     VisiblePosition modifyMovingForward(TextGranularity);
190     VisiblePosition modifyExtendingLeft(TextGranularity);
191     VisiblePosition modifyExtendingBackward(TextGranularity);
192     VisiblePosition modifyMovingLeft(TextGranularity);
193     VisiblePosition modifyMovingBackward(TextGranularity);
194
195     void updateCaretRect();
196     IntRect caretRepaintRect() const;
197     bool shouldRepaintCaret(const RenderView* view) const;
198
199     int xPosForVerticalArrowNavigation(EPositionType);
200     
201     void notifyAccessibilityForSelectionChange();
202
203     void focusedOrActiveStateChanged();
204     bool caretRendersInsideNode(Node*) const;
205     
206     IntRect absoluteBoundsForLocalRect(const IntRect&) const;
207
208     void caretBlinkTimerFired(Timer<SelectionController>*);
209
210     void setUseSecureKeyboardEntry(bool);
211
212     Frame* m_frame;
213
214     int m_xPosForVerticalArrowNavigation;
215
216     VisibleSelection m_selection;
217     TextGranularity m_granularity;
218
219     RefPtr<CSSMutableStyleDeclaration> m_typingStyle;
220
221     Timer<SelectionController> m_caretBlinkTimer;
222
223     IntRect m_caretRect; // caret rect in coords local to the renderer responsible for painting the caret
224     IntRect m_absCaretBounds; // absolute bounding rect for the caret
225     IntRect m_absoluteCaretRepaintBounds;
226     
227     bool m_caretRectNeedsUpdate; // true if m_caretRect and m_absCaretBounds need to be calculated
228     bool m_absCaretBoundsDirty;
229     bool m_isDirectional;
230     bool m_isDragCaretController;
231     bool m_isCaretBlinkingSuspended;
232     bool m_focused;
233     bool m_caretVisible;
234     bool m_caretPaint;
235 };
236
237 inline CSSMutableStyleDeclaration* SelectionController::typingStyle() const
238 {
239     return m_typingStyle.get();
240 }
241
242 inline void SelectionController::clearTypingStyle()
243 {
244     m_typingStyle.clear();
245 }
246
247 inline void SelectionController::setTypingStyle(PassRefPtr<CSSMutableStyleDeclaration> style)
248 {
249     m_typingStyle = style;
250 }
251
252 #if !(PLATFORM(MAC) || PLATFORM(GTK))
253 inline void SelectionController::notifyAccessibilityForSelectionChange()
254 {
255 }
256 #endif
257
258 } // namespace WebCore
259
260 #ifndef NDEBUG
261 // Outside the WebCore namespace for ease of invocation from gdb.
262 void showTree(const WebCore::SelectionController&);
263 void showTree(const WebCore::SelectionController*);
264 #endif
265
266 #endif // SelectionController_h
267