1fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins/*
2fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * Copyright (C) 2010 The Android Open Source Project
3fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins *
4fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * Licensed under the Apache License, Version 2.0 (the "License");
5fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * you may not use this file except in compliance with the License.
6fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * You may obtain a copy of the License at
7fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins *
8fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins *      http://www.apache.org/licenses/LICENSE-2.0
9fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins *
10fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * Unless required by applicable law or agreed to in writing, software
11fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * distributed under the License is distributed on an "AS IS" BASIS,
12fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * See the License for the specific language governing permissions and
14fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins * limitations under the License.
15fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins */
16fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
17fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginspackage android.webkit;
18fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
193442c74d2ce220a2d104a5717994bbaf09a9f02dNate Fischerimport android.annotation.NonNull;
20451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Sollaimport android.annotation.SystemApi;
21fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.content.Context;
22fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.content.res.Resources;
23d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reckimport android.graphics.Point;
24d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reckimport android.graphics.Rect;
25fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.text.Editable;
26fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.text.Selection;
27fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.text.Spannable;
28fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.text.TextWatcher;
29fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.view.ActionMode;
30fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.view.LayoutInflater;
31fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.view.Menu;
32fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.view.MenuItem;
33fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.view.View;
34fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scrogginsimport android.view.inputmethod.InputMethodManager;
35fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reckimport android.widget.EditText;
36fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reckimport android.widget.TextView;
37fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
3852c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch/**
3952c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch * @hide
4052c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch */
41451e338c51e8c45efc0d21536dfae6f78f6d5e06Ignacio Solla@SystemApi
4252c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdochpublic class FindActionModeCallback implements ActionMode.Callback, TextWatcher,
4352c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        View.OnClickListener, WebView.FindListener {
44fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private View mCustomView;
45fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private EditText mEditText;
46fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private TextView mMatches;
4752c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    private WebView mWebView;
48fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private InputMethodManager mInput;
49fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private Resources mResources;
50fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private boolean mMatchesFound;
51fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private int mNumberOfMatches;
5247d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease    private int mActiveMatchIndex;
5305919f2133f8af89ab69c3a39aa34c6a32e78f05Leon Scroggins    private ActionMode mActionMode;
54fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
5552c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    public FindActionModeCallback(Context context) {
56fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mCustomView = LayoutInflater.from(context).inflate(
57fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                com.android.internal.R.layout.webview_find, null);
58fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mEditText = (EditText) mCustomView.findViewById(
59fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                com.android.internal.R.id.edit);
607e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        mEditText.setCustomSelectionActionModeCallback(new NoAction());
617014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        mEditText.setOnClickListener(this);
62fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        setText("");
63fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mMatches = (TextView) mCustomView.findViewById(
64fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                com.android.internal.R.id.matches);
65777ef95ebf18c61ff09e7567a06058d351c530caYohei Yukawa        mInput = context.getSystemService(InputMethodManager.class);
66fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mResources = context.getResources();
67fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
68fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
6952c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    public void finish() {
7005919f2133f8af89ab69c3a39aa34c6a32e78f05Leon Scroggins        mActionMode.finish();
7105919f2133f8af89ab69c3a39aa34c6a32e78f05Leon Scroggins    }
7205919f2133f8af89ab69c3a39aa34c6a32e78f05Leon Scroggins
735cca7bd58695e4a34c3cacc400d89eeb7cb89e3eNate Fischer    /**
74fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     * Place text in the text field so it can be searched for.  Need to press
75fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     * the find next or find previous button to find all of the matches.
76fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     */
7752c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    public void setText(String text) {
78fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mEditText.setText(text);
79fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        Spannable span = (Spannable) mEditText.getText();
80fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        int length = span.length();
81fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // Ideally, we would like to set the selection to the whole field,
82fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // but this brings up the Text selection CAB, which dismisses this
83fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // one.
84fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        Selection.setSelection(span, length, length);
85fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // Necessary each time we set the text, so that this will watch
86fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // changes to it.
87fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
88fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mMatchesFound = false;
89fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
90fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
913442c74d2ce220a2d104a5717994bbaf09a9f02dNate Fischer    /**
923442c74d2ce220a2d104a5717994bbaf09a9f02dNate Fischer     * Set the WebView to search.
933442c74d2ce220a2d104a5717994bbaf09a9f02dNate Fischer     *
943442c74d2ce220a2d104a5717994bbaf09a9f02dNate Fischer     * @param webView an implementation of WebView
95fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     */
963442c74d2ce220a2d104a5717994bbaf09a9f02dNate Fischer    public void setWebView(@NonNull WebView webView) {
97fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        if (null == webView) {
98fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            throw new AssertionError("WebView supplied to "
99fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                    + "FindActionModeCallback cannot be null");
100fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        }
101fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mWebView = webView;
10252c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        mWebView.setFindDialogFindListener(this);
10352c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    }
10452c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch
10552c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    @Override
10652c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    public void onFindResultReceived(int activeMatchOrdinal, int numberOfMatches,
10752c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch            boolean isDoneCounting) {
10852c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        if (isDoneCounting) {
10952c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch            updateMatchCount(activeMatchOrdinal, numberOfMatches, numberOfMatches == 0);
11052c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        }
111fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
112fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
1135cca7bd58695e4a34c3cacc400d89eeb7cb89e3eNate Fischer    /**
114fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     * Move the highlight to the next match.
1150a6140d2173052b4fa753c9ea61f92814cbced6eNate Fischer     * @param next If {@code true}, find the next match further down in the document.
1160a6140d2173052b4fa753c9ea61f92814cbced6eNate Fischer     *             If {@code false}, find the previous match, up in the document.
117fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     */
118fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private void findNext(boolean next) {
119fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        if (mWebView == null) {
120fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            throw new AssertionError(
121fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                    "No WebView for FindActionModeCallback::findNext");
122fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        }
1237014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        if (!mMatchesFound) {
1247014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins            findAll();
1257014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins            return;
1267014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        }
1277014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        if (0 == mNumberOfMatches) {
1287014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins            // There are no matches, so moving to the next match will not do
1297014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins            // anything.
1307014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins            return;
1317014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        }
132fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mWebView.findNext(next);
1337014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        updateMatchesString();
134fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
135fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
1365cca7bd58695e4a34c3cacc400d89eeb7cb89e3eNate Fischer    /**
137fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     * Highlight all the instances of the string from mEditText in mWebView.
138fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     */
13952c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch    public void findAll() {
140fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        if (mWebView == null) {
141fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            throw new AssertionError(
142fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                    "No WebView for FindActionModeCallback::findAll");
143fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        }
144fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        CharSequence find = mEditText.getText();
145fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        if (0 == find.length()) {
146fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            mWebView.clearMatches();
147fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            mMatches.setVisibility(View.GONE);
148fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            mMatchesFound = false;
149abeb6a791501151308d06db6aebb438e16c1a784Victoria Lease            mWebView.findAll(null);
150fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        } else {
151fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            mMatchesFound = true;
15247d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mMatches.setVisibility(View.INVISIBLE);
15347d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mNumberOfMatches = 0;
154abeb6a791501151308d06db6aebb438e16c1a784Victoria Lease            mWebView.findAllAsync(find.toString());
155fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        }
156fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
157fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
158571354fd29db3e4855e2f179c2c6ad47f4eefd77Leon Scroggins    public void showSoftInput() {
1595f05965f546fa42750f1a8314f8a2da01fd6bfb4Yohei Yukawa        if (mEditText.requestFocus()) {
1605f05965f546fa42750f1a8314f8a2da01fd6bfb4Yohei Yukawa            mInput.showSoftInput(mEditText, 0);
1615f05965f546fa42750f1a8314f8a2da01fd6bfb4Yohei Yukawa        }
162571354fd29db3e4855e2f179c2c6ad47f4eefd77Leon Scroggins    }
163571354fd29db3e4855e2f179c2c6ad47f4eefd77Leon Scroggins
1640b8413bbeb528c854e28c5ba1550239867da5c2eVictoria Lease    public void updateMatchCount(int matchIndex, int matchCount, boolean isEmptyFind) {
1650b8413bbeb528c854e28c5ba1550239867da5c2eVictoria Lease        if (!isEmptyFind) {
16647d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mNumberOfMatches = matchCount;
16747d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mActiveMatchIndex = matchIndex;
16847d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            updateMatchesString();
16947d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease        } else {
1701c15b8d896229b11e13134c52579a5c9fac4d5f6Stefan Wysocki            mMatches.setVisibility(View.GONE);
17147d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mNumberOfMatches = 0;
17247d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease        }
17347d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease    }
17447d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease
1755cca7bd58695e4a34c3cacc400d89eeb7cb89e3eNate Fischer    /**
176fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     * Update the string which tells the user how many matches were found, and
177fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     * which match is currently highlighted.
178fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins     */
179fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    private void updateMatchesString() {
18047d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease        if (mNumberOfMatches == 0) {
18147d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mMatches.setText(com.android.internal.R.string.no_matches);
18247d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease        } else {
18347d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease            mMatches.setText(mResources.getQuantityString(
184fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                com.android.internal.R.plurals.matches_found, mNumberOfMatches,
18547d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease                mActiveMatchIndex + 1, mNumberOfMatches));
18647d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease        }
18747d0ee9766fb972f49d5116d2d7d3a23b5321211Victoria Lease        mMatches.setVisibility(View.VISIBLE);
188fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
189fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
1907014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins    // OnClickListener implementation
1917014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins
1927014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins    @Override
1937014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins    public void onClick(View v) {
1947014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins        findNext(true);
1957014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins    }
1967014b12873068f109f58b9d0ad4116fd8d4bf22fLeon Scroggins
197fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    // ActionMode.Callback implementation
198fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
199fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
200fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
201f8419a0299680ed580975b0fcb758990b4367db8Adam Powell        if (!mode.isUiFocusable()) {
202f8419a0299680ed580975b0fcb758990b4367db8Adam Powell            // If the action mode we're running in is not focusable the user
203f8419a0299680ed580975b0fcb758990b4367db8Adam Powell            // will not be able to type into the find on page field. This
204f8419a0299680ed580975b0fcb758990b4367db8Adam Powell            // should only come up when we're running in a dialog which is
205f8419a0299680ed580975b0fcb758990b4367db8Adam Powell            // already less than ideal; disable the option for now.
206f8419a0299680ed580975b0fcb758990b4367db8Adam Powell            return false;
207f8419a0299680ed580975b0fcb758990b4367db8Adam Powell        }
208f8419a0299680ed580975b0fcb758990b4367db8Adam Powell
209fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mode.setCustomView(mCustomView);
210fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mode.getMenuInflater().inflate(com.android.internal.R.menu.webview_find,
211fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                menu);
21205919f2133f8af89ab69c3a39aa34c6a32e78f05Leon Scroggins        mActionMode = mode;
213fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        Editable edit = mEditText.getText();
214fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        Selection.setSelection(edit, edit.length());
215fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mMatches.setVisibility(View.GONE);
216fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mMatchesFound = false;
217fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mMatches.setText("0");
218fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mEditText.requestFocus();
219fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        return true;
220fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
221fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
222fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
223fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public void onDestroyActionMode(ActionMode mode) {
224fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reck        mActionMode = null;
225fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        mWebView.notifyFindDialogDismissed();
22652c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        mWebView.setFindDialogFindListener(null);
22752c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
228fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
229fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
230fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
231fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
232fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        return false;
233fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
234fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
235fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
236fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
237261f42d64dbd6d59af8ffecb315169b747167cc1Leon Scroggins        if (mWebView == null) {
238261f42d64dbd6d59af8ffecb315169b747167cc1Leon Scroggins            throw new AssertionError(
239261f42d64dbd6d59af8ffecb315169b747167cc1Leon Scroggins                    "No WebView for FindActionModeCallback::onActionItemClicked");
240261f42d64dbd6d59af8ffecb315169b747167cc1Leon Scroggins        }
24152c9f7f95083a9d041b9261522e929073cb52fd5Ben Murdoch        mInput.hideSoftInputFromWindow(mWebView.getWindowToken(), 0);
242fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        switch(item.getItemId()) {
243fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            case com.android.internal.R.id.find_prev:
244fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                findNext(false);
245fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                break;
246fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            case com.android.internal.R.id.find_next:
247fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                findNext(true);
248fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                break;
249fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins            default:
250fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                return false;
251fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        }
252fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        return true;
253fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
254fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
255fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    // TextWatcher implementation
256fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
257fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
258fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public void beforeTextChanged(CharSequence s,
259fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                                  int start,
260fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                                  int count,
261fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                                  int after) {
262fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // Does nothing.  Needed to implement TextWatcher.
263fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
264fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
265fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
266fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public void onTextChanged(CharSequence s,
267fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                              int start,
268fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                              int before,
269fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins                              int count) {
270fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        findAll();
271fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
272fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
273fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    @Override
274fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    public void afterTextChanged(Editable s) {
275fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins        // Does nothing.  Needed to implement TextWatcher.
276fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins    }
277fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins
278d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck    private Rect mGlobalVisibleRect = new Rect();
279d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck    private Point mGlobalVisibleOffset = new Point();
280d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck    public int getActionModeGlobalBottom() {
281fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reck        if (mActionMode == null) {
282fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reck            return 0;
283fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reck        }
284d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck        View view = (View) mCustomView.getParent();
285d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck        if (view == null) {
286d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck            view = mCustomView;
287d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck        }
288d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck        view.getGlobalVisibleRect(mGlobalVisibleRect, mGlobalVisibleOffset);
289d6ac727234b9be45c3df4021dc83584e9849c00aJohn Reck        return mGlobalVisibleRect.bottom;
290fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reck    }
291fffce6fe99f7ae80f448790371b8c0fa90277d1aJohn Reck
2927e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount    public static class NoAction implements ActionMode.Callback {
2937e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        @Override
2947e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        public boolean onCreateActionMode(ActionMode mode, Menu menu) {
2957e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount            return false;
2967e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        }
2977e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount
2987e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        @Override
2997e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
3007e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount            return false;
3017e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        }
3027e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount
3037e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        @Override
3047e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
3057e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount            return false;
3067e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        }
3077e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount
3087e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        @Override
3097e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        public void onDestroyActionMode(ActionMode mode) {
3107e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount        }
3117e9f62ef486af98ce6fbb3e2918a45c68c0b551fGeorge Mount    }
312fe026bdd3c0fd7543ceaf0732aeb824cfddb5b23Leon Scroggins}
313