1 /* 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 17 package com.android.browser; 18 19 import android.app.Dialog; 20 import android.content.Context; 21 import android.os.Bundle; 22 import android.text.Editable; 23 import android.text.Spannable; 24 import android.text.TextWatcher; 25 import android.view.Gravity; 26 import android.view.KeyEvent; 27 import android.view.View; 28 import android.view.ViewGroup; 29 import android.view.Window; 30 import android.view.WindowManager; 31 import android.view.inputmethod.InputMethodManager; 32 import android.webkit.WebView; 33 import android.widget.EditText; 34 import android.widget.TextView; 35 36 /* package */ class FindDialog extends Dialog implements TextWatcher { 37 private WebView mWebView; 38 private TextView mMatches; 39 private BrowserActivity mBrowserActivity; 40 41 // Views with which the user can interact. 42 private EditText mEditText; 43 private View mNextButton; 44 private View mPrevButton; 45 private View mMatchesView; 46 47 private View.OnClickListener mFindListener = new View.OnClickListener() { 48 public void onClick(View v) { 49 findNext(); 50 } 51 }; 52 53 private View.OnClickListener mFindCancelListener = 54 new View.OnClickListener() { 55 public void onClick(View v) { 56 dismiss(); 57 } 58 }; 59 60 private View.OnClickListener mFindPreviousListener = 61 new View.OnClickListener() { 62 public void onClick(View v) { 63 if (mWebView == null) { 64 throw new AssertionError("No WebView for FindDialog::onClick"); 65 } 66 mWebView.findNext(false); 67 hideSoftInput(); 68 } 69 }; 70 71 /* 72 * Remove the soft keyboard from the screen. 73 */ 74 private void hideSoftInput() { 75 InputMethodManager imm = (InputMethodManager) 76 mBrowserActivity.getSystemService(Context.INPUT_METHOD_SERVICE); 77 imm.hideSoftInputFromWindow(mEditText.getWindowToken(), 0); 78 } 79 80 private void disableButtons() { 81 mPrevButton.setEnabled(false); 82 mNextButton.setEnabled(false); 83 mPrevButton.setFocusable(false); 84 mNextButton.setFocusable(false); 85 } 86 87 /* package */ void setWebView(WebView webview) { 88 mWebView = webview; 89 } 90 91 /* package */ FindDialog(BrowserActivity context) { 92 super(context, R.style.FindDialogTheme); 93 mBrowserActivity = context; 94 setCanceledOnTouchOutside(true); 95 } 96 97 @Override 98 protected void onCreate(Bundle savedInstanceState) { 99 super.onCreate(savedInstanceState); 100 101 Window theWindow = getWindow(); 102 theWindow.setGravity(Gravity.BOTTOM|Gravity.FILL_HORIZONTAL); 103 104 setContentView(R.layout.browser_find); 105 106 theWindow.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, 107 ViewGroup.LayoutParams.WRAP_CONTENT); 108 109 mEditText = (EditText) findViewById(R.id.edit); 110 111 View button = findViewById(R.id.next); 112 button.setOnClickListener(mFindListener); 113 mNextButton = button; 114 115 button = findViewById(R.id.previous); 116 button.setOnClickListener(mFindPreviousListener); 117 mPrevButton = button; 118 119 button = findViewById(R.id.done); 120 button.setOnClickListener(mFindCancelListener); 121 122 mMatches = (TextView) findViewById(R.id.matches); 123 mMatchesView = findViewById(R.id.matches_view); 124 disableButtons(); 125 theWindow.setSoftInputMode( 126 WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 127 } 128 129 public void dismiss() { 130 super.dismiss(); 131 mBrowserActivity.closeFind(); 132 mWebView.notifyFindDialogDismissed(); 133 } 134 135 @Override 136 public boolean dispatchKeyEvent(KeyEvent event) { 137 if (event.getKeyCode() == KeyEvent.KEYCODE_ENTER 138 && event.getAction() == KeyEvent.ACTION_UP 139 && mEditText.hasFocus()) { 140 findNext(); 141 return true; 142 } 143 return super.dispatchKeyEvent(event); 144 } 145 146 private void findNext() { 147 if (mWebView == null) { 148 throw new AssertionError("No WebView for FindDialog::findNext"); 149 } 150 mWebView.findNext(true); 151 hideSoftInput(); 152 } 153 154 public void show() { 155 super.show(); 156 mEditText.requestFocus(); 157 mEditText.setText(""); 158 Spannable span = (Spannable) mEditText.getText(); 159 span.setSpan(this, 0, span.length(), 160 Spannable.SPAN_INCLUSIVE_INCLUSIVE); 161 setMatchesFound(0); 162 disableButtons(); 163 } 164 165 // TextWatcher methods 166 public void beforeTextChanged(CharSequence s, 167 int start, 168 int count, 169 int after) { 170 } 171 172 public void onTextChanged(CharSequence s, 173 int start, 174 int before, 175 int count) { 176 if (mWebView == null) { 177 throw new AssertionError( 178 "No WebView for FindDialog::onTextChanged"); 179 } 180 CharSequence find = mEditText.getText(); 181 if (0 == find.length()) { 182 disableButtons(); 183 mWebView.clearMatches(); 184 mMatchesView.setVisibility(View.INVISIBLE); 185 } else { 186 mMatchesView.setVisibility(View.VISIBLE); 187 mWebView.setFindDialogHeight( 188 getWindow().getDecorView().getHeight()); 189 int found = mWebView.findAll(find.toString()); 190 setMatchesFound(found); 191 if (found < 2) { 192 disableButtons(); 193 if (found == 0) { 194 setMatchesFound(0); 195 } 196 } else { 197 mPrevButton.setFocusable(true); 198 mNextButton.setFocusable(true); 199 mPrevButton.setEnabled(true); 200 mNextButton.setEnabled(true); 201 } 202 } 203 } 204 205 private void setMatchesFound(int found) { 206 String template = mBrowserActivity.getResources(). 207 getQuantityString(R.plurals.matches_found, found, found); 208 209 mMatches.setText(template); 210 } 211 212 public void afterTextChanged(Editable s) { 213 } 214 } 215