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 "EditingStyle.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 CharacterData;
     40 class CSSMutableStyleDeclaration;
     41 class Frame;
     42 class GraphicsContext;
     43 class HTMLFormElement;
     44 class RenderObject;
     45 class RenderView;
     46 class Settings;
     47 class VisiblePosition;
     48 
     49 enum DirectionalityPolicy { MakeNonDirectionalSelection, MakeDirectionalSelection };
     50 
     51 class SelectionController {
     52     WTF_MAKE_NONCOPYABLE(SelectionController); WTF_MAKE_FAST_ALLOCATED;
     53 public:
     54     enum EAlteration { AlterationMove, AlterationExtend };
     55     enum CursorAlignOnScroll { AlignCursorOnScrollIfNeeded,
     56                                AlignCursorOnScrollAlways };
     57     enum SetSelectionOption {
     58         CloseTyping = 1 << 0,
     59         ClearTypingStyle = 1 << 1,
     60         UserTriggered = 1 << 2,
     61         SpellCorrectionTriggered = 1 << 3,
     62     };
     63     typedef unsigned SetSelectionOptions;
     64 
     65     SelectionController(Frame* = 0, bool isDragCaretController = false);
     66 
     67     Element* rootEditableElement() const { return m_selection.rootEditableElement(); }
     68     bool isContentEditable() const { return m_selection.isContentEditable(); }
     69     bool isContentRichlyEditable() const { return m_selection.isContentRichlyEditable(); }
     70     Node* shadowTreeRootNode() const { return m_selection.shadowTreeRootNode(); }
     71 
     72     void moveTo(const Range*, EAffinity, bool userTriggered = false);
     73     void moveTo(const VisiblePosition&, bool userTriggered = false, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded);
     74     void moveTo(const VisiblePosition&, const VisiblePosition&, bool userTriggered = false);
     75     void moveTo(const Position&, EAffinity, bool userTriggered = false);
     76     void moveTo(const Position&, const Position&, EAffinity, bool userTriggered = false);
     77 
     78     const VisibleSelection& selection() const { return m_selection; }
     79     void setSelection(const VisibleSelection&, SetSelectionOptions = CloseTyping | ClearTypingStyle, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded, TextGranularity = CharacterGranularity, DirectionalityPolicy = MakeDirectionalSelection);
     80     void setSelection(const VisibleSelection& selection, TextGranularity granularity, DirectionalityPolicy directionality = MakeDirectionalSelection) { setSelection(selection, CloseTyping | ClearTypingStyle, AlignCursorOnScrollIfNeeded, granularity, directionality); }
     81     bool setSelectedRange(Range*, EAffinity, bool closeTyping);
     82     void selectAll();
     83     void clear();
     84 
     85     // Call this after doing user-triggered selections to make it easy to delete the frame you entirely selected.
     86     void selectFrameElementInParentIfFullySelected();
     87 
     88     bool contains(const IntPoint&);
     89 
     90     VisibleSelection::SelectionType selectionType() const { return m_selection.selectionType(); }
     91 
     92     EAffinity affinity() const { return m_selection.affinity(); }
     93 
     94     bool modify(EAlteration, SelectionDirection, TextGranularity, bool userTriggered = false);
     95     bool modify(EAlteration, int verticalDistance, bool userTriggered = false, CursorAlignOnScroll = AlignCursorOnScrollIfNeeded);
     96     TextGranularity granularity() const { return m_granularity; }
     97 
     98     void setStart(const VisiblePosition &, bool userTriggered = false);
     99     void setEnd(const VisiblePosition &, bool userTriggered = false);
    100 
    101     void setBase(const VisiblePosition&, bool userTriggered = false);
    102     void setBase(const Position&, EAffinity, bool userTriggered = false);
    103     void setExtent(const VisiblePosition&, bool userTriggered = false);
    104     void setExtent(const Position&, EAffinity, bool userTriggered = false);
    105 
    106     Position base() const { return m_selection.base(); }
    107     Position extent() const { return m_selection.extent(); }
    108     Position start() const { return m_selection.start(); }
    109     Position end() const { return m_selection.end(); }
    110 
    111     // Return the renderer that is responsible for painting the caret (in the selection start node)
    112     RenderObject* caretRenderer() const;
    113 
    114     // Caret rect local to the caret's renderer
    115     IntRect localCaretRect();
    116     IntRect localCaretRectForPainting() const { return m_caretRect; }
    117 
    118     // Bounds of (possibly transformed) caret in absolute coords
    119     IntRect absoluteCaretBounds();
    120     void setCaretRectNeedsUpdate(bool flag = true);
    121 
    122     void setIsDirectional(bool);
    123     void willBeModified(EAlteration, SelectionDirection);
    124 
    125     bool isNone() const { return m_selection.isNone(); }
    126     bool isCaret() const { return m_selection.isCaret(); }
    127     bool isRange() const { return m_selection.isRange(); }
    128     bool isCaretOrRange() const { return m_selection.isCaretOrRange(); }
    129     bool isInPasswordField() const;
    130     bool isAll(EditingBoundaryCrossingRule rule = CannotCrossEditingBoundary) const { return m_selection.isAll(rule); }
    131 
    132     PassRefPtr<Range> toNormalizedRange() const { return m_selection.toNormalizedRange(); }
    133 
    134     void debugRenderer(RenderObject*, bool selected) const;
    135 
    136     void nodeWillBeRemoved(Node*);
    137     void textWillBeReplaced(CharacterData*, unsigned offset, unsigned oldLength, unsigned newLength);
    138 
    139     void setCaretVisible(bool = true);
    140     void clearCaretRectIfNeeded();
    141     bool recomputeCaretRect(); // returns true if caret rect moved
    142     void invalidateCaretRect();
    143     void paintCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect);
    144 
    145     // Used to suspend caret blinking while the mouse is down.
    146     void setCaretBlinkingSuspended(bool suspended) { m_isCaretBlinkingSuspended = suspended; }
    147     bool isCaretBlinkingSuspended() const { return m_isCaretBlinkingSuspended; }
    148 
    149     // Focus
    150     void setFocused(bool);
    151     bool isFocused() const { return m_focused; }
    152     bool isFocusedAndActive() const;
    153     void pageActivationChanged();
    154 
    155     // Painting.
    156     void updateAppearance();
    157 
    158     void updateSecureKeyboardEntryIfActive();
    159 
    160 #ifndef NDEBUG
    161     void formatForDebugger(char* buffer, unsigned length) const;
    162     void showTreeForThis() const;
    163 #endif
    164 
    165     bool shouldChangeSelection(const VisibleSelection&) const;
    166     bool shouldDeleteSelection(const VisibleSelection&) const;
    167     void setFocusedNodeIfNeeded();
    168     void notifyRendererOfSelectionChange(bool userTriggered);
    169 
    170     void paintDragCaret(GraphicsContext*, int tx, int ty, const IntRect& clipRect) const;
    171 
    172     EditingStyle* typingStyle() const;
    173     PassRefPtr<CSSMutableStyleDeclaration> copyTypingStyle() const;
    174     void setTypingStyle(PassRefPtr<EditingStyle>);
    175     void clearTypingStyle();
    176 
    177     FloatRect bounds(bool clipToVisibleContent = true) const;
    178 
    179     void getClippedVisibleTextRectangles(Vector<FloatRect>&) const;
    180 
    181     HTMLFormElement* currentForm() const;
    182 
    183     void revealSelection(const ScrollAlignment& = ScrollAlignment::alignCenterIfNeeded, bool revealExtent = false);
    184     void setSelectionFromNone();
    185 
    186 private:
    187     enum EPositionType { START, END, BASE, EXTENT };
    188 
    189     void respondToNodeModification(Node*, bool baseRemoved, bool extentRemoved, bool startRemoved, bool endRemoved);
    190     TextDirection directionOfEnclosingBlock();
    191 
    192     VisiblePosition positionForPlatform(bool isGetStart) const;
    193     VisiblePosition startForPlatform() const;
    194     VisiblePosition endForPlatform() const;
    195 
    196     VisiblePosition modifyExtendingRight(TextGranularity);
    197     VisiblePosition modifyExtendingForward(TextGranularity);
    198     VisiblePosition modifyMovingRight(TextGranularity);
    199     VisiblePosition modifyMovingForward(TextGranularity);
    200     VisiblePosition modifyExtendingLeft(TextGranularity);
    201     VisiblePosition modifyExtendingBackward(TextGranularity);
    202     VisiblePosition modifyMovingLeft(TextGranularity);
    203     VisiblePosition modifyMovingBackward(TextGranularity);
    204 
    205     void updateCaretRect();
    206     IntRect caretRepaintRect() const;
    207     bool shouldRepaintCaret(const RenderView* view) const;
    208 
    209     int xPosForVerticalArrowNavigation(EPositionType);
    210 
    211     void notifyAccessibilityForSelectionChange();
    212 
    213     void focusedOrActiveStateChanged();
    214     bool caretRendersInsideNode(Node*) const;
    215 
    216     IntRect absoluteBoundsForLocalRect(const IntRect&) const;
    217 
    218     void caretBlinkTimerFired(Timer<SelectionController>*);
    219 
    220     void setUseSecureKeyboardEntry(bool);
    221 
    222     Frame* m_frame;
    223 
    224     int m_xPosForVerticalArrowNavigation;
    225 
    226     VisibleSelection m_selection;
    227     TextGranularity m_granularity;
    228 
    229     RefPtr<EditingStyle> m_typingStyle;
    230 
    231     Timer<SelectionController> m_caretBlinkTimer;
    232 
    233     IntRect m_caretRect; // caret rect in coords local to the renderer responsible for painting the caret
    234     IntRect m_absCaretBounds; // absolute bounding rect for the caret
    235     IntRect m_absoluteCaretRepaintBounds;
    236 
    237     bool m_caretRectNeedsUpdate; // true if m_caretRect and m_absCaretBounds need to be calculated
    238     bool m_absCaretBoundsDirty;
    239     bool m_isDirectional;
    240     bool m_isDragCaretController;
    241     bool m_isCaretBlinkingSuspended;
    242     bool m_focused;
    243     bool m_caretVisible;
    244     bool m_caretPaint;
    245 };
    246 
    247 inline EditingStyle* SelectionController::typingStyle() const
    248 {
    249     return m_typingStyle.get();
    250 }
    251 
    252 inline void SelectionController::clearTypingStyle()
    253 {
    254     m_typingStyle.clear();
    255 }
    256 
    257 inline void SelectionController::setTypingStyle(PassRefPtr<EditingStyle> style)
    258 {
    259     m_typingStyle = style;
    260 }
    261 
    262 #if !(PLATFORM(MAC) || PLATFORM(GTK) || PLATFORM(CHROMIUM))
    263 inline void SelectionController::notifyAccessibilityForSelectionChange()
    264 {
    265 }
    266 #endif
    267 
    268 } // namespace WebCore
    269 
    270 #ifndef NDEBUG
    271 // Outside the WebCore namespace for ease of invocation from gdb.
    272 void showTree(const WebCore::SelectionController&);
    273 void showTree(const WebCore::SelectionController*);
    274 #endif
    275 
    276 #endif // SelectionController_h
    277 
    278