Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(323)

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/PopupTouchHandleDrawable.java

Issue 335943002: [Android] Composited selection handle rendering (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@input_native_handles_final
Patch Set: Fix animation tests Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.content.Context;
8 import android.graphics.Canvas;
9 import android.graphics.drawable.Drawable;
10 import android.view.MotionEvent;
11 import android.view.View;
12 import android.widget.PopupWindow;
13
14 import org.chromium.base.CalledByNative;
15 import org.chromium.base.JNINamespace;
16 import org.chromium.content.browser.PositionObserver;
17
18 import java.lang.ref.WeakReference;
19
20 /**
21 * View that displays a selection or insertion handle for text editing.
22 *
23 * While a HandleView is logically a child of some other view, it does not exist in that View's
24 * hierarchy.
25 *
26 */
27 @JNINamespace("content")
28 public class PopupTouchHandleDrawable extends View {
29 private Drawable mDrawable;
30 private final PopupWindow mContainer;
31 private final Context mContext;
32 private final PositionObserver.Listener mParentPositionListener;
33
34 // The weak delegate reference allows the PopupTouchHandleDrawable to be own ed by a native
35 // object that might have a different lifetime (or a cyclic lifetime) with r espect to the
36 // delegate, allowing garbage collection of any Java references.
37 private final WeakReference<PopupTouchHandleDrawableDelegate> mDelegate;
38
39 // The observer reference will only be non-null while it is attached to mPar entPositionListener.
40 private PositionObserver mParentPositionObserver;
41
42 // The position of the handle relative to the parent view.
43 private int mPositionX;
44 private int mPositionY;
45
46 // The position of the parent relative to the application's root view.
47 private int mParentPositionX;
48 private int mParentPositionY;
49
50 // The offset from this handles position to the "tip" of the handle.
51 private float mHotspotX;
52 private float mHotspotY;
53
54 private float mAlpha;
55
56 private final int[] mTempScreenCoords = new int[2];
57
58 static final int LEFT = 0;
59 static final int CENTER = 1;
60 static final int RIGHT = 2;
61 private int mOrientation = -1;
62
63 /**
64 * Provides additional interaction behaviors necessary for handle
65 * manipulation and interaction.
66 */
67 public interface PopupTouchHandleDrawableDelegate {
68 /**
69 * @return The parent View of the PopupWindow.
70 */
71 View getParent();
72
73 /**
74 * @return A position observer for the parent View, used to keep the
75 * absolutely positioned PopupWindow in-sync with the parent.
76 */
77 PositionObserver getParentPositionObserver();
78
79 /**
80 * Should route MotionEvents to the appropriate logic layer for
81 * performing handle manipulation.
82 */
83 boolean onTouchHandleEvent(MotionEvent ev);
84 }
85
86 public PopupTouchHandleDrawable(PopupTouchHandleDrawableDelegate delegate) {
87 super(delegate.getParent().getContext());
88 mContext = delegate.getParent().getContext();
89 mDelegate = new WeakReference<PopupTouchHandleDrawableDelegate>(delegate );
90 mContainer = new PopupWindow(mContext, null, android.R.attr.textSelectHa ndleWindowStyle);
91 mContainer.setSplitTouchEnabled(true);
92 mContainer.setClippingEnabled(false);
93 mAlpha = 1.f;
94 mParentPositionListener = new PositionObserver.Listener() {
95 @Override
96 public void onPositionChanged(int x, int y) {
97 updateParentPosition(x, y);
98 }
99 };
100 }
101
102 @Override
103 public boolean onTouchEvent(MotionEvent event) {
104 final PopupTouchHandleDrawableDelegate delegate = mDelegate.get();
105 if (delegate == null) {
106 // If the delegate is gone, we should immediately dispose of the pop up.
107 hide();
108 return false;
109 }
110
111 // Convert from PopupWindow local coordinates to
112 // parent view local coordinates prior to forwarding.
113 delegate.getParent().getLocationOnScreen(mTempScreenCoords);
114 final float offsetX = event.getRawX() - event.getX() - mTempScreenCoords [0];
115 final float offsetY = event.getRawY() - event.getY() - mTempScreenCoords [1];
116 final MotionEvent offsetEvent = MotionEvent.obtainNoHistory(event);
117 offsetEvent.offsetLocation(offsetX, offsetY);
118 final boolean handled = delegate.onTouchHandleEvent(offsetEvent);
119 offsetEvent.recycle();
120 return handled;
121 }
122
123 private void setOrientation(int orientation) {
124 assert orientation >= LEFT && orientation <= RIGHT;
125 if (mOrientation == orientation) return;
126
127 final boolean hadValidOrientation = mOrientation != -1;
128 mOrientation = orientation;
129
130 final int oldAdjustedPositionX = getAdjustedPositionX();
131 final int oldAdjustedPositionY = getAdjustedPositionY();
132
133 switch (orientation) {
134 case LEFT: {
135 mDrawable = HandleViewResources.getLeftHandleDrawable(mContext);
136 mHotspotX = (mDrawable.getIntrinsicWidth() * 3) / 4f;
137 break;
138 }
139
140 case RIGHT: {
141 mDrawable = HandleViewResources.getRightHandleDrawable(mContext) ;
142 mHotspotX = mDrawable.getIntrinsicWidth() / 4f;
143 break;
144 }
145
146 case CENTER:
147 default: {
148 mDrawable = HandleViewResources.getCenterHandleDrawable(mContext );
149 mHotspotX = mDrawable.getIntrinsicWidth() / 2f;
150 break;
151 }
152 }
153 mHotspotY = 0;
154
155 // Force handle repositioning to accommodate the new orientation's hotsp ot.
156 if (hadValidOrientation) positionAt(oldAdjustedPositionX, oldAdjustedPos itionY);
157 mDrawable.setAlpha((int) (255 * mAlpha));
158
159 invalidate();
160 }
161
162 private void updateParentPosition(int parentPositionX, int parentPositionY) {
163 mParentPositionX = parentPositionX;
164 mParentPositionY = parentPositionY;
165 onPositionChanged();
166 }
167
168 private int getContainerPositionX() {
169 return mParentPositionX + mPositionX;
170 }
171
172 private int getContainerPositionY() {
173 return mParentPositionY + mPositionY;
174 }
175
176 private void onPositionChanged() {
177 mContainer.update(getContainerPositionX(), getContainerPositionY(),
178 getRight() - getLeft(), getBottom() - getTop());
179 }
180
181 // x and y are in physical pixels.
182 private void moveTo(int x, int y) {
183 mPositionX = x;
184 mPositionY = y;
185 onPositionChanged();
186 }
187
188 @Override
189 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
190 if (mDrawable == null) {
191 setMeasuredDimension(0, 0);
192 return;
193 }
194 setMeasuredDimension(mDrawable.getIntrinsicWidth(),
195 mDrawable.getIntrinsicHeight());
196 }
197
198 @Override
199 protected void onDraw(Canvas c) {
200 if (mDrawable == null) return;
201 mDrawable.setBounds(0, 0, getRight() - getLeft(), getBottom() - getTop() );
202 mDrawable.draw(c);
203 }
204
205 // x and y are in physical pixels.
206 private void positionAt(int x, int y) {
207 moveTo(x - Math.round(mHotspotX), y - Math.round(mHotspotY));
208 }
209
210 // Returns the x coordinate of the position that the handle appears to be po inting to relative
211 // to the handles "parent" view.
212 private int getAdjustedPositionX() {
213 return mPositionX + Math.round(mHotspotX);
214 }
215
216 // Returns the y coordinate of the position that the handle appears to be po inting to relative
217 // to the handles "parent" view.
218 private int getAdjustedPositionY() {
219 return mPositionY + Math.round(mHotspotY);
220 }
221
222 @CalledByNative
223 private void show() {
224 if (mContainer.isShowing()) return;
225
226 final PopupTouchHandleDrawableDelegate delegate = mDelegate.get();
227 if (delegate == null) {
228 hide();
229 return;
230 }
231
232 mParentPositionObserver = delegate.getParentPositionObserver();
233 assert mParentPositionObserver != null;
234
235 // While hidden, the parent position may have become stale. It must be u pdated before
236 // checking isPositionVisible().
237 updateParentPosition(mParentPositionObserver.getPositionX(),
238 mParentPositionObserver.getPositionY());
239 mParentPositionObserver.addListener(mParentPositionListener);
240 mContainer.setContentView(this);
241 mContainer.showAtLocation(delegate.getParent(), 0,
242 getContainerPositionX(), getContainerPositionY());
243 }
244
245 @CalledByNative
246 private void hide() {
247 mContainer.dismiss();
248 if (mParentPositionObserver != null) {
249 mParentPositionObserver.removeListener(mParentPositionListener);
250 // Clear the strong reference to allow garbage collection.
251 mParentPositionObserver = null;
252 }
253 }
254
255 @CalledByNative
256 private void setRightOrientation() {
257 setOrientation(RIGHT);
258 }
259
260 @CalledByNative
261 private void setLeftOrientation() {
262 setOrientation(LEFT);
263 }
264
265 @CalledByNative
266 private void setCenterOrientation() {
267 setOrientation(CENTER);
268 }
269
270 @CalledByNative
271 private void setOpacity(float alpha) {
272 if (mAlpha == alpha) return;
273 mAlpha = alpha;
274 if (mDrawable != null) mDrawable.setAlpha((int) (255 * mAlpha));
275 }
276
277 @CalledByNative
278 private void setFocus(float x, float y) {
279 positionAt((int) x, (int) y);
280 }
281
282 @CalledByNative
283 private void setVisible(boolean visible) {
284 setVisibility(visible ? VISIBLE : INVISIBLE);
285 }
286
287 @CalledByNative
288 private boolean containsPoint(float x, float y) {
289 if (mDrawable == null) return false;
290 final int width = mDrawable.getIntrinsicWidth();
291 final int height = mDrawable.getIntrinsicHeight();
292 return x > mPositionX && x < (mPositionX + width)
293 && y > mPositionY && y < (mPositionY + height);
294 }
295 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698