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