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

Side by Side Diff: content/public/android/java/src/org/chromium/content/browser/input/PastePopupMenu.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.content.res.TypedArray;
9 import android.util.TypedValue;
10 import android.view.Gravity;
11 import android.view.LayoutInflater;
12 import android.view.View;
13 import android.view.View.OnClickListener;
14 import android.view.ViewGroup;
15 import android.view.ViewGroup.LayoutParams;
16 import android.widget.PopupWindow;
17
18 /**
19 * Paste popup implementation based on TextView.PastePopupMenu.
20 */
21 public class PastePopupMenu implements OnClickListener {
22 private final View mParent;
23 private final PastePopupMenuDelegate mDelegate;
24 private final Context mContext;
25 private final PopupWindow mContainer;
26 private int mRawPositionX;
27 private int mRawPositionY;
28 private int mPositionX;
29 private int mPositionY;
30 private final View[] mPasteViews;
31 private final int[] mPasteViewLayouts;
32 private final int mLineOffsetY;
33 private final int mWidthOffsetX;
34
35 /**
36 * Provider of paste functionality for the given popup.
37 */
38 public interface PastePopupMenuDelegate {
39 /**
40 * Called to initiate a paste after the popup has been tapped.
41 */
42 void paste();
43
44 /**
45 * @return true iff content can be pasted to a focused editable region.
46 */
47 boolean canPaste();
48 }
49
50 public PastePopupMenu(View parent, PastePopupMenuDelegate delegate) {
51 mParent = parent;
52 mDelegate = delegate;
53 mContext = parent.getContext();
54 mContainer = new PopupWindow(mContext, null,
55 android.R.attr.textSelectHandleWindowStyle);
56 mContainer.setSplitTouchEnabled(true);
57 mContainer.setClippingEnabled(false);
58 mContainer.setAnimationStyle(0);
59
60 mContainer.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
61 mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
62
63 final int[] POPUP_LAYOUT_ATTRS = {
64 android.R.attr.textEditPasteWindowLayout,
65 android.R.attr.textEditNoPasteWindowLayout,
66 android.R.attr.textEditSidePasteWindowLayout,
67 android.R.attr.textEditSideNoPasteWindowLayout,
68 };
69
70 mPasteViews = new View[POPUP_LAYOUT_ATTRS.length];
71 mPasteViewLayouts = new int[POPUP_LAYOUT_ATTRS.length];
72
73 TypedArray attrs = mContext.getTheme().obtainStyledAttributes(POPUP_LAYO UT_ATTRS);
74 for (int i = 0; i < attrs.length(); ++i) {
75 mPasteViewLayouts[i] = attrs.getResourceId(attrs.getIndex(i), 0);
76 }
77 attrs.recycle();
78
79 // Convert line offset dips to pixels.
80 mLineOffsetY = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_D IP,
81 5.0f, mContext.getResources().getDisplayMetrics());
82 mWidthOffsetX = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_ DIP,
83 30.0f, mContext.getResources().getDisplayMetrics());
84 }
85
86 /**
87 * Shows the paste popup at an appropriate location relative to the specifie d position.
88 */
89 public void showAt(int x, int y) {
90 if (!canPaste()) return;
91 updateContent(true);
92 positionAt(x, y);
93 }
94
95 /**
96 * Hides the paste popup.
97 */
98 public void hide() {
99 mContainer.dismiss();
100 }
101
102 /**
103 * @return Whether the popup is active and showing.
104 */
105 public boolean isShowing() {
106 return mContainer.isShowing();
107 }
108
109 @Override
110 public void onClick(View v) {
111 if (canPaste()) {
112 paste();
113 }
114 hide();
115 }
116
117 private void positionAt(int x, int y) {
118 if (mRawPositionX == x && mRawPositionY == y && isShowing()) return;
119 mRawPositionX = x;
120 mRawPositionY = y;
121
122 View contentView = mContainer.getContentView();
123 int width = contentView.getMeasuredWidth();
124 int height = contentView.getMeasuredHeight();
125
126 mPositionX = (int) (x - width / 2.0f);
127 mPositionY = y - height - mLineOffsetY;
128
129 final int[] coords = new int[2];
130 mParent.getLocationInWindow(coords);
131 coords[0] += mPositionX;
132 coords[1] += mPositionY;
133
134 final int screenWidth = mContext.getResources().getDisplayMetrics().widt hPixels;
135 if (coords[1] < 0) {
136 updateContent(false);
137 // Update dimensions from new view
138 contentView = mContainer.getContentView();
139 width = contentView.getMeasuredWidth();
140 height = contentView.getMeasuredHeight();
141
142 // Vertical clipping, move under edited line and to the side of inse rtion cursor
143 // TODO bottom clipping in case there is no system bar
144 coords[1] += height;
145 coords[1] += mLineOffsetY;
146
147 // Move to right hand side of insertion cursor by default. TODO RTL text.
148 final int handleHalfWidth = mWidthOffsetX / 2;
149
150 if (x + width < screenWidth) {
151 coords[0] += handleHalfWidth + width / 2;
152 } else {
153 coords[0] -= handleHalfWidth + width / 2;
154 }
155 } else {
156 // Horizontal clipping
157 coords[0] = Math.max(0, coords[0]);
158 coords[0] = Math.min(screenWidth - width, coords[0]);
159 }
160
161 mContainer.showAtLocation(mParent, Gravity.NO_GRAVITY, coords[0], coords [1]);
162 }
163
164 private int viewIndex(boolean onTop) {
165 return (onTop ? 0 : 1 << 1) + (canPaste() ? 0 : 1 << 0);
166 }
167
168 private void updateContent(boolean onTop) {
169 final int viewIndex = viewIndex(onTop);
170 View view = mPasteViews[viewIndex];
171
172 if (view == null) {
173 final int layout = mPasteViewLayouts[viewIndex];
174 LayoutInflater inflater = (LayoutInflater) mContext.
175 getSystemService(Context.LAYOUT_INFLATER_SERVICE);
176 if (inflater != null) {
177 view = inflater.inflate(layout, null);
178 }
179
180 if (view == null) {
181 throw new IllegalArgumentException("Unable to inflate TextEdit p aste window");
182 }
183
184 final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpe c.UNSPECIFIED);
185 view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CO NTENT,
186 ViewGroup.LayoutParams.WRAP_CONTENT));
187 view.measure(size, size);
188
189 view.setOnClickListener(this);
190
191 mPasteViews[viewIndex] = view;
192 }
193
194 mContainer.setContentView(view);
195 }
196
197 private boolean canPaste() {
198 return mDelegate.canPaste();
199 }
200
201 private void paste() {
202 mDelegate.paste();
203 }
204 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698