EMMA Coverage Report (generated Fri Aug 23 16:39:17 PDT 2013)
[all classes][org.chromium.content.browser.input]

COVERAGE SUMMARY FOR SOURCE FILE [InsertionHandleController.java]

nameclass, %method, %block, %line, %
InsertionHandleController.java50%  (1/2)36%  (12/33)18%  (89/502)27%  (32/120)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class InsertionHandleController$PastePopupMenu0%   (0/1)0%   (0/8)0%   (0/361)0%   (0/69)
InsertionHandleController$PastePopupMenu (InsertionHandleController): void 0%   (0/1)0%   (0/85)0%   (0/14)
hide (): void 0%   (0/1)0%   (0/4)0%   (0/2)
isShowing (): boolean 0%   (0/1)0%   (0/4)0%   (0/1)
onClick (View): void 0%   (0/1)0%   (0/10)0%   (0/4)
positionAtCursor (): void 0%   (0/1)0%   (0/173)0%   (0/28)
show (): void 0%   (0/1)0%   (0/6)0%   (0/3)
updateContent (boolean): void 0%   (0/1)0%   (0/65)0%   (0/16)
viewIndex (boolean): int 0%   (0/1)0%   (0/14)0%   (0/1)
     
class InsertionHandleController100% (1/1)48%  (12/25)63%  (89/141)63%  (32/51)
access$000 (InsertionHandleController): Context 0%   (0/1)0%   (0/3)0%   (0/1)
access$100 (InsertionHandleController): HandleView 0%   (0/1)0%   (0/3)0%   (0/1)
access$200 (InsertionHandleController): View 0%   (0/1)0%   (0/3)0%   (0/1)
beforeStartUpdatingPosition (HandleView): void 0%   (0/1)0%   (0/1)0%   (0/1)
beginHandleFadeIn (): void 0%   (0/1)0%   (0/4)0%   (0/2)
canPaste (): boolean 0%   (0/1)0%   (0/7)0%   (0/1)
getHandleX (): int 0%   (0/1)0%   (0/4)0%   (0/1)
getHandleY (): int 0%   (0/1)0%   (0/4)0%   (0/1)
onDetached (): void 0%   (0/1)0%   (0/1)0%   (0/1)
onTouchModeChanged (boolean): void 0%   (0/1)0%   (0/5)0%   (0/3)
showHandleWithPastePopup (): void 0%   (0/1)0%   (0/5)0%   (0/3)
showPastePopup (): void 0%   (0/1)0%   (0/7)0%   (0/3)
updatePosition (HandleView, int, int): void 0%   (0/1)0%   (0/5)0%   (0/2)
InsertionHandleController (View): void 100% (1/1)100% (10/10)100% (4/4)
allowAutomaticShowing (): void 100% (1/1)100% (4/4)100% (2/2)
createHandleIfNeeded (): void 100% (1/1)100% (13/13)100% (2/2)
getHandleViewForTest (): HandleView 100% (1/1)100% (3/3)100% (1/1)
hide (): void 100% (1/1)100% (13/13)100% (4/4)
hideAndDisallowAutomaticShowing (): void 100% (1/1)100% (6/6)100% (3/3)
isShowing (): boolean 100% (1/1)100% (3/3)100% (1/1)
onCursorPositionChanged (): void 100% (1/1)100% (6/6)100% (3/3)
setHandlePosition (float, float): void 100% (1/1)100% (8/8)100% (2/2)
setHandleVisibility (int): void 100% (1/1)100% (5/5)100% (2/2)
showHandle (): void 100% (1/1)100% (5/5)100% (3/3)
showHandleIfNeeded (): void 100% (1/1)100% (13/13)100% (5/5)

