Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / content / public / android / java / src / org / chromium / content / browser / input / SelectionHandleController.java
1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.content.browser.input;
6
7 import android.view.View;
8
9 import com.google.common.annotations.VisibleForTesting;
10
11 import org.chromium.content.browser.PositionObserver;
12
13 /**
14  * CursorController for selecting a range of text.
15  */
16 public abstract class SelectionHandleController implements CursorController {
17
18     // The following constants match the ones in
19     // third_party/WebKit/public/web/WebTextDirection.h
20     private static final int TEXT_DIRECTION_DEFAULT = 0;
21     private static final int TEXT_DIRECTION_LTR = 1;
22     private static final int TEXT_DIRECTION_RTL = 2;
23
24     /** The cursor controller images, lazily created when shown. */
25     private HandleView mStartHandle, mEndHandle;
26
27     /** Whether handles should show automatically when text is selected. */
28     private boolean mAllowAutomaticShowing = true;
29
30     /** Whether selection anchors are active. */
31     private boolean mIsShowing;
32
33     private View mParent;
34
35     private int mFixedHandleX;
36     private int mFixedHandleY;
37
38     private PositionObserver mPositionObserver;
39
40     public SelectionHandleController(View parent, PositionObserver positionObserver) {
41         mParent = parent;
42         mPositionObserver = positionObserver;
43     }
44
45     /** Automatically show selection anchors when text is selected. */
46     public void allowAutomaticShowing() {
47         mAllowAutomaticShowing = true;
48     }
49
50     /** Hide selection anchors, and don't automatically show them. */
51     public void hideAndDisallowAutomaticShowing() {
52         hide();
53         mAllowAutomaticShowing = false;
54     }
55
56     @Override
57     public boolean isShowing() {
58         return mIsShowing;
59     }
60
61     @Override
62     public void hide() {
63         if (mIsShowing) {
64             if (mStartHandle != null) mStartHandle.hide();
65             if (mEndHandle != null) mEndHandle.hide();
66             mIsShowing = false;
67         }
68     }
69
70     void cancelFadeOutAnimation() {
71         hide();
72     }
73
74     /**
75      * Updates the selection for a movement of the given handle (which
76      * should be the start handle or end handle) to coordinates x,y.
77      * Note that this will not actually result in the handle moving to (x,y):
78      * selectBetweenCoordinates(x1,y1,x2,y2) will trigger the selection and set the
79      * actual coordinates later via set[Start|End]HandlePosition.
80      */
81     @Override
82     public void updatePosition(HandleView handle, int x, int y) {
83         selectBetweenCoordinates(mFixedHandleX, mFixedHandleY, x, y);
84     }
85
86     @Override
87     public void beforeStartUpdatingPosition(HandleView handle) {
88         HandleView fixedHandle = (handle == mStartHandle) ? mEndHandle : mStartHandle;
89         mFixedHandleX = fixedHandle.getAdjustedPositionX();
90         mFixedHandleY = fixedHandle.getLineAdjustedPositionY();
91     }
92
93     /**
94      * The concrete implementation must trigger a selection between the given
95      * coordinates and (possibly asynchronously) set the actual handle positions
96      * after the selection is made via set[Start|End]HandlePosition.
97      */
98     protected abstract void selectBetweenCoordinates(int x1, int y1, int x2, int y2);
99
100     /**
101      * @return true iff this controller is being used to move the selection start.
102      */
103     boolean isSelectionStartDragged() {
104         return mStartHandle != null && mStartHandle.isDragging();
105     }
106
107     /**
108      * @return true iff this controller is being used to drag either the selection start or end.
109      */
110     public boolean isDragging() {
111         return (mStartHandle != null && mStartHandle.isDragging()) ||
112                (mEndHandle != null && mEndHandle.isDragging());
113     }
114
115     @Override
116     public void onTouchModeChanged(boolean isInTouchMode) {
117         if (!isInTouchMode) {
118             hide();
119         }
120     }
121
122     @Override
123     public void onDetached() {}
124
125     /**
126      * Moves the start handle so that it points at the given coordinates.
127      * @param x The start handle position X in physical pixels.
128      * @param y The start handle position Y in physical pixels.
129      */
130     public void setStartHandlePosition(float x, float y) {
131         mStartHandle.positionAt((int) x, (int) y);
132     }
133
134     /**
135      * Moves the end handle so that it points at the given coordinates.
136      * @param x The end handle position X in physical pixels.
137      * @param y The end handle position Y in physical pixels.
138      */
139     public void setEndHandlePosition(float x, float y) {
140         mEndHandle.positionAt((int) x, (int) y);
141     }
142
143     /**
144      * If the handles are not visible, sets their visibility to View.VISIBLE and begins fading them
145      * in.
146      */
147     public void beginHandleFadeIn() {
148         mStartHandle.beginFadeIn();
149         mEndHandle.beginFadeIn();
150     }
151
152     /**
153      * Sets the start and end handles to the given visibility.
154      */
155     public void setHandleVisibility(int visibility) {
156         mStartHandle.setVisibility(visibility);
157         mEndHandle.setVisibility(visibility);
158     }
159
160     /**
161      * Shows the handles if allowed.
162      *
163      * @param startDir Direction (left/right) of start handle.
164      * @param endDir Direction (left/right) of end handle.
165      */
166     public void onSelectionChanged(int startDir, int endDir) {
167         if (mAllowAutomaticShowing) {
168             showHandles(startDir, endDir);
169         }
170     }
171
172     /**
173      * Sets both start and end position and show the handles.
174      * Note: this method does not trigger a selection, see
175      * selectBetweenCoordinates()
176      *
177      * @param startDir Direction (left/right) of start handle.
178      * @param endDir Direction (left/right) of end handle.
179      */
180     public void showHandles(int startDir, int endDir) {
181         createHandlesIfNeeded(startDir, endDir);
182         showHandlesIfNeeded();
183     }
184
185     @VisibleForTesting
186     public HandleView getStartHandleViewForTest() {
187         return mStartHandle;
188     }
189
190     @VisibleForTesting
191     public HandleView getEndHandleViewForTest() {
192         return mEndHandle;
193     }
194
195     private void createHandlesIfNeeded(int startDir, int endDir) {
196         if (mStartHandle == null) {
197             mStartHandle = new HandleView(this,
198                     startDir == TEXT_DIRECTION_RTL ? HandleView.RIGHT : HandleView.LEFT, mParent,
199                     mPositionObserver);
200         }
201         if (mEndHandle == null) {
202             mEndHandle = new HandleView(this,
203                     endDir == TEXT_DIRECTION_RTL ? HandleView.LEFT : HandleView.RIGHT, mParent,
204                     mPositionObserver);
205         }
206     }
207
208     private void showHandlesIfNeeded() {
209         if (!mIsShowing) {
210             mIsShowing = true;
211             mStartHandle.show();
212             mEndHandle.show();
213             setHandleVisibility(HandleView.VISIBLE);
214         }
215     }
216 }