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 "Selection.h" 31 #include "Range.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 : 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 Selection& selection() const { return m_sel; } 60 void setSelection(const Selection&, 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 state()70 Selection::EState state() const { return m_sel.state(); } 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 toRange()106 PassRefPtr<Range> toRange() const { return m_sel.toRange(); } 107 108 void debugRenderer(RenderObject*, bool selected) const; 109 110 void nodeWillBeRemoved(Node*); 111 112 bool recomputeCaretRect(); // returns true if caret rect moved 113 void invalidateCaretRect(); 114 void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect); 115 116 // Used to suspend caret blinking while the mouse is down. setCaretBlinkingSuspended(bool suspended)117 void setCaretBlinkingSuspended(bool suspended) { m_isCaretBlinkingSuspended = suspended; } isCaretBlinkingSuspended()118 bool isCaretBlinkingSuspended() const { return m_isCaretBlinkingSuspended; } 119 120 // Focus 121 void setFocused(bool); 122 bool isFocusedAndActive() const; 123 void pageActivationChanged(); 124 125 #ifndef NDEBUG 126 void formatForDebugger(char* buffer, unsigned length) const; 127 void showTreeForThis() const; 128 #endif 129 130 private: 131 enum EPositionType { START, END, BASE, EXTENT }; 132 133 VisiblePosition modifyExtendingRightForward(TextGranularity); 134 VisiblePosition modifyMovingRight(TextGranularity); 135 VisiblePosition modifyMovingForward(TextGranularity); 136 VisiblePosition modifyExtendingLeftBackward(TextGranularity); 137 VisiblePosition modifyMovingLeft(TextGranularity); 138 VisiblePosition modifyMovingBackward(TextGranularity); 139 140 void layout(); 141 IntRect caretRepaintRect() const; 142 143 int xPosForVerticalArrowNavigation(EPositionType); 144 145 #if PLATFORM(MAC) 146 void notifyAccessibilityForSelectionChange(); 147 #else notifyAccessibilityForSelectionChange()148 void notifyAccessibilityForSelectionChange() {}; 149 #endif 150 151 void focusedOrActiveStateChanged(); 152 bool caretRendersInsideNode(Node*) const; 153 154 Frame* m_frame; 155 int m_xPosForVerticalArrowNavigation; 156 157 Selection m_sel; 158 159 IntRect m_caretRect; // caret rect in coords local to the renderer responsible for painting the caret 160 IntRect m_absCaretBounds; // absolute bounding rect for the caret 161 162 bool m_needsLayout : 1; // true if the caret and expectedVisible rectangles need to be calculated 163 bool m_absCaretBoundsDirty: 1; 164 bool m_lastChangeWasHorizontalExtension : 1; 165 bool m_isDragCaretController : 1; 166 bool m_isCaretBlinkingSuspended : 1; 167 bool m_focused : 1; 168 169 }; 170 171 inline bool operator==(const SelectionController& a, const SelectionController& b) 172 { 173 return a.start() == b.start() && a.end() == b.end() && a.affinity() == b.affinity(); 174 } 175 176 inline bool operator!=(const SelectionController& a, const SelectionController& b) 177 { 178 return !(a == b); 179 } 180 181 } // namespace WebCore 182 183 #ifndef NDEBUG 184 // Outside the WebCore namespace for ease of invocation from gdb. 185 void showTree(const WebCore::SelectionController&); 186 void showTree(const WebCore::SelectionController*); 187 #endif 188 189 #endif // SelectionController_h 190