blob: bcd5bb7c462d9abfd2156ff2ce5981f1fbf94c82 [file] [log] [blame]
The Android Open Source Project0c908882009-03-03 19:32:16 -08001/*
2 * Copyright (C) 2007 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.browser;
18
The Android Open Source Project0c908882009-03-03 19:32:16 -080019import android.content.Context;
The Android Open Source Project0c908882009-03-03 19:32:16 -080020import android.text.Editable;
Leon Scroggins III36529cf2010-05-06 13:34:28 -040021import android.text.Selection;
The Android Open Source Project0c908882009-03-03 19:32:16 -080022import android.text.Spannable;
23import android.text.TextWatcher;
24import android.view.Gravity;
25import android.view.KeyEvent;
Leon Scroggins III211ba542010-04-19 13:21:13 -040026import android.view.LayoutInflater;
The Android Open Source Project0c908882009-03-03 19:32:16 -080027import android.view.View;
28import android.view.ViewGroup;
Leon Scroggins III211ba542010-04-19 13:21:13 -040029import android.view.animation.AnimationUtils;
The Android Open Source Project0c908882009-03-03 19:32:16 -080030import android.view.inputmethod.InputMethodManager;
31import android.webkit.WebView;
32import android.widget.EditText;
Leon Scroggins III211ba542010-04-19 13:21:13 -040033import android.widget.LinearLayout;
The Android Open Source Project0c908882009-03-03 19:32:16 -080034import android.widget.TextView;
35
Leon Scroggins III211ba542010-04-19 13:21:13 -040036/* package */ class FindDialog extends LinearLayout implements TextWatcher {
The Android Open Source Project0c908882009-03-03 19:32:16 -080037 private WebView mWebView;
38 private TextView mMatches;
39 private BrowserActivity mBrowserActivity;
40
41 // Views with which the user can interact.
The Android Open Source Project0c908882009-03-03 19:32:16 -080042 private EditText mEditText;
43 private View mNextButton;
44 private View mPrevButton;
45 private View mMatchesView;
46
Leon Scroggins III36529cf2010-05-06 13:34:28 -040047 // When the dialog is opened up with old text, enter needs to be pressed
48 // (or the text needs to be changed) before WebView.findAll can be called.
49 // Once it has been called, enter should move to the next match.
50 private boolean mMatchesFound;
Leon Scrogginsbff40382010-05-06 16:36:42 -040051 private int mNumberOfMatches;
The Android Open Source Project0c908882009-03-03 19:32:16 -080052 private View.OnClickListener mFindListener = new View.OnClickListener() {
53 public void onClick(View v) {
54 findNext();
55 }
56 };
57
58 private View.OnClickListener mFindCancelListener =
59 new View.OnClickListener() {
60 public void onClick(View v) {
Leon Scroggins III211ba542010-04-19 13:21:13 -040061 mBrowserActivity.closeFind();
The Android Open Source Project0c908882009-03-03 19:32:16 -080062 }
63 };
64
65 private View.OnClickListener mFindPreviousListener =
66 new View.OnClickListener() {
67 public void onClick(View v) {
68 if (mWebView == null) {
69 throw new AssertionError("No WebView for FindDialog::onClick");
70 }
71 mWebView.findNext(false);
Leon Scrogginsbff40382010-05-06 16:36:42 -040072 updateMatchesString();
The Android Open Source Project0c908882009-03-03 19:32:16 -080073 hideSoftInput();
74 }
75 };
76
77 /*
78 * Remove the soft keyboard from the screen.
79 */
80 private void hideSoftInput() {
81 InputMethodManager imm = (InputMethodManager)
82 mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
83 imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0);
84 }
85
86 private void disableButtons() {
87 mPrevButton.setEnabled(false);
88 mNextButton.setEnabled(false);
89 mPrevButton.setFocusable(false);
90 mNextButton.setFocusable(false);
91 }
92
93 /* package */ void setWebView(WebView webview) {
94 mWebView = webview;
95 }
96
97 /* package */ FindDialog(BrowserActivity context) {
Leon Scroggins III211ba542010-04-19 13:21:13 -040098 super(context);
The Android Open Source Project0c908882009-03-03 19:32:16 -080099 mBrowserActivity = context;
The Android Open Source Project0c908882009-03-03 19:32:16 -0800100
Leon Scroggins III211ba542010-04-19 13:21:13 -0400101 LayoutInflater factory = LayoutInflater.from(context);
102 factory.inflate(R.layout.browser_find, this);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800103
104 mEditText = (EditText) findViewById(R.id.edit);
105
106 View button = findViewById(R.id.next);
107 button.setOnClickListener(mFindListener);
108 mNextButton = button;
109
110 button = findViewById(R.id.previous);
111 button.setOnClickListener(mFindPreviousListener);
112 mPrevButton = button;
113
114 button = findViewById(R.id.done);
115 button.setOnClickListener(mFindCancelListener);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800116
117 mMatches = (TextView) findViewById(R.id.matches);
118 mMatchesView = findViewById(R.id.matches_view);
119 disableButtons();
Leon Scroggins III211ba542010-04-19 13:21:13 -0400120
The Android Open Source Project0c908882009-03-03 19:32:16 -0800121 }
Leon Scroggins III211ba542010-04-19 13:21:13 -0400122
123 /**
124 * Called by BrowserActivity.closeFind. Start the animation to hide
125 * the dialog, inform the WebView that the dialog is being dismissed,
126 * and hide the soft keyboard.
127 */
The Android Open Source Project0c908882009-03-03 19:32:16 -0800128 public void dismiss() {
Cary Clark7d3ac792010-03-03 10:11:44 -0500129 mWebView.notifyFindDialogDismissed();
Leon Scroggins III211ba542010-04-19 13:21:13 -0400130 startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
131 R.anim.find_dialog_exit));
Leon Scroggins III36529cf2010-05-06 13:34:28 -0400132 hideSoftInput();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800133 }
Leon Scroggins354bbd02009-04-16 15:24:07 -0400134
The Android Open Source Project0c908882009-03-03 19:32:16 -0800135 @Override
Leon Scroggins IIIcda86002010-05-06 14:27:07 -0400136 public boolean dispatchKeyEventPreIme(KeyEvent event) {
137 if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
138 KeyEvent.DispatcherState state = getKeyDispatcherState();
139 if (state != null) {
140 int action = event.getAction();
141 if (KeyEvent.ACTION_DOWN == action
142 && event.getRepeatCount() == 0) {
143 state.startTracking(event, this);
144 return true;
145 } else if (KeyEvent.ACTION_UP == action
146 && !event.isCanceled() && state.isTracking(event)) {
147 mBrowserActivity.closeFind();
148 return true;
149 }
150 }
151 }
152 return super.dispatchKeyEventPreIme(event);
153 }
154
155 @Override
The Android Open Source Project0c908882009-03-03 19:32:16 -0800156 public boolean dispatchKeyEvent(KeyEvent event) {
Leon Scroggins III211ba542010-04-19 13:21:13 -0400157 int keyCode = event.getKeyCode();
Leon Scroggins IIIcda86002010-05-06 14:27:07 -0400158 if (event.getAction() == KeyEvent.ACTION_UP) {
Leon Scroggins III211ba542010-04-19 13:21:13 -0400159 if (keyCode == KeyEvent.KEYCODE_ENTER
160 && mEditText.hasFocus()) {
Leon Scroggins III36529cf2010-05-06 13:34:28 -0400161 if (mMatchesFound) {
162 findNext();
163 } else {
164 findAll();
165 // Set the selection to the end.
166 Spannable span = (Spannable) mEditText.getText();
167 Selection.setSelection(span, span.length());
168 }
Leon Scroggins III211ba542010-04-19 13:21:13 -0400169 return true;
170 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800171 }
172 return super.dispatchKeyEvent(event);
173 }
174
175 private void findNext() {
176 if (mWebView == null) {
177 throw new AssertionError("No WebView for FindDialog::findNext");
178 }
179 mWebView.findNext(true);
Leon Scrogginsbff40382010-05-06 16:36:42 -0400180 updateMatchesString();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800181 hideSoftInput();
182 }
183
184 public void show() {
Leon Scroggins III36529cf2010-05-06 13:34:28 -0400185 // In case the matches view is showing from a previous search
186 mMatchesView.setVisibility(View.INVISIBLE);
187 mMatchesFound = false;
Leon Scrogginsbff40382010-05-06 16:36:42 -0400188 // This text is only here to ensure that mMatches has a height.
189 mMatches.setText("0");
The Android Open Source Project0c908882009-03-03 19:32:16 -0800190 mEditText.requestFocus();
The Android Open Source Project0c908882009-03-03 19:32:16 -0800191 Spannable span = (Spannable) mEditText.getText();
Leon Scroggins III36529cf2010-05-06 13:34:28 -0400192 int length = span.length();
193 Selection.setSelection(span, 0, length);
194 span.setSpan(this, 0, length, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800195 disableButtons();
Leon Scroggins III211ba542010-04-19 13:21:13 -0400196 startAnimation(AnimationUtils.loadAnimation(mBrowserActivity,
197 R.anim.find_dialog_enter));
198 InputMethodManager imm = (InputMethodManager)
199 mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE);
200 imm.showSoftInput(mEditText, 0);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800201 }
202
203 // TextWatcher methods
204 public void beforeTextChanged(CharSequence s,
205 int start,
206 int count,
207 int after) {
208 }
209
210 public void onTextChanged(CharSequence s,
211 int start,
212 int before,
213 int count) {
Leon Scroggins III36529cf2010-05-06 13:34:28 -0400214 findAll();
215 }
216
217 private void findAll() {
Leon Scrogginsbff40382010-05-06 16:36:42 -0400218 if (mWebView == null) {
219 throw new AssertionError(
220 "No WebView for FindDialog::findAll");
221 }
The Android Open Source Project0c908882009-03-03 19:32:16 -0800222 CharSequence find = mEditText.getText();
223 if (0 == find.length()) {
224 disableButtons();
225 mWebView.clearMatches();
226 mMatchesView.setVisibility(View.INVISIBLE);
227 } else {
228 mMatchesView.setVisibility(View.VISIBLE);
229 int found = mWebView.findAll(find.toString());
Leon Scroggins III36529cf2010-05-06 13:34:28 -0400230 mMatchesFound = true;
Eric Fischer8963b292009-03-24 17:53:52 -0700231 setMatchesFound(found);
The Android Open Source Project0c908882009-03-03 19:32:16 -0800232 if (found < 2) {
233 disableButtons();
234 if (found == 0) {
Leon Scrogginsbff40382010-05-06 16:36:42 -0400235 // Cannot use getQuantityString, which ignores the "zero"
236 // quantity.
237 mMatches.setText(mBrowserActivity.getResources().getString(
238 R.string.no_matches));
The Android Open Source Project0c908882009-03-03 19:32:16 -0800239 }
240 } else {
241 mPrevButton.setFocusable(true);
242 mNextButton.setFocusable(true);
243 mPrevButton.setEnabled(true);
244 mNextButton.setEnabled(true);
245 }
246 }
247 }
248
Eric Fischer8963b292009-03-24 17:53:52 -0700249 private void setMatchesFound(int found) {
Leon Scrogginsbff40382010-05-06 16:36:42 -0400250 mNumberOfMatches = found;
251 updateMatchesString();
252 }
253
254 private void updateMatchesString() {
255 // Note: updateMatchesString is only called by methods that have already
256 // checked mWebView for null.
Eric Fischer8963b292009-03-24 17:53:52 -0700257 String template = mBrowserActivity.getResources().
Leon Scrogginsbff40382010-05-06 16:36:42 -0400258 getQuantityString(R.plurals.matches_found, mNumberOfMatches,
259 mWebView.findIndex() + 1, mNumberOfMatches);
Eric Fischer8963b292009-03-24 17:53:52 -0700260
261 mMatches.setText(template);
262 }
263
The Android Open Source Project0c908882009-03-03 19:32:16 -0800264 public void afterTextChanged(Editable s) {
265 }
266}