UserDictionarySettings.java revision 985f5efc8278e1a5c2170c3aba354a4c9367b741
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 163 switch (item.getItemId()) { 164 case CONTEXT_MENU_DELETE: 165 deleteWord(word); 166 return true; 167 168 case CONTEXT_MENU_EDIT: 169 showAddOrEditDialog(word); 170 return true; 171 } 172 173 return false; 174 } 175 176 @Override 177 public boolean onCreateOptionsMenu(Menu menu) { 178 menu.add(0, OPTIONS_MENU_ADD, 0, R.string.user_dict_settings_add_menu_title) 179 .setIcon(R.drawable.ic_menu_add); 180 return true; 181 } 182 183 @Override 184 public boolean onOptionsItemSelected(MenuItem item) { 185 showAddOrEditDialog(null); 186 return true; 187 } 188 189 private void showAddOrEditDialog(String editingWord) { 190 mDialogEditingWord = editingWord; 191 showDialog(DIALOG_ADD_OR_EDIT); 192 } 193 194 private String getWord(int position) { 195 mCursor.moveToPosition(position); 196 return mCursor.getString( 197 mCursor.getColumnIndexOrThrow(UserDictionary.Words.WORD)); 198 } 199 200 @Override 201 protected Dialog onCreateDialog(int id) { 202 View content = getLayoutInflater().inflate(R.layout.dialog_edittext, null); 203 final EditText editText = (EditText) content.findViewById(R.id.edittext); 204 // No prediction in soft keyboard mode. TODO: Create a better way to disable prediction 205 editText.setInputType(InputType.TYPE_CLASS_TEXT 206 | InputType.TYPE_TEXT_FLAG_AUTO_COMPLETE); 207 208 AlertDialog dialog = new AlertDialog.Builder(this) 209 .setTitle(mDialogEditingWord != null 210 ? R.string.user_dict_settings_edit_dialog_title 211 : R.string.user_dict_settings_add_dialog_title) 212 .setView(content) 213 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { 214 public void onClick(DialogInterface dialog, int which) { 215 onAddOrEditFinished(editText.getText().toString()); 216 if (mAutoReturn) finish(); 217 }}) 218 .setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() { 219 public void onClick(DialogInterface dialog, int which) { 220 if (mAutoReturn) finish(); 221 }}) 222 .create(); 223 dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | 224 WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE); 225 return dialog; 226 } 227 228 @Override 229 protected void onPrepareDialog(int id, Dialog d) { 230 AlertDialog dialog = (AlertDialog) d; 231 d.setTitle(mDialogEditingWord != null 232 ? R.string.user_dict_settings_edit_dialog_title 233 : R.string.user_dict_settings_add_dialog_title); 234 EditText editText = (EditText) dialog.findViewById(R.id.edittext); 235 editText.setText(mDialogEditingWord); 236 } 237 238 private void onAddOrEditFinished(String word) { 239 if (mDialogEditingWord != null) { 240 // The user was editing a word, so do a delete/add 241 deleteWord(mDialogEditingWord); 242 } 243 244 // Disallow duplicates 245 deleteWord(word); 246 247 // TODO: present UI for picking whether to add word to all locales, or current. 248 UserDictionary.Words.addWord(this, word.toString(), 249 250, UserDictionary.Words.LOCALE_TYPE_ALL); 250 mCursor.requery(); 251 mAddedWordAlready = true; 252 } 253 254 private void deleteWord(String word) { 255 getContentResolver().delete(UserDictionary.Words.CONTENT_URI, DELETE_SELECTION, 256 new String[] { word }); 257 } 258 259 private static class MyAdapter extends SimpleCursorAdapter implements SectionIndexer { 260 private AlphabetIndexer mIndexer; 261 262 public MyAdapter(Context context, int layout, Cursor c, String[] from, int[] to) { 263 super(context, layout, c, from, to); 264 265 int wordColIndex = c.getColumnIndexOrThrow(UserDictionary.Words.WORD); 266 String alphabet = context.getString(com.android.internal.R.string.fast_scroll_alphabet); 267 mIndexer = new AlphabetIndexer(c, wordColIndex, alphabet); 268 } 269 270 public int getPositionForSection(int section) { 271 return mIndexer.getPositionForSection(section); 272 } 273 274 public int getSectionForPosition(int position) { 275 return mIndexer.getSectionForPosition(position); 276 } 277 278 public Object[] getSections() { 279 return mIndexer.getSections(); 280 } 281 } 282} 283