UserDictionarySettings.java revision e33813932474f760073f92bdb7bbf93d1b923d70
1/** 2 * Copyright (C) 2009 Google Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not 5 * use this file except in compliance with the License. You may obtain a copy 6 * 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, WITHOUT 12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 * License for the specific language governing permissions and limitations 14 * under the License. 15 */ 16 17package com.android.settings; 18 19import android.app.AlertDialog; 20import android.app.Dialog; 21import android.app.ListActivity; 22import android.content.Context; 23import android.content.DialogInterface; 24import android.database.Cursor; 25import android.os.Bundle; 26import android.provider.UserDictionary; 27import android.text.InputType; 28import android.view.ContextMenu; 29import android.view.Menu; 30import android.view.MenuItem; 31import android.view.View; 32import android.view.WindowManager; 33import android.view.ContextMenu.ContextMenuInfo; 34import android.widget.AlphabetIndexer; 35import android.widget.EditText; 36import android.widget.ListAdapter; 37import android.widget.ListView; 38import android.widget.SectionIndexer; 39import android.widget.SimpleCursorAdapter; 40import android.widget.TextView; 41import android.widget.AdapterView.AdapterContextMenuInfo; 42 43import java.util.Locale; 44 45public class UserDictionarySettings extends ListActivity { 46 47 private static final String INSTANCE_KEY_DIALOG_EDITING_WORD = "DIALOG_EDITING_WORD"; 48 private static final String INSTANCE_KEY_ADDED_WORD = "DIALOG_ADDED_WORD"; 49 50 private static final String[] QUERY_PROJECTION = { 51 UserDictionary.Words._ID, UserDictionary.Words.WORD 52 }; 53 54 // Either the locale is empty (means the word is applicable to all locales) 55 // or the word equals our current locale 56 private static final String QUERY_SELECTION = UserDictionary.Words.LOCALE + "=? OR " 57 + UserDictionary.Words.LOCALE + " is null"; 58 59 private static final String DELETE_SELECTION = UserDictionary.Words.WORD + "=?"; 60 61 private static final String EXTRA_WORD = "word"; 62 63 private static final int CONTEXT_MENU_EDIT = Menu.FIRST; 64 private static final int CONTEXT_MENU_DELETE = Menu.FIRST + 1; 65 66 private static final int OPTIONS_MENU_ADD = Menu.FIRST; 67 68 private static final int DIALOG_ADD_OR_EDIT = 0; 69 70 /** The word being edited in the dialog (null means the user is adding a word). */ 71 private String mDialogEditingWord; 72 73 private Cursor mCursor; 74 75 private boolean mAddedWordAlready; 76 private boolean mAutoReturn; 77 78 @Override 79 protected void onCreate(Bundle savedInstanceState) { 80 super.onCreate(savedInstanceState); 81 82 setContentView(R.layout.list_content_with_empty_view); 83 84 mCursor = createCursor(); 85 setListAdapter(createAdapter()); 86 87 TextView emptyView = (TextView) findViewById(R.id.empty); 88 emptyView.setText(R.string.user_dict_settings_empty_text); 89 90 ListView listView = getListView(); 91 listView.setFastScrollEnabled(true); 92 listView.setEmptyView(emptyView); 93 94 registerForContextMenu(listView); 95 } 96 97 @Override 98 protected void onResume() { 99 super.onResume(); 100 if (!mAddedWordAlready 101 && getIntent().getAction().equals("com.android.settings.USER_DICTIONARY_INSERT")) { 102 String word = getIntent().getStringExtra(EXTRA_WORD); 103 mAutoReturn = true; 104 if (word != null) { 105 showAddOrEditDialog(word); 106 } 107 } 108 } 109 @Override 110 protected void onRestoreInstanceState(Bundle state) { 111 super.onRestoreInstanceState(state); 112 mDialogEditingWord = state.getString(INSTANCE_KEY_DIALOG_EDITING_WORD); 113 mAddedWordAlready = state.getBoolean(INSTANCE_KEY_ADDED_WORD, false); 114 } 115 116 @Override 117 protected void onSaveInstanceState(Bundle outState) { 118 super.onSaveInstanceState(outState); 119 outState.putString(INSTANCE_KEY_DIALOG_EDITING_WORD, mDialogEditingWord); 120 outState.putBoolean(INSTANCE_KEY_ADDED_WORD, mAddedWordAlready); 121 } 122 123 private Cursor createCursor() { 124 String currentLocale = Locale.getDefault().toString(); 125 // Case-insensitive sort 126 return managedQuery(UserDictionary.Words.CONTENT_URI, QUERY_PROJECTION, 127 QUERY_SELECTION, new String[] { currentLocale }, 128 "UPPER(" + UserDictionary.Words.WORD + ")"); 129 } 130 131 private ListAdapter createAdapter() { 132 return new MyAdapter(this, 133 android.R.layout.simple_list_item_1, mCursor, 134 new String[] { UserDictionary.Words.WORD }, 135 new int[] { android.R.id.text1 }); 136 } 137 138 @Override 139 protected void onListItemClick(ListView l, View v, int position, long id) { 140 openContextMenu(v); 141 } 142 143 @Override 144 public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { 145 if (!(menuInfo instanceof AdapterContextMenuInfo)) return; 146 147 AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo; 148 menu.setHeaderTitle(getWord(adapterMenuInfo.position)); 149 menu.add(0, CONTEXT_MENU_EDIT, 0, 150 R.string.user_dict_settings_context_menu_edit_title); 151 menu.add(0, CONTEXT_MENU_DELETE, 0, 152 R.string.user_dict_settings_context_menu_delete_title); 153 } 154 155 @Override 156 public boolean onContextItemSelected(MenuItem item) { 157 ContextMenuInfo menuInfo = item.getMenuInfo(); 158 if (!(menuInfo instanceof AdapterContextMenuInfo)) return false; 159 160 AdapterContextMenuInfo adapterMenuInfo = (AdapterContextMenuInfo) menuInfo; 161 String word = getWord(adapterMenuInfo.position); 162 if (word == null) return true; 163 164 switch (item.getItemId()) { 165 case CONTEXT_MENU_DELETE: 166 deleteWord(word); 167 return true; 168 169 case CONTEXT_MENU_EDIT: 170 showAddOrEditDialog(word); 171 return true; 172 } 173 174 return false; 175 } 176 177 @Override 178 public boolean onCreateOptionsMenu(Menu menu) { 179 menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title) 180 .setIcon(R.drawable.ic_menu_add); 181 return true; 182 } 183 184 @Override 185 public boolean onOptionsItemSelected(MenuItem item) { 186 showAddOrEditDialog(null); 187 return true; 188 } 189 190 private void showAddOrEditDialog(String editingWord) { 191 mDialogEditingWord = editingWord; 192 showDialog(DIALOG_ADD_OR_EDIT); 193 } 194 195 private String getWord(int position) { 196 mCursor.moveToPosition(position); 197 // Handle a possible race-condition 198 if (mCursor.isAfterLast()) return null; 199 200 return mCursor.getString( 201 mCursor.getColumnIndexOrThrow(UserDictionary.Words.WORD)); 202 } 203 204 @Override 205 protected Dialog onCreateDialog(int id) { 206 View content = getLayoutInflater().inflate(R.layout.dialog_edittext, null); 207 final EditText editText = (EditText) content.findViewById(R.id.edittext); 208 // No prediction in soft keyboard mode. TODO: Create a better way to disable prediction 209 editText.setInputType(InputType.TYPE_CLASS_TEXT 210 | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); 211 212 AlertDialog dialog = new AlertDialog.Builder(this) 213 .setTitle(mDialogEditingWord != null 214 ? R.string.user_dict_settings_edit_dialog_title 215 : R.string.user_dict_settings_add_dialog_title) 216 .setView(content) 217 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 218 public void onClick(DialogInterface dialog, int which) { 219 onAddOrEditFinished(editText.getText().toString()); 220 if (mAutoReturn) finish(); 221 }}) 222 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 223 public void onClick(DialogInterface dialog, int which) { 224 if (mAutoReturn) finish(); 225 }}) 226 .create(); 227 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | 228 WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 229 return dialog; 230 } 231 232 @Override 233 protected void onPrepareDialog(int id, Dialog d) { 234 AlertDialog dialog = (AlertDialog) d; 235 d.setTitle(mDialogEditingWord != null 236 ? R.string.user_dict_settings_edit_dialog_title 237 : R.string.user_dict_settings_add_dialog_title); 238 EditText editText = (EditText) dialog.findViewById(R.id.edittext); 239 editText.setText(mDialogEditingWord); 240 } 241 242 private void onAddOrEditFinished(String word) { 243 if (mDialogEditingWord != null) { 244 // The user was editing a word, so do a delete/add 245 deleteWord(mDialogEditingWord); 246 } 247 248 // Disallow duplicates 249 deleteWord(word); 250 251 // TODO: present UI for picking whether to add word to all locales, or current. 252 UserDictionary.Words.addWord(this, word.toString(), 253 250, UserDictionary.Words.LOCALE_TYPE_ALL); 254 mCursor.requery(); 255 mAddedWordAlready = true; 256 } 257 258 private void deleteWord(String word) { 259 getContentResolver().delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION, 260 new String[] { word }); 261 } 262 263 private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer { 264 private AlphabetIndexer mIndexer; 265 266 public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { 267 super(context, layout, c, from, to); 268 269 int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD); 270 String alphabet = context.getString(com.android.internal.R.string.fast_scroll_alphabet); 271 mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet); 272 } 273 274 public int getPositionForSection(int section) { 275 return mIndexer.getPositionForSection(section); 276 } 277 278 public int getSectionForPosition(int position) { 279 return mIndexer.getSectionForPosition(position); 280 } 281 282 public Object[] getSections() { 283 return mIndexer.getSections(); 284 } 285 } 286} 287