1// Copyright (c) 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 
5package org.chromium.content.browser.input;
6 
7import android.content.ClipboardManager;
8import android.content.Context;
9import android.content.res.TypedArray;
10import android.graphics.drawable.Drawable;
11import android.view.Gravity;
12import android.view.LayoutInflater;
13import android.view.View;
14import android.view.View.OnClickListener;
15import android.view.ViewGroup;
16import android.view.ViewGroup.LayoutParams;
17import android.widget.PopupWindow;
18 
19import com.google.common.annotations.VisibleForTesting;
20 
21/**
22 * CursorController for inserting text at the cursor position.
23 */
24public abstract class InsertionHandleController implements CursorController {
25 
26    /** The handle view, lazily created when first shown */
27    private HandleView mHandle;
28 
29    /** The view over which the insertion handle should be shown */
30    private View mParent;
31 
32    /** True iff the insertion handle is currently showing */
33    private boolean mIsShowing;
34 
35    /** True iff the insertion handle can be shown automatically when selection changes */
36    private boolean mAllowAutomaticShowing;
37 
38    private Context mContext;
39 
40    public InsertionHandleController(View parent) {
41        mParent = parent;
42        mContext = parent.getContext();
43    }
44 
45    /** Allows the handle to be shown automatically when cursor position changes */
46    public void allowAutomaticShowing() {
47        mAllowAutomaticShowing = true;
48    }
49 
50    /** Disallows the handle from being shown automatically when cursor position changes */
51    public void hideAndDisallowAutomaticShowing() {
52        hide();
53        mAllowAutomaticShowing = false;
54    }
55 
56    /**
57     * Shows the handle.
58     */
59    public void showHandle() {
60        createHandleIfNeeded();
61        showHandleIfNeeded();
62    }
63 
64    void showPastePopup() {
65        if (mIsShowing) {
66            mHandle.showPastePopupWindow();
67        }
68    }
69 
70    public void showHandleWithPastePopup() {
71        showHandle();
72        showPastePopup();
73    }
74 
75    /** Shows the handle at the given coordinates, as long as automatic showing is allowed */
76    public void onCursorPositionChanged() {
77        if (mAllowAutomaticShowing) {
78            showHandle();
79        }
80    }
81 
82    /**
83     * Moves the handle so that it points at the given coordinates.
84     * @param x Handle x in physical pixels.
85     * @param y Handle y in physical pixels.
86     */
87    public void setHandlePosition(float x, float y) {
88        mHandle.positionAt((int) x, (int) y);
89    }
90 
91    /**
92     * If the handle is not visible, sets its visibility to View.VISIBLE and begins fading it in.
93     */
94    public void beginHandleFadeIn() {
95        mHandle.beginFadeIn();
96    }
97 
98    /**
99     * Sets the handle to the given visibility.
100     */
101    public void setHandleVisibility(int visibility) {
102        mHandle.setVisibility(visibility);
103    }
104 
105    int getHandleX() {
106        return mHandle.getAdjustedPositionX();
107    }
108 
109    int getHandleY() {
110        return mHandle.getAdjustedPositionY();
111    }
112 
113    @VisibleForTesting
114    public HandleView getHandleViewForTest() {
115        return mHandle;
116    }
117 
118    @Override
119    public void onTouchModeChanged(boolean isInTouchMode) {
120        if (!isInTouchMode) {
121            hide();
122        }
123    }
124 
125    @Override
126    public void hide() {
127        if (mIsShowing) {
128            if (mHandle != null) mHandle.hide();
129            mIsShowing = false;
130        }
131    }
132 
133    @Override
134    public boolean isShowing() {
135        return mIsShowing;
136    }
137 
138    @Override
139    public void beforeStartUpdatingPosition(HandleView handle) {}
140 
141    @Override
142    public void updatePosition(HandleView handle, int x, int y) {
143        setCursorPosition(x, y);
144    }
145 
146    /**
147     * The concrete implementation must cause the cursor position to move to the given
148     * coordinates and (possibly asynchronously) set the insertion handle position
149     * after the cursor position change is made via setHandlePosition.
150     * @param x
151     * @param y
152     */
153    protected abstract void setCursorPosition(int x, int y);
154 
155    /** Pastes the contents of clipboard at the current insertion point */
156    protected abstract void paste();
157 
158    /** Returns the current line height in pixels */
159    protected abstract int getLineHeight();
160 
161    @Override
162    public void onDetached() {}
163 
164    boolean canPaste() {
165        return ((ClipboardManager)mContext.getSystemService(
166                Context.CLIPBOARD_SERVICE)).hasPrimaryClip();
167    }
168 
169    private void createHandleIfNeeded() {
170        if (mHandle == null) mHandle = new HandleView(this, HandleView.CENTER, mParent);
171    }
172 
173    private void showHandleIfNeeded() {
174        if (!mIsShowing) {
175            mIsShowing = true;
176            mHandle.show();
177            setHandleVisibility(HandleView.VISIBLE);
178        }
179    }
180 
181    /*
182     * This class is based on TextView.PastePopupMenu.
183     */
184    class PastePopupMenu implements OnClickListener {
185        private final PopupWindow mContainer;
186        private int mPositionX;
187        private int mPositionY;
188        private View[] mPasteViews;
189        private int[] mPasteViewLayouts;
190 
191        public PastePopupMenu() {
192            mContainer = new PopupWindow(mContext, null,
193                    android.R.attr.textSelectHandleWindowStyle);
194            mContainer.setSplitTouchEnabled(true);
195            mContainer.setClippingEnabled(false);
196 
197            mContainer.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
198            mContainer.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);
199 
200            final int[] POPUP_LAYOUT_ATTRS = {
201                android.R.attr.textEditPasteWindowLayout,
202                android.R.attr.textEditNoPasteWindowLayout,
203                android.R.attr.textEditSidePasteWindowLayout,
204                android.R.attr.textEditSideNoPasteWindowLayout,
205            };
206 
207            mPasteViews = new View[POPUP_LAYOUT_ATTRS.length];
208            mPasteViewLayouts = new int[POPUP_LAYOUT_ATTRS.length];
209 
210            TypedArray attrs = mContext.obtainStyledAttributes(POPUP_LAYOUT_ATTRS);
211            for (int i = 0; i < attrs.length(); ++i) {
212                mPasteViewLayouts[i] = attrs.getResourceId(attrs.getIndex(i), 0);
213            }
214            attrs.recycle();
215        }
216 
217        private int viewIndex(boolean onTop) {
218            return (onTop ? 0 : 1<<1) + (canPaste() ? 0 : 1 << 0);
219        }
220 
221        private void updateContent(boolean onTop) {
222            final int viewIndex = viewIndex(onTop);
223            View view = mPasteViews[viewIndex];
224 
225            if (view == null) {
226                final int layout = mPasteViewLayouts[viewIndex];
227                LayoutInflater inflater = (LayoutInflater)mContext.
228                    getSystemService(Context.LAYOUT_INFLATER_SERVICE);
229                if (inflater != null) {
230                    view = inflater.inflate(layout, null);
231                }
232 
233                if (view == null) {
234                    throw new IllegalArgumentException("Unable to inflate TextEdit paste window");
235                }
236 
237                final int size = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED);
238                view.setLayoutParams(new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
239                        ViewGroup.LayoutParams.WRAP_CONTENT));
240                view.measure(size, size);
241 
242                view.setOnClickListener(this);
243 
244                mPasteViews[viewIndex] = view;
245            }
246 
247            mContainer.setContentView(view);
248        }
249 
250        void show() {
251            updateContent(true);
252            positionAtCursor();
253        }
254 
255        void hide() {
256            mContainer.dismiss();
257        }
258 
259        boolean isShowing() {
260            return mContainer.isShowing();
261        }
262 
263        @Override
264        public void onClick(View v) {
265            if (canPaste()) {
266                paste();
267            }
268            hide();
269        }
270 
271        void positionAtCursor() {
272            View contentView = mContainer.getContentView();
273            int width = contentView.getMeasuredWidth();
274            int height = contentView.getMeasuredHeight();
275 
276            int lineHeight = getLineHeight();
277 
278            mPositionX = (int) (mHandle.getAdjustedPositionX() - width / 2.0f);
279            mPositionY = mHandle.getAdjustedPositionY() - height - lineHeight;
280 
281            final int[] coords = new int[2];
282            mParent.getLocationInWindow(coords);
283            coords[0] += mPositionX;
284            coords[1] += mPositionY;
285 
286            final int screenWidth = mContext.getResources().getDisplayMetrics().widthPixels;
287            if (coords[1] < 0) {
288                updateContent(false);
289                // Update dimensions from new view
290                contentView = mContainer.getContentView();
291                width = contentView.getMeasuredWidth();
292                height = contentView.getMeasuredHeight();
293 
294                // Vertical clipping, move under edited line and to the side of insertion cursor
295                // TODO bottom clipping in case there is no system bar
296                coords[1] += height;
297                coords[1] += lineHeight;
298 
299                // Move to right hand side of insertion cursor by default. TODO RTL text.
300                final Drawable handle = mHandle.getDrawable();
301                final int handleHalfWidth = handle.getIntrinsicWidth() / 2;
302 
303                if (mHandle.getAdjustedPositionX() + width < screenWidth) {
304                    coords[0] += handleHalfWidth + width / 2;
305                } else {
306                    coords[0] -= handleHalfWidth + width / 2;
307                }
308            } else {
309                // Horizontal clipping
310                coords[0] = Math.max(0, coords[0]);
311                coords[0] = Math.min(screenWidth - width, coords[0]);
312            }
313 
314            mContainer.showAtLocation(mParent, Gravity.NO_GRAVITY, coords[0], coords[1]);
315        }
316    }
317}

[all classes][org.chromium.content.browser.input]
EMMA 2.0.5312 (C) Vladimir Roubtsov