• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2004 Apple Computer, 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 "IntRect.h"
30 #include "Range.h"
31 #include "VisibleSelection.h"
32 #include <wtf/Noncopyable.h>
33 
34 namespace WebCore {
35 
36 class Frame;
37 class GraphicsContext;
38 class RenderObject;
39 class VisiblePosition;
40 
41 class SelectionController : public Noncopyable {
42 public:
43     enum EAlteration { MOVE, EXTEND };
44     enum EDirection { FORWARD, BACKWARD, RIGHT, LEFT };
45 
46     SelectionController(Frame* = 0, bool isDragCaretController = false);
47 
rootEditableElement()48     Element* rootEditableElement() const { return m_sel.rootEditableElement(); }
isContentEditable()49     bool isContentEditable() const { return m_sel.isContentEditable(); }
isContentRichlyEditable()50     bool isContentRichlyEditable() const { return m_sel.isContentRichlyEditable(); }
shadowTreeRootNode()51     Node* shadowTreeRootNode() const { return m_sel.shadowTreeRootNode(); }
52 
53     void moveTo(const Range*, EAffinity, bool userTriggered = false);
54     void moveTo(const VisiblePosition&, bool userTriggered = false);
55     void moveTo(const VisiblePosition&, const VisiblePosition&, bool userTriggered = false);
56     void moveTo(const Position&, EAffinity, bool userTriggered = false);
57     void moveTo(const Position&, const Position&, EAffinity, bool userTriggered = false);
58 
selection()59     const VisibleSelection& selection() const { return m_sel; }
60     void setSelection(const VisibleSelection&, bool closeTyping = true, bool clearTypingStyle = true, bool userTriggered = false);
61     bool setSelectedRange(Range*, EAffinity, bool closeTyping);
62     void selectAll();
63     void clear();
64 
65     // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
66     void selectFrameElementInParentIfFullySelected();
67 
68     bool contains(const IntPoint&);
69 
selectionType()70     VisibleSelection::SelectionType selectionType() const { return m_sel.selectionType(); }
71 
affinity()72     EAffinity affinity() const { return m_sel.affinity(); }
73 
74     bool modify(EAlteration, EDirection, TextGranularity, bool userTriggered = false);
75     bool modify(EAlteration, int verticalDistance, bool userTriggered = false);
76     bool expandUsingGranularity(TextGranularity);
77 
78     void setBase(const VisiblePosition&, bool userTriggered = false);
79     void setBase(const Position&, EAffinity, bool userTriggered = false);
80     void setExtent(const VisiblePosition&, bool userTriggered = false);
81     void setExtent(const Position&, EAffinity, bool userTriggered = false);
82 
base()83     Position base() const { return m_sel.base(); }
extent()84     Position extent() const { return m_sel.extent(); }
start()85     Position start() const { return m_sel.start(); }
end()86     Position end() const { return m_sel.end(); }
87 
88     // Return the renderer that is responsible for painting the caret (in the selection start node)
89     RenderObject* caretRenderer() const;
90 
91     // Caret rect local to the caret's renderer
92     IntRect localCaretRect() const;
93     // Bounds of (possibly transformed) caret in absolute coords
94     IntRect absoluteCaretBounds();
95     void setNeedsLayout(bool flag = true);
96 
setLastChangeWasHorizontalExtension(bool b)97     void setLastChangeWasHorizontalExtension(bool b) { m_lastChangeWasHorizontalExtension = b; }
98     void willBeModified(EAlteration, EDirection);
99 
isNone()100     bool isNone() const { return m_sel.isNone(); }
isCaret()101     bool isCaret() const { return m_sel.isCaret(); }
isRange()102     bool isRange() const { return m_sel.isRange(); }
isCaretOrRange()103     bool isCaretOrRange() const { return m_sel.isCaretOrRange(); }
104     bool isInPasswordField() const;
105     bool isAll(StayInEditableContent stayInEditableContent = MustStayInEditableContent) const { return m_sel.isAll(stayInEditableContent); }
106 
toNormalizedRange()107     PassRefPtr<Range> toNormalizedRange() const { return m_sel.toNormalizedRange(); }
108 
109     void debugRenderer(RenderObject*, bool selected) const;
110 
111     void nodeWillBeRemoved(Node*);
112 
113     bool recomputeCaretRect(); // returns true if caret rect moved
114     void invalidateCaretRect();
115     void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect);
116 
117     // Used to suspend caret blinking while the mouse is down.
setCaretBlinkingSuspended(bool suspended)118     void setCaretBlinkingSuspended(bool suspended) { m_isCaretBlinkingSuspended = suspended; }
isCaretBlinkingSuspended()119     bool isCaretBlinkingSuspended() const { return m_isCaretBlinkingSuspended; }
120 
121     // Focus
122     void setFocused(bool);
isFocused()123     bool isFocused() const { return m_focused; }
124     bool isFocusedAndActive() const;
125     void pageActivationChanged();
126 
127 #ifndef NDEBUG
128     void formatForDebugger(char* buffer, unsigned length) const;
129     void showTreeForThis() const;
130 #endif
131 
132 private:
133     enum EPositionType { START, END, BASE, EXTENT };
134 
135     TextDirection directionOfEnclosingBlock();
136 
137     VisiblePosition modifyExtendingRight(TextGranularity);
138     VisiblePosition modifyExtendingForward(TextGranularity);
139     VisiblePosition modifyMovingRight(TextGranularity);
140     VisiblePosition modifyMovingForward(TextGranularity);
141     VisiblePosition modifyExtendingLeft(TextGranularity);
142     VisiblePosition modifyExtendingBackward(TextGranularity);
143     VisiblePosition modifyMovingLeft(TextGranularity);
144     VisiblePosition modifyMovingBackward(TextGranularity);
145 
146     void layout();
147     IntRect caretRepaintRect() const;
148 
149     int xPosForVerticalArrowNavigation(EPositionType);
150 
151 #if PLATFORM(MAC) || PLATFORM(GTK)
152     void notifyAccessibilityForSelectionChange();
153 #else
notifyAccessibilityForSelectionChange()154     void notifyAccessibilityForSelectionChange() {};
155 #endif
156 
157     void focusedOrActiveStateChanged();
158     bool caretRendersInsideNode(Node*) const;
159 
160     IntRect absoluteBoundsForLocalRect(const IntRect&) const;
161 
162     Frame* m_frame;
163     int m_xPosForVerticalArrowNavigation;
164 
165     VisibleSelection m_sel;
166 
167     IntRect m_caretRect;        // caret rect in coords local to the renderer responsible for painting the caret
168     IntRect m_absCaretBounds;   // absolute bounding rect for the caret
169     IntRect m_absoluteCaretRepaintBounds;
170 
171     bool m_needsLayout : 1;       // true if the caret and expectedVisible rectangles need to be calculated
172     bool m_absCaretBoundsDirty: 1;
173     bool m_lastChangeWasHorizontalExtension : 1;
174     bool m_isDragCaretController : 1;
175     bool m_isCaretBlinkingSuspended : 1;
176     bool m_focused : 1;
177 
178 };
179 
180 inline bool operator==(const SelectionController& a, const SelectionController& b)
181 {
182     return a.start() == b.start() && a.end() == b.end() && a.affinity() == b.affinity();
183 }
184 
185 inline bool operator!=(const SelectionController& a, const SelectionController& b)
186 {
187     return !(a == b);
188 }
189 
190 } // namespace WebCore
191 
192 #ifndef NDEBUG
193 // Outside the WebCore namespace for ease of invocation from gdb.
194 void showTree(const WebCore::SelectionController&);
195 void showTree(const WebCore::SelectionController*);
196 #endif
197 
198 #endif // SelectionController_h
199 
200